blob: 511b87968770b84e5a912251d9837a7fe6dfba82 [file] [log] [blame]
/*
* 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: bharathbhushan@google.com (Bharath Bhushan Kowshik Raghupathi)
#include "net/instaweb/rewriter/public/critical_line_info_finder.h"
#include <memory>
#include "net/instaweb/rewriter/critical_line_info.pb.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/property_cache.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
namespace net_instaweb {
const char CriticalLineInfoFinder::kCriticalLineInfoPropertyName[] =
"critical_line_info";
CriticalLineInfoFinder::CriticalLineInfoFinder(
const PropertyCache::Cohort* cohort)
: cohort_(cohort) {}
CriticalLineInfoFinder::~CriticalLineInfoFinder() {}
const CriticalLineInfo* CriticalLineInfoFinder::GetCriticalLine(
RewriteDriver* driver) {
UpdateInDriver(driver);
return driver->critical_line_info();
}
// Critical line configuration can come from the following sources and will be
// given preference in order:
// - Http header kXPsaSplitConfig
// - property cache value
// - domain configuration options
void CriticalLineInfoFinder::UpdateInDriver(RewriteDriver* driver) {
if (driver->critical_line_info() != NULL) {
return;
}
GoogleString critical_line_config;
const RequestHeaders* request_headers = driver->request_headers();
if (request_headers != NULL) {
const char* header = request_headers->Lookup1(
HttpAttributes::kXPsaSplitConfig);
if (header != NULL) {
critical_line_config = header;
}
}
if (critical_line_config.empty()) {
PropertyCacheDecodeResult pcache_status;
scoped_ptr<CriticalLineInfo> critical_line_info(
DecodeFromPropertyCache<CriticalLineInfo>(
driver, cohort_, kCriticalLineInfoPropertyName,
driver->options()->finder_properties_cache_expiration_time_ms(),
&pcache_status));
switch (pcache_status) {
case kPropertyCacheDecodeNotFound:
driver->InfoHere("Critical line info not found in cache");
break;
case kPropertyCacheDecodeExpired:
driver->InfoHere("Critical line info cache entry expired");
break;
case kPropertyCacheDecodeParseError:
driver->WarningHere("Unable to parse Critical line info PropertyValue");
break;
case kPropertyCacheDecodeOk:
break;
}
driver->set_critical_line_info(critical_line_info.release());
if (driver->critical_line_info() != NULL) {
return;
}
// Pcache does not have the config. Pick it up from the domain config.
critical_line_config = driver->options()->critical_line_config();
}
if (!critical_line_config.empty()) {
// The critical_line_config string has the following format:
// xpath1_start:xpath1_end,xpath2_start:xpath2_end,...
// The xpath_ends are optional.
scoped_ptr<CriticalLineInfo> critical_line_info(new CriticalLineInfo);
StringPieceVector xpaths;
SplitStringPieceToVector(critical_line_config, ",", &xpaths, true);
for (int i = 0, n = xpaths.size(); i < n; ++i) {
StringPieceVector xpath_pair;
SplitStringPieceToVector(xpaths[i], ":", &xpath_pair, true);
// If a particular panel specification has less than one or more than two
// parts, we ignore the entire config.
if (!(xpath_pair.size() == 1 || xpath_pair.size() == 2)) {
driver->WarningHere("Unable to parse Critical line config");
return;
}
Panel* panel = critical_line_info->add_panels();
panel->set_start_xpath(xpath_pair[0].data(), xpath_pair[0].length());
if (xpath_pair.size() == 2) {
panel->set_end_marker_xpath(
xpath_pair[1].data(), xpath_pair[1].length());
}
}
driver->set_critical_line_info(critical_line_info.release());
return;
}
}
} // namespace net_instaweb