| /* |
| * Copyright 2013 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Author: jud@google.com (Jud Porter) |
| |
| #include "net/instaweb/rewriter/public/beacon_critical_line_info_finder.h" |
| |
| #include <set> |
| |
| #include "base/logging.h" |
| #include "net/instaweb/rewriter/critical_keys.pb.h" |
| #include "net/instaweb/rewriter/critical_line_info.pb.h" |
| #include "net/instaweb/rewriter/public/critical_finder_support_util.h" |
| #include "net/instaweb/rewriter/public/property_cache_util.h" |
| #include "net/instaweb/rewriter/public/rewrite_driver.h" |
| #include "net/instaweb/rewriter/public/rewrite_options.h" |
| #include "net/instaweb/util/public/fallback_property_page.h" |
| #include "pagespeed/kernel/base/scoped_ptr.h" |
| |
| namespace net_instaweb { |
| |
| class Timer; |
| |
| const char BeaconCriticalLineInfoFinder::kBeaconCriticalLineInfoPropertyName[] = |
| "beacon_critical_line_info"; |
| |
| BeaconCriticalLineInfoFinder::BeaconCriticalLineInfoFinder( |
| const PropertyCache::Cohort* cohort, NonceGenerator* nonce_generator) |
| : CriticalLineInfoFinder(cohort), nonce_generator_(nonce_generator) {} |
| |
| BeaconCriticalLineInfoFinder::~BeaconCriticalLineInfoFinder() {} |
| |
| void BeaconCriticalLineInfoFinder::WriteXPathsToPropertyCacheFromBeacon( |
| const StringSet& xpaths_set, StringPiece nonce, const PropertyCache* cache, |
| const PropertyCache::Cohort* cohort, AbstractPropertyPage* page, |
| MessageHandler* message_handler, Timer* timer) { |
| WriteCriticalKeysToPropertyCache(xpaths_set, nonce, kDefaultSupportInterval, |
| /* We merge prior result w/o requiring |
| prior support */ |
| kNoRequirementsOnPriorResult, |
| kBeaconCriticalLineInfoPropertyName, cache, |
| cohort, page, message_handler, timer); |
| } |
| |
| BeaconMetadata BeaconCriticalLineInfoFinder::PrepareForBeaconInsertion( |
| RewriteDriver* driver) { |
| BeaconMetadata metadata; |
| UpdateInDriver(driver); |
| const StringSet empty; |
| CriticalKeys* proto = driver->beacon_critical_line_info(); |
| // If an explicit xpath config has been set, we don't need to beacon. In that |
| // case, beacon_critical_line_info() will be NULL. |
| if (proto == NULL) { |
| metadata.status = kDoNotBeacon; |
| return metadata; |
| } |
| // Call the generic version of PrepareForBeaconInsertion in |
| // critical_finder_support_util to decide if we should beacon. |
| net_instaweb::PrepareForBeaconInsertionHelper( |
| proto, nonce_generator_, driver, |
| false /* using_candidate_key_detection */, &metadata); |
| if (metadata.status != kDoNotBeacon) { |
| DCHECK(cohort() != NULL); |
| UpdateInPropertyCache(*proto, cohort(), kBeaconCriticalLineInfoPropertyName, |
| true /* write_cohort */, |
| driver->fallback_property_page()); |
| } |
| return metadata; |
| } |
| |
| void BeaconCriticalLineInfoFinder::UpdateInDriver(RewriteDriver* driver) { |
| CHECK(driver != NULL); |
| // The parent class's UpdateInDriver will populate critical_line_info if it |
| // was configured explicitly, through a ModPagespeedCriticalLineConfig option |
| // for instance. |
| CriticalLineInfoFinder::UpdateInDriver(driver); |
| |
| // Don't recompute the critical line info if it has already been determined. |
| if (driver->critical_line_info() != NULL || |
| driver->beacon_critical_line_info() != NULL) { |
| return; |
| } |
| |
| // Setup default values if the pcache isn't configured. |
| if (driver->property_page() == NULL || cohort() == NULL) { |
| driver->set_critical_line_info(NULL); |
| driver->set_beacon_critical_line_info(new CriticalKeys); |
| return; |
| } |
| |
| // The split config was not explicitly set, so check to see if we have a |
| // property cache entry from a beacon, and if so, populate critical_line_info |
| // with it. |
| PropertyCacheDecodeResult result; |
| |
| scoped_ptr<CriticalKeys> critical_keys(DecodeFromPropertyCache<CriticalKeys>( |
| driver, cohort(), kBeaconCriticalLineInfoPropertyName, |
| driver->options()->finder_properties_cache_expiration_time_ms(), |
| &result)); |
| switch (result) { |
| case kPropertyCacheDecodeNotFound: |
| driver->InfoHere("Beacon critical line info not found in cache"); |
| break; |
| case kPropertyCacheDecodeExpired: |
| driver->InfoHere("Beacon critical line info cache entry expired"); |
| break; |
| case kPropertyCacheDecodeParseError: |
| driver->WarningHere( |
| "Unable to parse beacon critical line info PropertyValue"); |
| break; |
| case kPropertyCacheDecodeOk: |
| break; |
| } |
| |
| if (critical_keys == NULL) { |
| critical_keys.reset(new CriticalKeys); |
| } |
| |
| StringSet keys; |
| GetCriticalKeysFromProto(0 /* support_percentage */, *critical_keys, &keys); |
| |
| // If there were critical keys in the pcache, populate the critical_line_info |
| // with them. |
| if (!keys.empty()) { |
| scoped_ptr<CriticalLineInfo> critical_line_info(new CriticalLineInfo); |
| for (StringSet::const_iterator it = keys.begin(); it != keys.end(); ++it) { |
| Panel* panel = critical_line_info->add_panels(); |
| panel->set_start_xpath(*it); |
| } |
| driver->set_critical_line_info(critical_line_info.release()); |
| } else { |
| driver->set_critical_line_info(NULL); |
| } |
| |
| driver->set_beacon_critical_line_info(critical_keys.release()); |
| } |
| |
| } // namespace net_instaweb |