| /* |
| * Copyright 2012 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_images_finder.h" |
| |
| #include "base/logging.h" |
| #include "net/instaweb/rewriter/critical_images.pb.h" |
| #include "net/instaweb/rewriter/critical_keys.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_driver_factory.h" |
| #include "net/instaweb/rewriter/public/rewrite_options.h" |
| #include "net/instaweb/rewriter/public/server_context.h" |
| #include "net/instaweb/util/public/fallback_property_page.h" |
| #include "pagespeed/kernel/base/basictypes.h" |
| #include "pagespeed/kernel/base/statistics.h" |
| #include "pagespeed/kernel/base/string.h" |
| #include "pagespeed/kernel/base/string_hash.h" |
| #include "pagespeed/kernel/base/timer.h" |
| |
| namespace net_instaweb { |
| |
| BeaconCriticalImagesFinder::BeaconCriticalImagesFinder( |
| const PropertyCache::Cohort* cohort, NonceGenerator* nonce_generator, |
| Statistics* stats) |
| : CriticalImagesFinder(cohort, stats), nonce_generator_(nonce_generator) {} |
| |
| BeaconCriticalImagesFinder::~BeaconCriticalImagesFinder() { |
| } |
| |
| bool BeaconCriticalImagesFinder::UpdateCriticalImagesCacheEntry( |
| const StringSet* html_critical_images_set, |
| const StringSet* css_critical_images_set, |
| const RenderedImages* rendered_images_set, |
| const StringPiece& nonce, |
| const PropertyCache::Cohort* cohort, |
| AbstractPropertyPage* page, Timer* timer) { |
| DCHECK(cohort != NULL); |
| DCHECK(page != NULL); |
| PropertyValue* property_value = |
| page->GetProperty(cohort, kCriticalImagesPropertyName); |
| if (property_value == NULL) { |
| return false; |
| } |
| CriticalImages critical_images; |
| if (!PopulateCriticalImagesFromPropertyValue( |
| property_value, &critical_images)) { |
| return false; |
| } |
| if (!ValidateAndExpireNonce( |
| timer->NowMs(), nonce, |
| critical_images.mutable_html_critical_image_support())) { |
| return false; |
| } |
| return CriticalImagesFinder::UpdateAndWriteBackCriticalImagesCacheEntry( |
| html_critical_images_set, css_critical_images_set, rendered_images_set, |
| kBeaconImageSupportInterval, cohort, page, &critical_images); |
| } |
| |
| GoogleString BeaconCriticalImagesFinder::GetKeyForUrl(StringPiece url) { |
| unsigned int hash_val = |
| HashString<CasePreserve, unsigned int>(url.data(), url.size()); |
| return UintToString(hash_val); |
| } |
| |
| CriticalImagesFinder::Availability BeaconCriticalImagesFinder::Available( |
| RewriteDriver* driver) { |
| if (driver->options()->critical_images_beacon_enabled() && |
| driver->server_context()->factory()->UseBeaconResultsInFilters()) { |
| return CriticalImagesFinder::Available(driver); |
| } else { |
| return CriticalImagesFinder::kDisabled; |
| } |
| } |
| |
| bool BeaconCriticalImagesFinder::ShouldBeacon(RewriteDriver* driver) { |
| UpdateCriticalImagesSetInDriver(driver); |
| int64 next_beacon_timestamp_ms = 0; |
| CriticalImagesInfo* critical_images = driver->critical_images_info(); |
| DCHECK(critical_images != NULL) |
| << "UpdateCriticalImagesSetInDriver must be called before ShouldBeacon"; |
| if (critical_images != NULL) { |
| const CriticalImages& proto = critical_images->proto; |
| if (proto.has_html_critical_image_support()) { |
| next_beacon_timestamp_ms = |
| proto.html_critical_image_support().next_beacon_timestamp_ms(); |
| } |
| } |
| return net_instaweb::ShouldBeacon(next_beacon_timestamp_ms, *driver); |
| } |
| |
| BeaconMetadata BeaconCriticalImagesFinder::PrepareForBeaconInsertion( |
| RewriteDriver* driver) { |
| BeaconMetadata metadata; |
| UpdateCriticalImagesSetInDriver(driver); |
| CriticalImages& proto = driver->critical_images_info()->proto; |
| // We store the metadata about last beacon time and nonce generation in the |
| // html_critical_image_support field of the CriticalImages proto. |
| net_instaweb::PrepareForBeaconInsertionHelper( |
| proto.mutable_html_critical_image_support(), nonce_generator_, driver, |
| true /* using_candidate_key_detection */, &metadata); |
| if (metadata.status != kDoNotBeacon) { |
| UpdateInPropertyCache(proto, cohort(), kCriticalImagesPropertyName, |
| true /* write_cohort */, |
| driver->fallback_property_page()); |
| } |
| return metadata; |
| } |
| |
| void BeaconCriticalImagesFinder::UpdateCandidateImagesForBeaconing( |
| const StringSet& images, RewriteDriver* driver, bool beaconing) { |
| UpdateCriticalImagesSetInDriver(driver); |
| CriticalImages& proto = driver->critical_images_info()->proto; |
| if (::net_instaweb::UpdateCandidateKeys( |
| images, proto.mutable_html_critical_image_support(), !beaconing)) { |
| UpdateInPropertyCache(proto, cohort(), kCriticalImagesPropertyName, |
| true /* write_cohort */, |
| driver->fallback_property_page()); |
| } |
| } |
| |
| } // namespace net_instaweb |