blob: 3956818734474f1ce9bb254dc5c214d2ca7d63b9 [file] [log] [blame]
/*
* Copyright 2010 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: jmarantz@google.com (Joshua Marantz)
#ifndef NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_OPTIONS_H_
#define NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_OPTIONS_H_
#include <bitset>
#include <cstddef>
#include <map>
#include <set>
#include <utility>
#include <vector>
#include "base/logging.h"
#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/experiment_util.h"
#include "net/instaweb/rewriter/public/file_load_policy.h"
#include "net/instaweb/rewriter/public/javascript_library_identification.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/dense_hash_map.h"
#include "pagespeed/kernel/base/enum_set.h"
#include "pagespeed/kernel/base/fast_wildcard_group.h"
#include "pagespeed/kernel/base/gtest_prod.h"
#include "pagespeed/kernel/base/hasher.h"
#include "pagespeed/kernel/base/md5_hasher.h"
#include "pagespeed/kernel/base/proto_util.h"
#include "pagespeed/kernel/base/rde_hash_map.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/sha1_signature.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_hash.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_annotations.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/base/wildcard.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/semantic_type.h"
#include "pagespeed/kernel/http/user_agent_matcher.h"
#include "pagespeed/kernel/util/copy_on_write.h"
namespace net_instaweb {
class MessageHandler;
class PurgeSet;
class RequestHeaders;
struct HttpOptions;
// Defines a set of customizations that can be applied to any Rewrite. There
// are multiple categories of customizations:
// - filter sets (controllable individually or by level)
// - options (arbitrarily typed variables)
// - domain customization (see DomainLawyer class).
// - FileLoadPolicy (enables reading resources as files from the file system)
// RewriteOptions can be specified in several ways, forming a hierarchy:
// - Globally for a process
// - Customized per server (e.g. Apache VirtualHost)
// - Customized at Directory level (e.g. Apache <Directory> or .htaccess)
// - Tuned at the request-level (e.g. via request-headers or query-params).
// The hierarchy is implemented via Merging.
//
// The options are themselves a complex system. Many Option objects are
// instantiated for each RewriteOptions instance. RewriteOptions can be
// constructed and destroyed multiple times per request so to reduce
// this cost, the static aspects of Options are factored out into
// Properties, which are intialized once per process via
// RewriteOptions::Initialize. Subclasses may also add new Properties
// and so property-list-merging takes place at Initialization time.
class RewriteOptions {
protected:
// These being protected is against the style guide but necessary to keep
// them protected while still being used by the Option class hierarchy.
// Note that iwyu.py incorrectly complains about the template classes but
// scripts/iwyu manually removes the warning.
class PropertyBase;
template<class ValueType> class Property;
template<class RewriteOptionsSubclass, class OptionClass> class PropertyLeaf;
public:
// If you add or remove anything from this list, you must also update the
// kFilterVectorStaticInitializer array in rewrite_options.cc. If you add
// an image-related filter or a css-related filter, you must add it to the
// kRelatedFilters array in image_rewrite_filter.cc and/or css_filter.cc
//
// Each filter added here should go into at least one of the filter-arrays
// in rewrite_options.cc, even if it's just kDangerousFilterSet.
//
// Filters that can improve bandwidth but have basically zero risk
// of breaking pages should be added to
// kOptimizeForBandwidthFilterSet. Filters with relatively low risk
// should be added to kCoreFilterSet.
enum Filter {
kAddBaseTag, // Update kFirstFilter if you add something before this.
kAddHead,
kAddIds,
kAddInstrumentation,
kComputeStatistics,
kCachePartialHtml,
kCanonicalizeJavascriptLibraries,
kCollapseWhitespace,
kCollectFlushEarlyContentFilter,
kCombineCss,
kCombineHeads,
kCombineJavascript,
kComputeCriticalCss,
kComputeVisibleText,
kConvertGifToPng,
kConvertJpegToProgressive,
kConvertJpegToWebp,
kConvertMetaTags,
kConvertPngToJpeg,
kConvertToWebpAnimated,
kConvertToWebpLossless,
kDebug,
kDecodeRewrittenUrls,
kDedupInlinedImages,
kDeferIframe,
kDeferJavascript,
kDelayImages,
kDeterministicJs,
kDisableJavascript,
kDivStructure,
kElideAttributes,
kExperimentCollectMobImageInfo,
kExperimentSpdy, // Temporary and will be removed soon.
kExplicitCloseTags,
kExtendCacheCss,
kExtendCacheImages,
kExtendCachePdfs,
kExtendCacheScripts,
kFallbackRewriteCssUrls,
kFixReflows,
kFlattenCssImports,
kFlushSubresources,
kHandleNoscriptRedirect,
kHtmlWriterFilter,
kIncludeJsSourceMaps,
kInlineCss,
kInlineGoogleFontCss,
kInlineImages,
kInlineImportToLink,
kInlineJavascript,
kInPlaceOptimizeForBrowser,
kInsertDnsPrefetch,
kInsertGA,
kInsertImageDimensions,
kJpegSubsampling,
kLazyloadImages,
kLeftTrimUrls,
kLocalStorageCache,
kMakeGoogleAnalyticsAsync,
kMakeShowAdsAsync,
kMobilize,
kMobilizePrecompute, // TODO(jud): This is unused, remove it.
kMoveCssAboveScripts,
kMoveCssToHead,
kOutlineCss,
kOutlineJavascript,
kPedantic,
kPrioritizeCriticalCss,
kRecompressJpeg,
kRecompressPng,
kRecompressWebp,
kRemoveComments,
kRemoveQuotes,
kResizeImages,
kResizeMobileImages,
kResizeToRenderedImageDimensions,
kResponsiveImages,
kResponsiveImagesZoom,
kRewriteCss,
kRewriteDomains,
kRewriteJavascriptExternal,
kRewriteJavascriptInline,
kRewriteStyleAttributes,
kRewriteStyleAttributesWithUrl,
kServeDeprecationNotice,
kSplitHtml,
kSplitHtmlHelper,
kSpriteImages,
kStripImageColorProfile,
kStripImageMetaData,
kStripNonCacheable,
kStripScripts,
kEndOfFilters
};
enum EnabledEnum {
// Don't optimize HTML. Do serve .pagespeed. Can be overridden via query
// param.
kEnabledOff,
// Pagespeed runs normally. Can be overridden via query param.
kEnabledOn,
// Completely passive. Do not serve .pagespeed. Return from handlers
// immediately. Cannot be overridden via query param.
kEnabledUnplugged,
};
// Any new Option added should have a corresponding name here that must be
// passed in when Add*Property is called in AddProperties(). You must also
// update the LookupOptionByNameTest method in rewrite_options_test.cc. If
// you add an image-related option or css-related option you must also add
// it to the kRelatedOptions array in image_rewrite_filter.cc and/or
// css_filter.cc.
static const char kAcceptInvalidSignatures[];
static const char kAccessControlAllowOrigins[];
static const char kAddOptionsToUrls[];
static const char kAllowLoggingUrlsInLogRecord[];
static const char kAllowOptionsToBeSetByCookies[];
static const char kAllowVaryOn[];
static const char kAlwaysMobilize[];
static const char kAlwaysRewriteCss[];
static const char kAnalyticsID[];
static const char kAvoidRenamingIntrospectiveJavascript[];
static const char kAwaitPcacheLookup[];
static const char kBeaconReinstrumentTimeSec[];
static const char kBeaconUrl[];
static const char kBlinkMaxHtmlSizeRewritable[];
static const char kCacheFragment[];
static const char kCacheSmallImagesUnrewritten[];
static const char kClientDomainRewrite[];
static const char kCombineAcrossPaths[];
static const char kContentExperimentID[];
static const char kContentExperimentVariantID[];
static const char kCriticalImagesBeaconEnabled[];
static const char kCriticalLineConfig[];
static const char kCssFlattenMaxBytes[];
static const char kCssImageInlineMaxBytes[];
static const char kCssInlineMaxBytes[];
static const char kCssOutlineMinBytes[];
static const char kCssPreserveURLs[];
static const char kDefaultCacheHtml[];
static const char kDisableBackgroundFetchesForBots[];
static const char kDisableRewriteOnNoTransform[];
static const char kDistributeFetches[];
static const char kDistributedRewriteKey[];
static const char kDistributedRewriteServers[];
static const char kDistributedRewriteTimeoutMs[];
static const char kDomainRewriteCookies[];
static const char kDomainRewriteHyperlinks[];
static const char kDomainShardCount[];
static const char kDownstreamCachePurgeMethod[];
static const char kDownstreamCacheRebeaconingKey[];
static const char kDownstreamCacheRewrittenPercentageThreshold[];
static const char kEnableAggressiveRewritersForMobile[];
static const char kEnableBlinkHtmlChangeDetection[];
static const char kEnableBlinkHtmlChangeDetectionLogging[];
static const char kEnableCachePurge[];
static const char kEnableDeferJsExperimental[];
static const char kEnableExtendedInstrumentation[];
static const char kEnableFlushEarlyCriticalCss[];
static const char kEnableLazyLoadHighResImages[];
static const char kEnablePrioritizingScripts[];
static const char kEnabled[];
static const char kEnrollExperiment[];
static const char kExperimentCookieDurationMs[];
static const char kExperimentSlot[];
static const char kFetcherTimeOutMs[];
static const char kFinderPropertiesCacheExpirationTimeMs[];
static const char kFinderPropertiesCacheRefreshTimeMs[];
static const char kFlushBufferLimitBytes[];
static const char kFlushHtml[];
static const char kFlushMoreResourcesEarlyIfTimePermits[];
static const char kGoogleFontCssInlineMaxBytes[];
static const char kForbidAllDisabledFilters[];
static const char kHideRefererUsingMeta[];
static const char kHttpCacheCompressionLevel[];
static const char kIdleFlushTimeMs[];
static const char kImageInlineMaxBytes[];
// TODO(huibao): Unify terminology for image rewrites. For example,
// kImageJpeg*Quality might be renamed to kImageJpegQuality.
static const char kImageJpegNumProgressiveScans[];
static const char kImageJpegNumProgressiveScansForSmallScreens[];
static const char kImageJpegQualityForSaveData[];
static const char kImageJpegRecompressionQuality[];
static const char kImageJpegRecompressionQualityForSmallScreens[];
static const char kImageLimitOptimizedPercent[];
static const char kImageLimitRenderedAreaPercent[];
static const char kImageLimitResizeAreaPercent[];
static const char kImageMaxRewritesAtOnce[];
static const char kImagePreserveURLs[];
static const char kImageRecompressionQuality[];
static const char kImageResolutionLimitBytes[];
static const char kImageWebpQualityForSaveData[];
static const char kImageWebpRecompressionQuality[];
static const char kImageWebpRecompressionQualityForSmallScreens[];
static const char kImageWebpAnimatedRecompressionQuality[];
static const char kImageWebpTimeoutMs[];
static const char kImplicitCacheTtlMs[];
static const char kIncreaseSpeedTracking[];
static const char kInlineOnlyCriticalImages[];
static const char kInPlacePreemptiveRewriteCss[];
static const char kInPlacePreemptiveRewriteCssImages[];
static const char kInPlacePreemptiveRewriteImages[];
static const char kInPlacePreemptiveRewriteJavascript[];
static const char kInPlaceResourceOptimization[];
static const char kInPlaceRewriteDeadlineMs[];
static const char kInPlaceWaitForOptimized[];
static const char kJsInlineMaxBytes[];
static const char kJsOutlineMinBytes[];
static const char kJsPreserveURLs[];
static const char kLazyloadImagesAfterOnload[];
static const char kLazyloadImagesBlankUrl[];
static const char kLoadFromFileCacheTtlMs[];
static const char kLogBackgroundRewrite[];
static const char kLogMobilizationSamples[];
static const char kLogRewriteTiming[];
static const char kLogUrlIndices[];
static const char kLowercaseHtmlNames[];
static const char kMaxCacheableResponseContentLength[];
static const char kMaxCombinedCssBytes[];
static const char kMaxCombinedJsBytes[];
static const char kMaxHtmlCacheTimeMs[];
static const char kMaxHtmlParseBytes[];
static const char kMaxImageBytesForWebpInCss[];
static const char kMaxImageSizeLowResolutionBytes[];
static const char kMaxInlinedPreviewImagesIndex[];
static const char kMaxLowResImageSizeBytes[];
static const char kMaxLowResToHighResImageSizePercentage[];
static const char kMaxPrefetchJsElements[];
static const char kMaxRewriteInfoLogSize[];
static const char kMaxUrlSegmentSize[];
static const char kMaxUrlSize[];
static const char kMetadataCacheStalenessThresholdMs[];
static const char kMinCacheTtlMs[];
static const char kMinImageSizeLowResolutionBytes[];
static const char kMinResourceCacheTimeToRewriteMs[];
static const char kMobBeaconCategory[];
static const char kMobBeaconUrl[];
static const char kMobMapLocation[];
static const char kMobPhoneNumber[];
static const char kMobConversionId[];
static const char kMobMapConversionLabel[];
static const char kMobPhoneConversionLabel[];
static const char kMobConfig[];
static const char kMobIframe[];
static const char kMobIframeDisable[];
static const char kMobIframeViewport[];
static const char kMobLayout[];
static const char kMobNav[];
static const char kMobLabeledMode[];
static const char kMobNavClasses[];
static const char kMobStatic[];
static const char kMobTheme[];
static const char kModifyCachingHeaders[];
static const char kNoop[];
static const char kNoTransformOptimizedImages[];
static const char kNonCacheablesForCachePartialHtml[];
static const char kObliviousPagespeedUrls[];
static const char kOptionCookiesDurationMs[];
static const char kOverrideCachingTtlMs[];
static const char kPreserveSubresourceHints[];
static const char kPreserveUrlRelativity[];
static const char kPrivateNotVaryForIE[];
static const char kProactiveResourceFreshening[];
static const char kProactivelyFreshenUserFacingRequest[];
static const char kProgressiveJpegMinBytes[];
static const char kPubliclyCacheMismatchedHashesExperimental[];
static const char kRejectBlacklistedStatusCode[];
static const char kRejectBlacklisted[];
static const char kRemoteConfigurationTimeoutMs[];
static const char kRemoteConfigurationUrl[];
static const char kReportUnloadTime[];
static const char kRequestOptionOverride[];
static const char kRespectVary[];
static const char kRespectXForwardedProto[];
static const char kResponsiveImageDensities[];
static const char kRewriteDeadlineMs[];
static const char kRewriteLevel[];
static const char kRewriteRandomDropPercentage[];
static const char kRewriteUncacheableResources[];
static const char kRunningExperiment[];
static const char kServeGhostClickBusterWithSplitHtml[];
static const char kServeSplitHtmlInTwoChunks[];
static const char kServeStaleIfFetchError[];
static const char kServeStaleWhileRevalidateThresholdSec[];
static const char kServeXhrAccessControlHeaders[];
static const char kStickyQueryParameters[];
static const char kSupportNoScriptEnabled[];
static const char kTestOnlyPrioritizeCriticalCssDontApplyOriginalCss[];
static const char kUrlSigningKey[];
static const char kUseAnalyticsJs[];
static const char kUseBlankImageForInlinePreview[];
static const char kUseExperimentalJsMinifier[];
static const char kUseFallbackPropertyCacheValues[];
static const char kUseImageScanlineApi[];
static const char kUseSelectorsForCriticalCss[];
static const char kUseSmartDiffInBlink[];
static const char kXModPagespeedHeaderValue[];
static const char kXPsaBlockingRewrite[];
// Options that require special handling, e.g. non-scalar values
static const char kAllow[];
static const char kBlockingRewriteRefererUrls[];
static const char kDisableFilters[];
static const char kDisallow[];
static const char kDistributableFilters[]; // For experimentation.
static const char kDomain[];
static const char kDownstreamCachePurgeLocationPrefix[];
static const char kEnableFilters[];
static const char kExperimentVariable[];
static const char kExperimentSpec[];
static const char kForbidFilters[];
static const char kInlineResourcesWithoutExplicitAuthorization[];
static const char kRetainComment[];
// 2-argument ones:
static const char kCustomFetchHeader[];
static const char kLoadFromFile[];
static const char kLoadFromFileMatch[];
static const char kLoadFromFileRule[];
static const char kLoadFromFileRuleMatch[];
static const char kMapOriginDomain[];
static const char kMapProxyDomain[];
static const char kMapRewriteDomain[];
static const char kShardDomain[];
// 3-argument ones:
static const char kLibrary[];
static const char kUrlValuedAttribute[];
// apache/ or system/ specific:
// TODO(matterbury): move these to system_rewrite_options.cc?
static const char kCacheFlushFilename[];
static const char kCacheFlushPollIntervalSec[];
static const char kCompressMetadataCache[];
static const char kFetcherProxy[];
static const char kFetchFromModSpdy[];
static const char kFetchHttps[];
static const char kFileCacheCleanInodeLimit[];
static const char kFileCacheCleanIntervalMs[];
static const char kFileCacheCleanSizeKb[];
static const char kFileCachePath[];
static const char kLogDir[];
static const char kLruCacheByteLimit[];
static const char kLruCacheKbPerProcess[];
static const char kMemcachedServers[];
static const char kMemcachedThreads[];
static const char kMemcachedTimeoutUs[];
static const char kProxySuffix[];
static const char kRateLimitBackgroundFetches[];
static const char kServeWebpToAnyAgent[];
static const char kSlurpDirectory[];
static const char kSlurpFlushLimit[];
static const char kSlurpReadOnly[];
static const char kSslCertDirectory[];
static const char kSslCertFile[];
static const char kStatisticsEnabled[];
static const char kStatisticsLoggingChartsCSS[];
static const char kStatisticsLoggingChartsJS[];
static const char kStatisticsLoggingEnabled[];
static const char kStatisticsLoggingIntervalMs[];
static const char kStatisticsLoggingMaxFileSizeKb[];
static const char kTestProxy[];
static const char kTestProxySlurp[];
static const char kUseSharedMemLocking[];
// The option name you have when you don't have an option name.
static const char kNullOption[];
// We allow query params to be set in custom beacon URLs through the
// ModPagespeedBeaconUrl option, but we don't use those query params for
// validation of a beacon URL. The http and https fields should be the URLs
// that beacon responses are to be sent to, while http_in and https_in are the
// fields that should be validated on the server to verify if a URL is a
// beacon request (they are just a precomputation of the corresponding
// outbound URL with query params stripped).
struct BeaconUrl {
GoogleString http;
GoogleString https;
GoogleString http_in;
GoogleString https_in;
};
struct Color {
unsigned char r;
unsigned char g;
unsigned char b;
};
struct MobTheme {
Color background_color;
Color foreground_color;
GoogleString logo_url;
};
struct NameValue {
NameValue(StringPiece name_in, StringPiece value_in) {
name_in.CopyToString(&name);
value_in.CopyToString(&value);
}
GoogleString name;
GoogleString value;
};
// We only create this class so that we get the correct ParseFromString()
// version for parsing densities.
class ResponsiveDensities : public std::vector<double> {
};
class AllowVaryOn {
public:
// Strings for display.
static const char kNoneString[];
static const char kAutoString[];
AllowVaryOn() :
allow_auto_(false),
allow_accept_(false),
allow_save_data_(false),
allow_user_agent_(false) {
}
GoogleString ToString() const;
bool allow_auto() const {
return allow_auto_;
}
void set_allow_auto(bool v) {
allow_auto_ = v;
}
bool allow_accept() const {
return allow_accept_;
}
void set_allow_accept(bool v) {
allow_accept_ = v;
}
bool allow_save_data() const {
return allow_save_data_ || allow_auto_;
}
void set_allow_save_data(bool v) {
allow_save_data_ = v;
}
bool allow_user_agent() const {
return allow_user_agent_;
}
void set_allow_user_agent(bool v) {
allow_user_agent_ = v;
}
private:
// All of the properties must be included in
// RewriteOptions::OptionSignature.
bool allow_auto_;
bool allow_accept_;
bool allow_save_data_;
bool allow_user_agent_;
};
bool AllowVaryOnAuto() const {
return allow_vary_on_.value().allow_auto();
}
bool AllowVaryOnAccept() const {
return allow_vary_on_.value().allow_accept();
}
bool AllowVaryOnSaveData() const {
return allow_vary_on_.value().allow_save_data();
}
bool AllowVaryOnUserAgent() const {
return allow_vary_on_.value().allow_user_agent();
}
GoogleString AllowVaryOnToString() const {
return ToString(allow_vary_on_.value());
}
// Returns true if PageSpeed responds differently for image requests with
// Save-Data header, i.e., using a unique quality and adding
// "Vary: Save-Data" header.
bool SupportSaveData() const {
return (HasValidSaveDataQualities() && AllowVaryOnSaveData());
}
void set_allow_vary_on(const AllowVaryOn& x) {
set_option(x, &allow_vary_on_);
}
// Image qualities and parameters, after applying the inheritance rules.
int64 ImageJpegQuality() const;
int64 ImageJpegQualityForSmallScreen() const;
int64 ImageJpegQualityForSaveData() const;
int64 ImageWebpQuality() const;
int64 ImageWebpQualityForSmallScreen() const;
int64 ImageWebpQualityForSaveData() const;
int64 ImageWebpAnimatedQuality() const;
int64 ImageJpegNumProgressiveScansForSmallScreen() const;
// Returns true if any quality for small screen is valid and different from
// the base quality.
bool HasValidSmallScreenQualities() const;
// Returns true if any quality for Save-Data is valid and different from the
// base quality.
bool HasValidSaveDataQualities() const;
// This version index serves as global signature key. Much of the
// data emitted in signatures is based on the option ordering, which
// can change as we add new options. So every time there is a
// binary-incompatible change to the option ordering, we bump this
// version.
//
// Note: we now use a two-letter code for identifying enabled filters, so
// there is no need bump the option version when changing the filter enum.
//
// Updating this value will have the indirect effect of flushing the metadata
// cache. The HTTPCache can be flushed by updating kHttpCacheVersion in
// http_cache.cc.
//
// This version number should be incremented if any default-values
// are changed, either in an Add*Property() call or via
// options->set_default.
static const int kOptionsVersion = 14;
// Number of bytes used for signature hashing.
static const int kHashBytes = 20;
// Number of bytes capacity in the URL invalidation set.
static const int kCachePurgeBytes = 25000;
// Determines the scope at which an option is evaluated. In Apache,
// for example, kDirectoryScope indicates it can be changed via .htaccess
// files, which is the only way that sites using shared hosting can change
// settings.
//
// The options are ordered from most permissive to least permissive.
enum OptionScope {
kQueryScope, // customized at query (query-param, request headers,
// response headers)
kDirectoryScope, // customized at directory level (.htaccess, <Directory>)
kServerScope, // customized at server level (e.g. VirtualHost)
kProcessScope, // customized at process level only (command-line flags)
kProcessScopeStrict, // as above, but fail startup if included in vhost
};
static const char kCacheExtenderId[];
static const char kCollectFlushEarlyContentFilterId[];
static const char kCssCombinerId[];
static const char kCssFilterId[];
static const char kCssImportFlattenerId[];
static const char kCssInlineId[];
static const char kGoogleFontCssInlineId[];
static const char kImageCombineId[];
static const char kImageCompressionId[];
static const char kInPlaceRewriteId[];
static const char kJavascriptCombinerId[];
static const char kJavascriptInlineId[];
static const char kJavascriptMinId[];
static const char kJavascriptMinSourceMapId[];
static const char kLocalStorageCacheId[];
static const char kPrioritizeCriticalCssId[];
static const char kPanelCommentPrefix[];
// Return the appropriate human-readable filter name for the given filter,
// e.g. "CombineCss".
static const char* FilterName(Filter filter);
// Returns a two-letter id code for this filter, used for for encoding
// URLs.
static const char* FilterId(Filter filter);
// Returns the number of filter ids. This is used to loop over all filter ids
// using the FilterId() method.
static int NumFilterIds();
// Used for enumerating over all entries in the Filter enum.
static const Filter kFirstFilter = kAddBaseTag;
typedef EnumSet<Filter, kEndOfFilters> FilterSet;
typedef std::vector<Filter> FilterVector;
// Convenience name for a set of rewrite filter ids.
typedef std::set<GoogleString> FilterIdSet;
// Lookup the given name to see if it's a filter name or one of the special
// names like "core" or "rewrite_images", and if so add the corresponding
// filter(s) to the given set. If the given name doesn't match -and- if
// handler is not NULL, logs a warning message to handler. Returns true if
// the name matched and the set was updated, false otherwise.
static bool AddByNameToFilterSet(const StringPiece& option, FilterSet* set,
MessageHandler* handler);
// Convenience name for (name,value) pairs of options (typically filter
// parameters), as well as sets of those pairs.
typedef std::pair<GoogleString, GoogleString> OptionStringPair;
typedef std::set<OptionStringPair> OptionSet;
typedef std::vector<PropertyBase*> PropertyVector;
// Base class for Option -- the instantiation of a Property that
// occurs in each RewriteOptions instance.
class OptionBase {
public:
OptionBase() {}
virtual ~OptionBase();
// Returns if parsing was successful. error_detail will be appended to
// to an error message if this returns false. Implementors are not
// required to set *error_detail; its the callers responsibility to do so.
virtual bool SetFromString(StringPiece value_string,
GoogleString* error_detail) = 0;
virtual void Merge(const OptionBase* src) = 0;
virtual bool was_set() const = 0;
virtual GoogleString Signature(const Hasher* hasher) const = 0;
virtual GoogleString ToString() const = 0;
const char* id() const { return property()->id(); }
const char* help_text() const { return property()->help_text(); }
OptionScope scope() const { return property()->scope(); }
StringPiece option_name() const { return property()->option_name(); }
bool is_used_for_signature_computation() const {
return property()->is_used_for_signature_computation();
}
virtual const PropertyBase* property() const = 0;
};
// Convenience name for a set of rewrite options.
typedef std::vector<OptionBase*> OptionBaseVector;
// TODO(huibao): Use bitmask for the values of the enums, and make combination
// of rewrite levels possible.
enum RewriteLevel {
// Enable no filters. Parse HTML but do not perform any
// transformations. This is the default value. Most users should
// explicitly enable the kCoreFilters level by calling
// SetRewriteLevel(kCoreFilters).
kPassThrough,
// Enable filters that make resources smaller, but carry no risk
// of site breakage. Turning this on implies inplace resource
// optimization and preserve-URLs.
kOptimizeForBandwidth,
// Enable the core set of filters. These filters are considered
// generally safe for most sites, though even safe filters can
// break some sites. Most users should specify this option, and
// then optionally add or remove specific filters based on
// specific needs.
kCoreFilters,
// Enable the filters which are essential to make webpages designed for
// desktop computers look good on mobile devices.
kMobilizeFilters,
// Enable all filters intended for core, but some of which might
// need more testing. Good for if users are willing to test out
// the results of the rewrite more closely.
kTestingCoreFilters,
// Enable all filters. This includes filters you should never turn
// on for a real page, like StripScripts!
kAllFilters,
};
// Used for return value of SetOptionFromName.
enum OptionSettingResult {
kOptionOk,
kOptionNameUnknown,
kOptionValueInvalid
};
static const char kDefaultAllowVaryOn[];
static const int kDefaultBeaconReinstrumentTimeSec;
static const int64 kDefaultBlinkMaxHtmlSizeRewritable;
static const int64 kDefaultCssFlattenMaxBytes;
static const int64 kDefaultCssImageInlineMaxBytes;
static const int64 kDefaultCssInlineMaxBytes;
static const int64 kDefaultCssOutlineMinBytes;
static const int64 kDefaultGoogleFontCssInlineMaxBytes;
static const int64 kDefaultImageInlineMaxBytes;
static const int64 kDefaultJsInlineMaxBytes;
static const int64 kDefaultJsOutlineMinBytes;
static const int64 kDefaultProgressiveJpegMinBytes;
static const int64 kDefaultMaxCacheableResponseContentLength;
static const int64 kDefaultMaxHtmlCacheTimeMs;
static const int64 kDefaultMaxHtmlParseBytes;
static const int64 kDefaultMaxImageBytesForWebpInCss;
static const int64 kDefaultMaxLowResImageSizeBytes;
static const int kDefaultMaxLowResToFullResImageSizePercentage;
static const int64 kDefaultMetadataInputErrorsCacheTtlMs;
static const int64 kDefaultMinResourceCacheTimeToRewriteMs;
static const char kDefaultDownstreamCachePurgeMethod[];
static const int64 kDefaultDownstreamCacheRewrittenPercentageThreshold;
static const int64 kDefaultIdleFlushTimeMs;
static const int64 kDefaultFlushBufferLimitBytes;
static const int64 kDefaultImplicitCacheTtlMs;
static const int64 kDefaultMinCacheTtlMs;
static const int64 kDefaultPrioritizeVisibleContentCacheTimeMs;
static const char kDefaultBeaconUrl[];
static const int64 kDefaultImageRecompressQuality;
static const int64 kDefaultImageJpegQualityForSaveData;
static const int64 kDefaultImageJpegRecompressQuality;
static const int64 kDefaultImageJpegRecompressQualityForSmallScreens;
static const int kDefaultImageLimitOptimizedPercent;
static const int kDefaultImageLimitRenderedAreaPercent;
static const int kDefaultImageLimitResizeAreaPercent;
static const int64 kDefaultImageResolutionLimitBytes;
static const int64 kDefaultImageJpegNumProgressiveScans;
static const int64 kDefaultImageWebpQualityForSaveData;
static const int64 kDefaultImageWebpRecompressQuality;
static const int64 kDefaultImageWebpAnimatedRecompressQuality;
static const int64 kDefaultImageWebpRecompressQualityForSmallScreens;
static const int64 kDefaultImageWebpTimeoutMs;
static const int kDefaultDomainShardCount;
static const int64 kDefaultBlinkHtmlChangeDetectionTimeMs;
static const int kDefaultMaxPrefetchJsElements;
static const int64 kDefaultOptionCookiesDurationMs;
static const int64 kDefaultLoadFromFileCacheTtlMs;
static const double kDefaultResponsiveImageDensities[];
// IE limits URL size overall to about 2k characters. See
// http://support.microsoft.com/kb/208427/EN-US
static const int kDefaultMaxUrlSize;
static const int kDefaultImageMaxRewritesAtOnce;
// See http://code.google.com/p/modpagespeed/issues/detail?id=9
// Apache evidently limits each URL path segment (between /) to
// about 256 characters. This is not fundamental URL limitation
// but is Apache specific.
static const int kDefaultMaxUrlSegmentSize;
// Default time to wait for rewrite before returning original resource.
static const int kDefaultRewriteDeadlineMs;
// Default time to wait for a distributed rewrite to return.
static const int64 kDefaultDistributedTimeoutMs;
// Default number of first N images for which low res image is generated by
// DelayImagesFilter.
static const int kDefaultMaxInlinedPreviewImagesIndex;
// Default minimum image size above which low res image is generated by
// InlinePreviewImagesFilter.
static const int64 kDefaultMinImageSizeLowResolutionBytes;
// Default maximum image size below which low res image is generated by
// InlinePreviewImagesFilter.
static const int64 kDefaultMaxImageSizeLowResolutionBytes;
// Default cache expiration value for finder properties in pcache.
static const int64 kDefaultFinderPropertiesCacheExpirationTimeMs;
// Default cache refresh value for finder properties in pcache.
static const int64 kDefaultFinderPropertiesCacheRefreshTimeMs;
// Default duration after which the experiment cookie will expire on the
// user's browser.
static const int64 kDefaultExperimentCookieDurationMs;
// Default time in milliseconds for which a metadata cache entry may be used
// after expiry.
static const int64 kDefaultMetadataCacheStalenessThresholdMs;
// Default maximum size of the combined CSS resource.
static const int64 kDefaultMaxCombinedCssBytes;
// Default maximum size of the combined js resource generated by JsCombiner.
static const int64 kDefaultMaxCombinedJsBytes;
static const int kDefaultExperimentTrafficPercent;
// Default Custom Variable slot in which to put Experiment information.
static const int kDefaultExperimentSlot;
static const char kDefaultBlockingRewriteKey[];
static const char kRejectedRequestUrlKeyName[];
static const int kDefaultPropertyCacheHttpStatusStabilityThreshold;
static const int kDefaultMaxRewriteInfoLogSize;
// This class is a separate subset of options for running an experiment.
// These options can be specified by a spec string that looks like:
// "id=<number greater than 0>;level=<rewrite level>;enabled=
// <comma-separated-list of filters to enable>;disabled=
// <comma-separated-list of filters to disable>;options=
// <comma-separated-list of option=value pairs to set>.
class ExperimentSpec {
public:
// Creates a ExperimentSpec parsed from spec.
// If spec doesn't have an id, then id_ will be set to
// experiment::kExperimentNotSet. These ExperimentSpecs will then be
// rejected by AddExperimentSpec().
ExperimentSpec(const StringPiece& spec, const RewriteOptions* options,
MessageHandler* handler);
// Creates a ExperimentSpec with id_=id. All other variables
// are initialized to 0.
// This is primarily used for setting up the control and for cloning.
explicit ExperimentSpec(int id);
virtual ~ExperimentSpec();
// Return a ExperimentSpec with all the same information as this one.
virtual ExperimentSpec* Clone();
bool is_valid() const { return id_ >= 0; }
// Accessors.
int id() const { return id_; }
int percent() const { return percent_; }
const GoogleString& ga_id() const { return ga_id_; }
int slot() const { return ga_variable_slot_; }
RewriteLevel rewrite_level() const { return rewrite_level_; }
FilterSet enabled_filters() const { return enabled_filters_; }
FilterSet disabled_filters() const { return disabled_filters_; }
OptionSet filter_options() const { return filter_options_; }
bool matches_device_type(UserAgentMatcher::DeviceType type) const;
bool use_default() const { return use_default_; }
GoogleString ToString() const;
// Mutate the origin domains in DomainLawyer with alternate_origin_domains_.
void ApplyAlternateOriginsToDomainLawyer(DomainLawyer* domain_lawyer,
MessageHandler* handler) const;
protected:
// Merges a spec into this. This follows the same semantics as
// RewriteOptions. Specifically, filter/options list get unioned, and
// vars get overwritten, except ID. In the event of a conflict, e.g.
// preserve vs extend_cache, *this will take precedence.
void Merge(const ExperimentSpec& spec);
typedef std::bitset<net_instaweb::UserAgentMatcher::kEndOfDeviceType>
DeviceTypeBitSet;
static bool ParseDeviceTypeBitSet(const StringPiece& in,
DeviceTypeBitSet* out,
MessageHandler* handler);
struct AlternateOriginDomainSpec {
StringVector serving_domains;
GoogleString origin_domain;
GoogleString host_header;
};
// Simple check that 's' is not obviously an invalid host. Used to avoid
// problems when a port number is accidentally placed in a host field.
static bool LooksLikeValidHost(const StringPiece& s);
// Parses the string after an 'alternate_origin_domain' experiment
// option, returning if it was successfull. If it returns false, the spec is
// invalid and should be discarded.
static bool ParseAlternateOriginDomain(const StringPiece& in,
AlternateOriginDomainSpec* out,
MessageHandler* handler);
// Combine consecutive entries in a StringPieceVector such that
// [ a, b, "host, port" ] can be turned into [ a, b, host:port ].
// Inspects vec[first_pos] and vec[first_pos + 1]. If they appear to be a
// quoted tuple, will replace vec[first_pos] with a combined value and
// vec[first_pos + 1] will be removed, ie: vec will reduce in size by 1.
// combined_container is used as the underlying storage for the combined
// string, if necessary.
static void CombineQuotedHostPort(StringPieceVector* vec, size_t first_pos,
GoogleString* combined_container);
// Returns a copy of the input string that will be surrounded by double
// quotes if the input string contains a colon. This is used to turn
// host:port into "host:port" when printing an ExperimentSpec.
static GoogleString QuoteHostPort(const GoogleString& in);
private:
FRIEND_TEST(RewriteOptionsTest, ExperimentMergeTest);
FRIEND_TEST(RewriteOptionsTest, DeviceTypeMergeTest);
FRIEND_TEST(RewriteOptionsTest, AlternateOriginDomainMergeTest);
// Parse 'spec' and set the FilterSets, rewrite level, inlining thresholds,
// and OptionSets accordingly.
void Initialize(const StringPiece& spec, MessageHandler* handler);
//
// If you add any members to this list, be sure to also add them to the
// Merge method.
//
int id_; // id for this experiment
GoogleString ga_id_; // Google Analytics ID for this experiment
int ga_variable_slot_;
int percent_; // percentage of traffic to go through this experiment.
RewriteLevel rewrite_level_;
FilterSet enabled_filters_;
FilterSet disabled_filters_;
OptionSet filter_options_;
// bitset to indicate which device types this ExperimentSpec should apply
// to. If NULL, no device type was specified and the experiment applies
// to all device types.
scoped_ptr<DeviceTypeBitSet> matches_device_types_;
// Use whatever RewriteOptions' settings are without experiments
// for this experiment.
bool use_default_;
// vector of parsed alternate_origin_domain options. These mutations will
// be applied to a DomainLawyer when passed to MutateDomainLawer.
typedef std::vector<AlternateOriginDomainSpec> AlternateOriginDomains;
AlternateOriginDomains alternate_origin_domains_;
DISALLOW_COPY_AND_ASSIGN(ExperimentSpec);
};
// Represents the content type of user-defined url-valued attributes.
struct ElementAttributeCategory {
GoogleString element;
GoogleString attribute;
semantic_type::Category category;
};
// Identifies static properties of RewriteOptions that must be
// initialized before the properties can be used. Primarily for the
// benefit of unit tests and valgrind sanity, Initialize/Terminate
// is balance-checked.
//
// TODO(jmarantz): Add static properties -- currently there are none.
class Properties {
public:
// Initializes a static Properties* object. Pass the address of a static
// member variable. A count is kept of how many times Initialize is called.
//
// True will be returned if this was the first call to initialize
// the properties object, and this can be used by implementations
// to decide whether to initialize other static variables.
//
// Initialization is not thread-safe.
static bool Initialize(Properties** properties);
// Terminates a static Properties* object. Pass the address of a static
// member variable.
//
// True will be returned if Terminate has been called the same number
// of times as Initialize is called, and this can be used to decide
// whether to clean up other static variables.
//
// Termination is not thread-safe.
static bool Terminate(Properties** properties_handle);
// Returns the number of properties
int size() const { return property_vector_.size(); }
const PropertyBase* property(int index) const {
return property_vector_[index];
}
PropertyBase* property(int index) { return property_vector_[index]; }
// Merges the passed-in property-vector into this one, sorting the
// merged properties. Each property's needs its index into the
// merged vector for initializing subclass-specific Options in
// each constructor. So this method mutates its input by setting
// an index field in each property.
void Merge(Properties* properties);
void push_back(PropertyBase* p) { property_vector_.push_back(p); }
private:
// This object should not be constructed/destructed directly; it should be
// created by calling Properties::Initialize and Properties::Terminate.
Properties();
~Properties();
// initialization_count_ acts as a reference count: it is incremented on
// Initialize(), and decremented on Terminate(). At 0 the object is
// deleted.
int initialization_count_;
// owns_properties_ is set to true if the PropertyBase* in the vector should
// be deleted when Terminate is called bringing initialization_count_ to 0.
// RewriteOptions::properties_.owns_properties_ is true.
// RewriteOptions::all_properties_.owns_properties_ is false.
bool owns_properties_;
PropertyVector property_vector_;
};
// Maps a filter's enum (kAddHead) to its id ("ah") and name ("Add Head").
struct FilterEnumToIdAndNameEntry {
RewriteOptions::Filter filter_enum;
const char* filter_id;
const char* filter_name;
};
static bool ParseRewriteLevel(const StringPiece& in, RewriteLevel* out);
typedef std::set<semantic_type::Category> ResourceCategorySet;
static bool ParseInlineUnauthorizedResourceType(
const StringPiece& in,
ResourceCategorySet* resource_types);
// Parse a beacon url, or a pair of beacon urls (http https) separated by a
// space. If only an http url is given, the https url is derived from it
// by simply substituting the protocol.
static bool ParseBeaconUrl(const StringPiece& in, BeaconUrl* out);
// Checks if either of the optimizing rewrite options are ON and it includes
// kRecompressJPeg, kRecompressPng, kRecompressWebp, kConvertGifToPng,
// kConvertJpegToWebp, kConvertPngToJpeg, and kConvertToWebpLossless.
bool ImageOptimizationEnabled() const;
explicit RewriteOptions(ThreadSystem* thread_system);
virtual ~RewriteOptions();
// Static initialization of members. Calls to Initialize and
// Terminate must be matched. Returns 'true' for the first
// Initialize call and the last Terminate call.
static bool Initialize();
static bool Terminate();
#ifndef NDEBUG
// Determines whether it's OK to modify the RewriteOptions in the
// current thread. Note that this is stricter than necessary, but
// makes it easier to reason about potential thread safety issues
// for copy-on-write sharing of substructures.
//
// This is exposed as an external API for ease of unit testing.
bool ModificationOK() const;
// Determines whether it's OK to merge from the RewriteOptions object
// in the current thread. Note that this is stricter than necessary, but
// makes it easier to reason about potential thread safety issues
// for copy-on-write sharing of substructures.
//
// This is exposed as an external API for ease of unit testing.
bool MergeOK() const;
#endif
// Initializes the Options objects in a RewriteOptions instance
// based on the supplied Properties vector. Note that subclasses
// can statically define additional properties, in which case they
// should call this method from their constructor.
void InitializeOptions(const Properties* properties);
bool modified() const { return modified_; }
// Sets the default rewrite level for this RewriteOptions object only.
// Note that the defaults for other RewriteOptions objects are unaffected.
//
// TODO(jmarantz): Get rid of this method. The semantics it requires are
// costly to implement and don't add much value.
void SetDefaultRewriteLevel(RewriteLevel level) {
// Do not set the modified bit -- we are only changing the default.
level_.set_default(level);
}
void SetRewriteLevel(RewriteLevel level) {
set_option(level, &level_);
}
// Specify a header to insert when fetching subresources.
void AddCustomFetchHeader(const StringPiece& name, const StringPiece& value);
const NameValue* custom_fetch_header(int i) const {
return custom_fetch_headers_[i];
}
int num_custom_fetch_headers() const {
return custom_fetch_headers_.size();
}
// Returns the spec with the id_ that matches id. Returns NULL if no
// spec matches.
ExperimentSpec* GetExperimentSpec(int id) const;
// Returns false if id is negative, or if the id is reserved
// for NoExperiment or NotSet, or if we already have an experiment
// with that id.
bool AvailableExperimentId(int id);
// Creates a ExperimentSpec from spec and adds it to the configuration,
// returning it on success and NULL on failure.
virtual ExperimentSpec* AddExperimentSpec(const StringPiece& spec,
MessageHandler* handler);
// Sets which side of the experiment these RewriteOptions are on.
// Cookie-setting must be done separately.
// experiment::kExperimentNotSet indicates it hasn't been set.
// experiment::kNoExperiment indicates this request shouldn't be
// in any experiment.
// Then sets the rewriters to match the experiment indicated by id.
// Returns true if succeeded in setting state.
virtual bool SetExperimentState(int id);
// We encode experiment information in urls as an experiment index: the first
// ExperimentSpec is a, the next is b, and so on. Empty string or an invalid
// letter means kNoExperiment.
void SetExperimentStateStr(const StringPiece& experiment_index);
int experiment_id() const { return experiment_id_; }
int experiment_spec_id(int i) const {
return experiment_specs_[i]->id();
}
// Returns a string representation of experiment_id() suitable for consumption
// by SetExperimentStateStr(), encoding the index of the current experiment
// (not its id). If we're not running an experiment, returns the empty
// string.
GoogleString GetExperimentStateStr() const;
ExperimentSpec* experiment_spec(int i) const {
return experiment_specs_[i];
}
int num_experiments() const { return experiment_specs_.size(); }
bool enroll_experiment() const {
return enroll_experiment_id() != experiment::kForceNoExperiment;
}
// Store that when we see <element attribute=X> we should treat X as a URL
// pointing to a resource of the type indicated by category. For example,
// while by default we would treat the 'src' attribute of an a 'img' element
// as the URL for an image and will cache-extend, inline, or otherwise
// optimize it as appropriate, we would not do the same for the 'src'
// atrtribute of a 'span' element (<span src=...>) because there's no "src"
// attribute of "span" in the HTML spec. If someone needed us to treat
// span.src as a URL, however, they could call:
// AddUrlValuedAttribute("src", "span", appropriate_category)
//
// Makes copies of element and attribute.
void AddUrlValuedAttribute(const StringPiece& element,
const StringPiece& attribute,
semantic_type::Category category);
// Look up a url-valued attribute, return details via element, attribute,
// and category. index must be less than num_url_valued_attributes().
void UrlValuedAttribute(int index,
StringPiece* element,
StringPiece* attribute,
semantic_type::Category* category) const;
int num_url_valued_attributes() const {
if (url_valued_attributes_ == NULL) {
return 0;
} else {
return url_valued_attributes_->size();
}
}
void AddInlineUnauthorizedResourceType(semantic_type::Category category);
bool HasInlineUnauthorizedResourceType(
semantic_type::Category category) const;
void ClearInlineUnauthorizedResourceTypes();
void set_inline_unauthorized_resource_types(ResourceCategorySet x);
// Store size, md5 hash and canonical url for library recognition.
bool RegisterLibrary(
uint64 bytes, StringPiece md5_hash, StringPiece canonical_url) {
return WriteableJavascriptLibraryIdentification()->RegisterLibrary(
bytes, md5_hash, canonical_url);
}
// Return the javascript_library_identification_ object that applies to
// the current configuration (NULL if identification is disabled).
const JavascriptLibraryIdentification* javascript_library_identification()
const {
if (Enabled(kCanonicalizeJavascriptLibraries)) {
return javascript_library_identification_.get();
} else {
return NULL;
}
}
RewriteLevel level() const { return level_.value(); }
// Enables filters specified without a prefix or with a prefix of '+' and
// disables filters specified with a prefix of '-'. Returns false if any
// of the filter names are invalid, but all the valid ones will be
// added anyway.
bool AdjustFiltersByCommaSeparatedList(const StringPiece& filters,
MessageHandler* handler);
// Adds a set of filters to the enabled set. Returns false if any
// of the filter names are invalid, but all the valid ones will be
// added anyway.
bool EnableFiltersByCommaSeparatedList(const StringPiece& filters,
MessageHandler* handler);
// Adds a set of filters to the disabled set. Returns false if any
// of the filter names are invalid, but all the valid ones will be
// added anyway.
bool DisableFiltersByCommaSeparatedList(const StringPiece& filters,
MessageHandler* handler);
// Adds a set of filters to the forbidden set. Returns false if any
// of the filter names are invalid, but all the valid ones will be
// added anyway.
bool ForbidFiltersByCommaSeparatedList(const StringPiece& filters,
MessageHandler* handler);
// Set rewrite level to kPassThrough and explicitly disable all filters.
void DisableAllFilters();
// Explicitly disable all filters which are not *currently* explicitly enabled
//
// Note: Do not call EnableFilter(...) for this options object after calling
// DisableAllFilters..., because the Disable list will not be auto-updated.
//
// Used to deal with query param ?ModPagespeedFilter=foo
// Which implies that all filters not listed should be disabled.
void DisableAllFiltersNotExplicitlyEnabled();
// Adds a set of filter prefixes (ids) to the set of distributable filters.
// The names are not verified and all prefixes will be added.
void DistributeFiltersByCommaSeparatedList(const StringPiece& filter_ids,
MessageHandler* handler);
// Adds the filter to the list of distributable filters.
// For experimentation, may be removed later.
void DistributeFilter(const StringPiece& filter_id);
// Returns true if the filter is in the list of distributable filters.
// For experimentation, may be removed later.
bool Distributable(const StringPiece& filter_id) const;
// Adds the filter to the list of enabled filters. However, if the filter
// is also present in either the list of disabled or forbidden filters,
// that takes precedence and it is not enabled.
void EnableFilter(Filter filter);
// Guarantees that a filter would be enabled even if it is present in the list
// of disabled filters by removing it from disabled & forbidden filter lists.
void ForceEnableFilter(Filter filter);
void DisableFilter(Filter filter);
void DisableIfNotExplictlyEnabled(Filter filter);
void ForbidFilter(Filter filter);
void EnableFilters(const FilterSet& filter_set);
void DisableFilters(const FilterSet& filter_set);
void ForbidFilters(const FilterSet& filter_set);
// Clear all explicitly enabled and disabled filters. Some filters may still
// be enabled by the rewrite level and HtmlWriterFilter will be enabled.
void ClearFilters();
// Induces a filter to be considered enabled by turning on the AllFilters
// level and disabling the filters that are not wanted. This is used for
// testing the desired behavior of PreserveUrls, which is to disable inlining
// and combining when the level is CoreFilters, but allow explictly enabled
// combiners and inliners to work.
//
// Beware: this mode of enabling filters is difficult to manage
// across multiple levels of test inheritance. In particular, once
// SoftEnableFilterForTesting is called, EnableFilter will no longer
// work due to the explicit disables. It does work to call
// SoftEnableFilterForTesting multiple times to enable several
// filters, and it also works to call EnableFilter first. ForceEnable
// also works.
//
// It is only necessary to call this in tests with PreserveUrls.
//
// Caveat emptor.
void SoftEnableFilterForTesting(Filter filter);
// Enables extend_cache_css, extend_cache_images, and extend_cache_scripts.
// Does not enable extend_cache_pdfs.
void EnableExtendCacheFilters();
bool Enabled(Filter filter) const;
bool Forbidden(Filter filter) const;
bool Forbidden(StringPiece filter_id) const;
// Returns the set of enabled filters that require JavaScript for execution.
void GetEnabledFiltersRequiringScriptExecution(FilterVector* filters) const;
// Disables all filters that depend on executing custom javascript.
void DisableFiltersRequiringScriptExecution();
// Returns true if any filter benefits from per-origin property cache
// information.
bool UsePerOriginPropertyCachePage() const;
// Adds pairs of (option, value) to the option set. The option names and
// values are not checked for validity, just stored. If the string piece
// was parsed correctly, this returns true. If there were parsing errors this
// returns false. The set is still populated on error.
static bool AddCommaSeparatedListToOptionSet(
const StringPiece& options, OptionSet* set, MessageHandler* handler);
// Set Option 'name' to 'value'. Returns whether it succeeded or the kind of
// failure (wrong name or value), and writes the diagnostic into 'msg'.
// This only understands simple scalar options, and not more general things
// like filter lists, blacklists, etc.
OptionSettingResult SetOptionFromName(
StringPiece name, StringPiece value, GoogleString* msg);
// Like above, but doesn't bother formatting the error message.
OptionSettingResult SetOptionFromName(
StringPiece name, StringPiece value);
// Same as SetOptionFromName, but only works with options that are valid
// to use as query parameters, returning kOptionNameUnknown for properties
// where the scope() is not kQueryScope.
OptionSettingResult SetOptionFromQuery(StringPiece name, StringPiece value);
// Same as SetOptionFromName, but only works with options that are valid
// to use as remote config, returning kOptionNameUnknown for properties
// where the scope() is not kQueryScope or kDirectoryScope.
OptionSettingResult SetOptionFromRemoteConfig(StringPiece name,
StringPiece value);
GoogleString ScopeEnumToString(OptionScope scope);
// Advanced option parsing, that can understand non-scalar values
// (unlike SetOptionFromName), and which is extensible by platforms.
// Returns whether succeeded or the kind of failure, and writes the
// diagnostic into *msg.
//
// If you extend any of these you also need to extend Merge() and
// SubclassSignatureLockHeld().
virtual OptionSettingResult ParseAndSetOptionFromName1(
StringPiece name, StringPiece arg,
GoogleString* msg, MessageHandler* handler);
// Parses and sets options like ParseAndSetOptionFromName1, but with a maximum
// scope specified. ParseAndSetOptionFromName1 will apply options from any
// scope, whereas ParseAndSetOptionFromNameWithScope will only apply options
// within max_scope scope.
OptionSettingResult ParseAndSetOptionFromNameWithScope(
StringPiece name, StringPiece arg, OptionScope max_scope,
GoogleString* msg, MessageHandler* handler);
virtual OptionSettingResult ParseAndSetOptionFromName2(
StringPiece name, StringPiece arg1, StringPiece arg2,
GoogleString* msg, MessageHandler* handler);
virtual OptionSettingResult ParseAndSetOptionFromName3(
StringPiece name, StringPiece arg1, StringPiece arg2, StringPiece arg3,
GoogleString* msg, MessageHandler* handler);
// Returns the id and value of the specified option-enum in *id and *value.
// Sets *was_set to true if this option has been altered from the default.
//
// If this option was not found, false is returned, and *id, *was_set, and
// *value will be left unassigned.
bool OptionValue(StringPiece option_name, const char** id,
bool* was_set, GoogleString* value) const;
// Set all of the options to their values specified in the option set.
// Returns true if all options in the set were successful, false if not.
bool SetOptionsFromName(const OptionSet& option_set, MessageHandler* handler);
// Sets Option 'name' to 'value'. Returns whether it succeeded and logs
// any warnings to 'handler'.
bool SetOptionFromNameAndLog(StringPiece name,
StringPiece value,
MessageHandler* handler);
// These static methods are used by Option<T>::SetFromString to set
// Option<T>::value_ from a string representation of it.
static bool ParseFromString(StringPiece value_string, bool* value);
static bool ParseFromString(StringPiece value_string, EnabledEnum* value);
static bool ParseFromString(StringPiece value_string, int* value) {
return StringToInt(value_string, value);
}
static bool ParseFromString(StringPiece value_string, int64* value) {
return StringToInt64(value_string, value);
}
static bool ParseFromString(StringPiece value_string, double* value) {
return StringToDouble(value_string, value);
}
static bool ParseFromString(StringPiece value_string, GoogleString* value) {
value_string.CopyToString(value);
return true;
}
static bool ParseFromString(StringPiece value_string, RewriteLevel* value) {
return ParseRewriteLevel(value_string, value);
}
static bool ParseFromString(StringPiece value_string,
ResourceCategorySet* value) {
return ParseInlineUnauthorizedResourceType(value_string, value);
}
static bool ParseFromString(StringPiece value_string, BeaconUrl* value) {
return ParseBeaconUrl(value_string, value);
}
static bool ParseFromString(StringPiece value_string, Color* color);
static bool ParseFromString(StringPiece value_string, MobTheme* theme);
static bool ParseFromString(StringPiece value_string,
ResponsiveDensities* value);
static bool ParseFromString(StringPiece value_string,
protobuf::MessageLite* proto);
static bool ParseFromString(StringPiece value_string,
AllowVaryOn* allow_vary_on);
// TODO(jmarantz): consider setting flags in the set_ methods so that
// first's explicit settings can override default values from second.
int64 css_outline_min_bytes() const { return css_outline_min_bytes_.value(); }
void set_css_outline_min_bytes(int64 x) {
set_option(x, &css_outline_min_bytes_);
}
const GoogleString& ga_id() const { return ga_id_.value(); }
void set_ga_id(const GoogleString& id) {
set_option(id, &ga_id_);
}
void set_content_experiment_id(const GoogleString& s) {
set_option(s, &content_experiment_id_);
}
const GoogleString& content_experiment_id() const {
return content_experiment_id_.value();
}
void set_content_experiment_variant_id(const GoogleString& s) {
set_option(s, &content_experiment_variant_id_);
}
const GoogleString& content_experiment_variant_id() const {
return content_experiment_variant_id_.value();
}
bool is_content_experiment() const {
return !content_experiment_id().empty() &&
!content_experiment_variant_id().empty();
}
bool use_analytics_js() const {
return use_analytics_js_.value();
}
void set_use_analytics_js(bool x) {
set_option(x, &use_analytics_js_);
}
bool increase_speed_tracking() const {
return increase_speed_tracking_.value();
}
void set_increase_speed_tracking(bool x) {
set_option(x, &increase_speed_tracking_);
}
int64 js_outline_min_bytes() const { return js_outline_min_bytes_.value(); }
void set_js_outline_min_bytes(int64 x) {
set_option(x, &js_outline_min_bytes_);
}
int64 progressive_jpeg_min_bytes() const {
return progressive_jpeg_min_bytes_.value();
}
void set_progressive_jpeg_min_bytes(int64 x) {
set_option(x, &progressive_jpeg_min_bytes_);
}
int64 css_flatten_max_bytes() const { return css_flatten_max_bytes_.value(); }
void set_css_flatten_max_bytes(int64 x) {
set_option(x, &css_flatten_max_bytes_);
}
bool cache_small_images_unrewritten() const {
return cache_small_images_unrewritten_.value();
}
void set_cache_small_images_unrewritten(bool x) {
set_option(x, &cache_small_images_unrewritten_);
}
int64 image_resolution_limit_bytes() const {
return image_resolution_limit_bytes_.value();
}
void set_image_resolution_limit_bytes(int64 x) {
set_option(x, &image_resolution_limit_bytes_);
}
// Retrieve the image inlining threshold, but return 0 if it's disabled.
int64 ImageInlineMaxBytes() const;
void set_image_inline_max_bytes(int64 x);
// Retrieve the css image inlining threshold, but return 0 if it's disabled.
int64 CssImageInlineMaxBytes() const;
void set_css_image_inline_max_bytes(int64 x) {
set_option(x, &css_image_inline_max_bytes_);
}
// The larger of ImageInlineMaxBytes and CssImageInlineMaxBytes.
int64 MaxImageInlineMaxBytes() const;
int64 css_inline_max_bytes() const { return css_inline_max_bytes_.value(); }
void set_css_inline_max_bytes(int64 x) {
set_option(x, &css_inline_max_bytes_);
}
int64 google_font_css_inline_max_bytes() const {
return google_font_css_inline_max_bytes_.value();
}
void set_google_font_css_inline_max_bytes(int64 x) {
set_option(x, &google_font_css_inline_max_bytes_);
}
int64 js_inline_max_bytes() const { return js_inline_max_bytes_.value(); }
void set_js_inline_max_bytes(int64 x) {
set_option(x, &js_inline_max_bytes_);
}
int64 max_html_cache_time_ms() const {
return max_html_cache_time_ms_.value();
}
void set_max_html_cache_time_ms(int64 x) {
set_option(x, &max_html_cache_time_ms_);
}
int64 max_html_parse_bytes() const {
return max_html_parse_bytes_.value();
}
void set_max_html_parse_bytes(int64 x) {
set_option(x, &max_html_parse_bytes_);
}
int64 max_image_bytes_for_webp_in_css() const {
return max_image_bytes_for_webp_in_css_.value();
}
void set_max_image_bytes_for_webp_in_css(int64 x) {
set_option(x, &max_image_bytes_for_webp_in_css_);
}
int64 max_cacheable_response_content_length() const {
return max_cacheable_response_content_length_.value();
}
void set_max_cacheable_response_content_length(int64 x) {
set_option(x, &max_cacheable_response_content_length_);
}
int64 min_resource_cache_time_to_rewrite_ms() const {
return min_resource_cache_time_to_rewrite_ms_.value();
}
void set_min_resource_cache_time_to_rewrite_ms(int64 x) {
set_option(x, &min_resource_cache_time_to_rewrite_ms_);
}
bool need_to_store_experiment_data() const {
return need_to_store_experiment_data_;
}
void set_need_to_store_experiment_data(bool x) {
need_to_store_experiment_data_ = x;
}
int64 blocking_fetch_timeout_ms() const {
return blocking_fetch_timeout_ms_.value();
}
void set_blocking_fetch_timeout_ms(int64 x) {
set_option(x, &blocking_fetch_timeout_ms_);
}
bool override_ie_document_mode() const {
return override_ie_document_mode_.value();
}
void set_override_ie_document_mode(bool x) {
set_option(x, &override_ie_document_mode_);
}
int64 blink_blacklist_end_timestamp_ms() const {
return blink_blacklist_end_timestamp_ms_.value();
}
void set_blink_blacklist_end_timestamp_ms(int64 x) {
set_option(x, &blink_blacklist_end_timestamp_ms_);
}
bool preserve_subresource_hints() const {
return preserve_subresource_hints_.value();
}
void set_preserve_subresource_hints(bool x) {
set_option(x, &preserve_subresource_hints_);
}
bool preserve_url_relativity() const {
return preserve_url_relativity_.value();
}
void set_preserve_url_relativity(bool x) {
set_option(x, &preserve_url_relativity_);
}
// Returns whether the given URL is valid for use in the cache, given the
// timestamp stored in the cache.
//
// It first checks time_ms against the global cache invalidation timestamp.
//
// It next checks if PurgeCacheUrl has been called on url with a timestamp
// earlier than time_ms. Note: this is not a wildcard check but an
// exact lookup.
//
// Finally, if search_wildcards is true, it scans
// url_cache_invalidation_entries_ for entries with timestamp_ms > time_ms and
// url matching the url_pattern.
//
// In most contexts where you'd call this you should consider instead
// calling OptionsAwareHTTPCacheCallback::IsCacheValid instead, which takes
// into account request-headers.
bool IsUrlCacheValid(StringPiece url, int64 time_ms,
bool search_wildcards) const;
// If timestamp_ms greater than or equal to the last timestamp in
// url_cache_invalidation_entries_, then appends an UrlCacheInvalidationEntry
// with 'timestamp_ms' and 'url_pattern' to url_cache_invalidation_entries_.
// Else does nothing.
//
// Also see PurgeCacheUrl. AddUrlCacheInvalidationEntry with a non-wildcard
// pattern and ignores_metadata_and_pcache==false is equivalent to
// PurgeCacheUrl.
//
// If ignores_metadata_and_pcache is true, metadata is not
// invalidated and property cache is invalidated of URLs matching
// url_pattern. If false, metadata cache and property cache entries
// may be invalidated, depending on whether there are wildcards in
// the pattern, and whether enable_cache_purge() is true. Note that
// HTTP cache invalidation is always exactly for the URLs matching
// url_pattern.
void AddUrlCacheInvalidationEntry(StringPiece url_pattern,
int64 timestamp_ms,
bool ignores_metadata_and_pcache);
// Purge a cache entry for an exact URL, not a wildcard.
void PurgeUrl(StringPiece url, int64 timestamp_ms);
// Checks if url_cache_invalidation_entries_ is in increasing order of
// timestamp. For testing.
bool IsUrlCacheInvalidationEntriesSorted() const;
// Supply optional mutex for setting a global cache invalidation
// timestamp. Ownership of 'lock' is transfered to this.
void set_cache_invalidation_timestamp_mutex(ThreadSystem::RWLock* lock) {
cache_purge_mutex_.reset(lock);
}
// Cache invalidation timestamp is in milliseconds since 1970. It is used
// for invalidating everything in the cache written prior to the timestamp.
//
// TODO(jmarantz): rename to cache_invalidation_timestamp_ms().
int64 cache_invalidation_timestamp() const;
// Determines whether there is a valid cache_invalidation_timestamp. It
// is invalid to call cache_invalidation_timestamp() if
// has_cache_invalidation_timestamp_ms() is false.
bool has_cache_invalidation_timestamp_ms() const;
// Sets the cache invalidation timestamp -- in milliseconds since
// 1970. This function is meant to be called on a RewriteOptions*
// immediately after instantiation.
//
// It can also be used to mutate the invalidation timestamp of a
// RewriteOptions instance that is used as a base for cloning/merging,
// in which case you should make sure to establish a real mutex with
// set_cache_invalidation_timestamp_mutex for such instances.
bool UpdateCacheInvalidationTimestampMs(int64 timestamp_ms)
LOCKS_EXCLUDED(cache_purge_mutex_.get());
// Mutates the options PurgeSet by copying the contents from purge_set.
// Returns true if the contents actually changed, false if the incoming
// purge_set was identical to purge_set already in this.
bool UpdateCachePurgeSet(const CopyOnWrite<PurgeSet>& purge_set)
LOCKS_EXCLUDED(cache_purge_mutex_.get());
// Generates a human-readable view of the PurgeSet, including timestamps
// in GMT.
GoogleString PurgeSetString() const;
// How much inactivity of HTML input will result in PSA introducing a flush.
// Values <= 0 disable the feature.
int64 idle_flush_time_ms() const {
return idle_flush_time_ms_.value();
}
void set_idle_flush_time_ms(int64 x) {
set_option(x, &idle_flush_time_ms_);
}
// How much accumulated HTML will result in PSA introducing a flush.
int64 flush_buffer_limit_bytes() const {
return flush_buffer_limit_bytes_.value();
}
void set_flush_buffer_limit_bytes(int64 x) {
set_option(x, &flush_buffer_limit_bytes_);
}
// The maximum length of a URL segment.
// for http://a/b/c.d, this is == strlen("c.d")
int max_url_segment_size() const { return max_url_segment_size_.value(); }
void set_max_url_segment_size(int x) {
set_option(x, &max_url_segment_size_);
}
int image_max_rewrites_at_once() const {
return image_max_rewrites_at_once_.value();
}
void set_image_max_rewrites_at_once(int x) {
set_option(x, &image_max_rewrites_at_once_);
}
// The maximum size of the entire URL. If '0', this is left unlimited.
int max_url_size() const { return max_url_size_.value(); }
void set_max_url_size(int x) {
set_option(x, &max_url_size_);
}
int rewrite_deadline_ms() const { return rewrite_deadline_ms_.value(); }
void set_rewrite_deadline_ms(int x) {
set_option(x, &rewrite_deadline_ms_);
}
bool test_instant_fetch_rewrite_deadline() const {
return test_instant_fetch_rewrite_deadline_.value();
}
void set_test_instant_fetch_rewrite_deadline(bool x) {
set_option(x, &test_instant_fetch_rewrite_deadline_);
}
void set_test_only_prioritize_critical_css_dont_apply_original_css(bool x) {
set_option(x, &test_only_prioritize_critical_css_dont_apply_original_css_);
}
bool test_only_prioritize_critical_css_dont_apply_original_css() const {
return test_only_prioritize_critical_css_dont_apply_original_css_.value();
}
int domain_shard_count() const { return domain_shard_count_.value(); }
// The argument is int64 to allow it to be set from the http header or url
// query param and int64_query_params_ only allows setting of 64 bit values.
void set_domain_shard_count(int64 x) {
int value = x;
set_option(value, &domain_shard_count_);
}
void set_enabled(EnabledEnum x) {
set_option(x, &enabled_);
}
bool enabled() const {
return enabled_.value() == kEnabledOn;
}
bool unplugged() const {
return enabled_.value() == kEnabledUnplugged;
}
void set_add_options_to_urls(bool x) {
set_option(x, &add_options_to_urls_);
}
bool add_options_to_urls() const {
return add_options_to_urls_.value();
}
void set_publicly_cache_mismatched_hashes_experimental(bool x) {
set_option(x, &publicly_cache_mismatched_hashes_experimental_);
}
bool publicly_cache_mismatched_hashes_experimental() const {
return publicly_cache_mismatched_hashes_experimental_.value();
}
void set_oblivious_pagespeed_urls(bool x) {
set_option(x, &oblivious_pagespeed_urls_);
}
bool oblivious_pagespeed_urls() const {
return oblivious_pagespeed_urls_.value();
}
void set_in_place_rewriting_enabled(bool x) {
set_option(x, &in_place_rewriting_enabled_);
}
bool in_place_rewriting_enabled() const {
return CheckBandwidthOption(in_place_rewriting_enabled_);
}
void set_in_place_wait_for_optimized(bool x) {
set_option(x, &in_place_wait_for_optimized_);
}
bool in_place_wait_for_optimized() const {
return (in_place_wait_for_optimized_.value() ||
(in_place_rewrite_deadline_ms() < 0));
}
void set_in_place_rewrite_deadline_ms(int x) {
set_option(x, &in_place_rewrite_deadline_ms_);
}
int in_place_rewrite_deadline_ms() const {
return in_place_rewrite_deadline_ms_.value();
}
void set_in_place_preemptive_rewrite_css(bool x) {
set_option(x, &in_place_preemptive_rewrite_css_);
}
bool in_place_preemptive_rewrite_css() const {
return CheckBandwidthOption(in_place_preemptive_rewrite_css_);
}
void set_in_place_preemptive_rewrite_css_images(bool x) {
set_option(x, &in_place_preemptive_rewrite_css_images_);
}
bool in_place_preemptive_rewrite_css_images() const {
return CheckBandwidthOption(in_place_preemptive_rewrite_css_images_);
}
void set_in_place_preemptive_rewrite_images(bool x) {
set_option(x, &in_place_preemptive_rewrite_images_);
}
bool in_place_preemptive_rewrite_images() const {
return CheckBandwidthOption(in_place_preemptive_rewrite_images_);
}
void set_in_place_preemptive_rewrite_javascript(bool x) {
set_option(x, &in_place_preemptive_rewrite_javascript_);
}
bool in_place_preemptive_rewrite_javascript() const {
return CheckBandwidthOption(in_place_preemptive_rewrite_javascript_);
}
void set_private_not_vary_for_ie(bool x) {
set_option(x, &private_not_vary_for_ie_);
}
bool private_not_vary_for_ie() const {
return private_not_vary_for_ie_.value();
}
void set_combine_across_paths(bool x) {
set_option(x, &combine_across_paths_);
}
bool combine_across_paths() const { return combine_across_paths_.value(); }
void set_log_background_rewrites(bool x) {
set_option(x, &log_background_rewrites_);
}
bool log_background_rewrites() const {
return log_background_rewrites_.value();
}
void set_log_mobilization_samples(bool x) {
set_option(x, &log_mobilization_samples_);
}
bool log_mobilization_samples() const {
return log_mobilization_samples_.value();
}
void set_log_rewrite_timing(bool x) {
set_option(x, &log_rewrite_timing_);
}
bool log_rewrite_timing() const { return log_rewrite_timing_.value(); }
void set_log_url_indices(bool x) {
set_option(x, &log_url_indices_);
}
bool log_url_indices() const { return log_url_indices_.value(); }
void set_lowercase_html_names(bool x) {
set_option(x, &lowercase_html_names_);
}
bool lowercase_html_names() const { return lowercase_html_names_.value(); }
void set_always_rewrite_css(bool x) {
set_option(x, &always_rewrite_css_);
}
bool always_rewrite_css() const { return always_rewrite_css_.value(); }
void set_respect_vary(bool x) {
set_option(x, &respect_vary_);
}
bool respect_vary() const { return respect_vary_.value(); }
void set_respect_x_forwarded_proto(bool x) {
set_option(x, &respect_x_forwarded_proto_);
}
bool respect_x_forwarded_proto() const {
return respect_x_forwarded_proto_.value();
}
void set_flush_html(bool x) { set_option(x, &flush_html_); }
bool flush_html() const { return flush_html_.value(); }
void set_serve_split_html_in_two_chunks(bool x) {
set_option(x, &serve_split_html_in_two_chunks_);
}
bool serve_split_html_in_two_chunks() const {
return serve_split_html_in_two_chunks_.value();
}
void set_serve_stale_if_fetch_error(bool x) {
set_option(x, &serve_stale_if_fetch_error_);
}
bool serve_stale_if_fetch_error() const {
return serve_stale_if_fetch_error_.value();
}
void set_serve_ghost_click_buster_with_split_html(bool x) {
set_option(x, &serve_ghost_click_buster_with_split_html_);
}
bool serve_ghost_click_buster_with_split_html() const {
return serve_ghost_click_buster_with_split_html_.value();
}
void set_serve_xhr_access_control_headers(bool x) {
set_option(x, &serve_xhr_access_control_headers_);
}
bool serve_xhr_access_control_headers() const {
return serve_xhr_access_control_headers_.value();
}
void set_proactively_freshen_user_facing_request(bool x) {
set_option(x, &proactively_freshen_user_facing_request_);
}
bool proactively_freshen_user_facing_request() const {
return proactively_freshen_user_facing_request_.value();
}
void set_serve_stale_while_revalidate_threshold_sec(int64 x) {
set_option(x, &serve_stale_while_revalidate_threshold_sec_);
}
int64 serve_stale_while_revalidate_threshold_sec() const {
return serve_stale_while_revalidate_threshold_sec_.value();
}
void set_enable_flush_early_critical_css(bool x) {
set_option(x, &enable_flush_early_critical_css_);
}
bool enable_flush_early_critical_css() const {
return enable_flush_early_critical_css_.value();
}
void set_use_selectors_for_critical_css(bool x) {
set_option(x, &use_selectors_for_critical_css_);
}
bool use_selectors_for_critical_css() const {
return use_selectors_for_critical_css_.value();
}
void set_default_cache_html(bool x) { set_option(x, &default_cache_html_); }
bool default_cache_html() const { return default_cache_html_.value(); }
void set_modify_caching_headers(bool x) {
set_option(x, &modify_caching_headers_);
}
bool modify_caching_headers() const {
return modify_caching_headers_.value();
}
void set_inline_only_critical_images(bool x) {
set_option(x, &inline_only_critical_images_);
}
bool inline_only_critical_images() const {
return inline_only_critical_images_.value();
}
void set_critical_images_beacon_enabled(bool x) {
set_option(x, &critical_images_beacon_enabled_);
}
bool critical_images_beacon_enabled() const {
return critical_images_beacon_enabled_.value();
}
void set_beacon_reinstrument_time_sec(int x) {
set_option(x, &beacon_reinstrument_time_sec_);
}
int beacon_reinstrument_time_sec() const {
return beacon_reinstrument_time_sec_.value();
}
void set_accept_invalid_signatures(bool x) {
set_option(x, &accept_invalid_signatures_);
}
bool accept_invalid_signatures() const {
return accept_invalid_signatures_.value();
}
void set_remote_configuration_timeout_ms(int64 x) {
set_option(x, &remote_configuration_timeout_ms_);
}
int64 remote_configuration_timeout_ms() const {
return remote_configuration_timeout_ms_.value();
}
void set_remote_configuration_url(StringPiece p) {
set_option(GoogleString(p.data(), p.size()), &remote_configuration_url_);
}
const GoogleString& remote_configuration_url() const {
return remote_configuration_url_.value();
}
void set_http_cache_compression_level(int x) {
set_option(x, &http_cache_compression_level_);
}
int http_cache_compression_level() const {
return http_cache_compression_level_.value();
}
void set_request_option_override(StringPiece p) {
set_option(GoogleString(p.data(), p.size()), &request_option_override_);
}
const GoogleString& request_option_override() const {
return request_option_override_.value();
}
void set_url_signing_key(StringPiece p) {
set_option(GoogleString(p.data(), p.size()), &url_signing_key_);
}
const GoogleString& url_signing_key() const {
return url_signing_key_.value();
}
void set_lazyload_images_after_onload(bool x) {
set_option(x, &lazyload_images_after_onload_);
}
bool lazyload_images_after_onload() const {
return lazyload_images_after_onload_.value();
}
void set_lazyload_images_blank_url(StringPiece p) {
set_option(GoogleString(p.data(), p.size()), &lazyload_images_blank_url_);
}
const GoogleString& lazyload_images_blank_url() const {
return lazyload_images_blank_url_.value();
}
void set_max_inlined_preview_images_index(int x) {
set_option(x, &max_inlined_preview_images_index_);
}
int max_inlined_preview_images_index() const {
return max_inlined_preview_images_index_.value();
}
void set_use_blank_image_for_inline_preview(bool x) {
set_option(x, &use_blank_image_for_inline_preview_);
}
bool use_blank_image_for_inline_preview() const {
return use_blank_image_for_inline_preview_.value();
}
void set_min_image_size_low_resolution_bytes(int64 x) {
set_option(x, &min_image_size_low_resolution_bytes_);
}
int64 min_image_size_low_resolution_bytes() const {
return min_image_size_low_resolution_bytes_.value();
}
void set_max_image_size_low_resolution_bytes(int64 x) {
set_option(x, &max_image_size_low_resolution_bytes_);
}
int64 max_image_size_low_resolution_bytes() const {
return max_image_size_low_resolution_bytes_.value();
}
void set_experiment_cookie_duration_ms(int64 x) {
set_option(x, &experiment_cookie_duration_ms_);
}
int64 experiment_cookie_duration_ms() const {
return experiment_cookie_duration_ms_.value();
}
void set_finder_properties_cache_expiration_time_ms(int64 x) {
set_option(x, &finder_properties_cache_expiration_time_ms_);
}
int64 finder_properties_cache_expiration_time_ms() const {
return finder_properties_cache_expiration_time_ms_.value();
}
void set_finder_properties_cache_refresh_time_ms(int64 x) {
set_option(x, &finder_properties_cache_refresh_time_ms_);
}
int64 finder_properties_cache_refresh_time_ms() const {
return finder_properties_cache_refresh_time_ms_.value();
}
void set_rewrite_random_drop_percentage(int x) {
set_option(x, &rewrite_random_drop_percentage_);
}
int rewrite_random_drop_percentage() const {
return rewrite_random_drop_percentage_.value();
}
// css_preserve_urls() is determined by the following rules in order:
// 1. Value set by the user, if the user has explicitly set it.
// 2. Default value (true) for OptimizeForBandwidth, if this is the rewrite
// level.
// 3. Default value (true) for MobilizeFilters, if this is the rewrite level.
// 4. Default value (false) otherwise.
bool css_preserve_urls() const {
return (CheckBandwidthOption(css_preserve_urls_) ||
CheckMobilizeFiltersOption(css_preserve_urls_));
}
void set_css_preserve_urls(bool x) {
set_option(x, &css_preserve_urls_);
}
bool image_preserve_urls() const {
return CheckBandwidthOption(image_preserve_urls_);
}
void set_image_preserve_urls(bool x) {
set_option(x, &image_preserve_urls_);
}
bool js_preserve_urls() const {
return CheckBandwidthOption(js_preserve_urls_);
}
void set_js_preserve_urls(bool x) {
set_option(x, &js_preserve_urls_);
}
void set_metadata_cache_staleness_threshold_ms(int64 x) {
set_option(x, &metadata_cache_staleness_threshold_ms_);
}
int64 metadata_cache_staleness_threshold_ms() const {
return metadata_cache_staleness_threshold_ms_.value();
}
void set_metadata_input_errors_cache_ttl_ms(int64 x) {
set_option(x, &metadata_input_errors_cache_ttl_ms_);
}
int64 metadata_input_errors_cache_ttl_ms() const {
return metadata_input_errors_cache_ttl_ms_.value();
}
const GoogleString& downstream_cache_purge_method() const {
return downstream_cache_purge_method_.value();
}
void set_downstream_cache_purge_method(StringPiece p) {
set_option(p.as_string(), &downstream_cache_purge_method_);
}
const GoogleString& downstream_cache_purge_location_prefix() const {
return downstream_cache_purge_location_prefix_.value();
}
void set_downstream_cache_purge_location_prefix(StringPiece p) {
// Remove any trailing slashes. Leaving them in causes the request to have
// multiple trailing slashes.
while (p.ends_with("/")) {
p.remove_suffix(1);
}
set_option(p.as_string(), &downstream_cache_purge_location_prefix_);
}
bool IsDownstreamCacheIntegrationEnabled() const {
return !downstream_cache_purge_location_prefix().empty();
}
void set_downstream_cache_rebeaconing_key(StringPiece p) {
set_option(p.as_string(), &downstream_cache_rebeaconing_key_);
}
const GoogleString& downstream_cache_rebeaconing_key() const {
return downstream_cache_rebeaconing_key_.value();
}
bool IsDownstreamCacheRebeaconingKeyConfigured() const {
return !downstream_cache_rebeaconing_key().empty();
}
// Return true only if downstream cache rebeaconing key is configured and
// the key argument matches the configured key.
bool MatchesDownstreamCacheRebeaconingKey(StringPiece key) const {
if (!IsDownstreamCacheRebeaconingKeyConfigured()) {
return false;
}
return StringCaseEqual(key, downstream_cache_rebeaconing_key());
}
void set_downstream_cache_rewritten_percentage_threshold(int64 x) {
set_option(x, &downstream_cache_rewritten_percentage_threshold_);
}
int64 downstream_cache_rewritten_percentage_threshold() const {
return downstream_cache_rewritten_percentage_threshold_.value();
}
const BeaconUrl& beacon_url() const { return beacon_url_.value(); }
void set_beacon_url(const GoogleString& beacon_url) {
GoogleString ignored_error_detail;
beacon_url_.SetFromString(beacon_url, &ignored_error_detail);
}
// Return false in a subclass if you want to disallow all URL trimming in CSS.
virtual bool trim_urls_in_css() const { return true; }
void set_image_jpeg_recompress_quality(int64 x) {
set_option(x, &image_jpeg_recompress_quality_);
}
void set_image_jpeg_recompress_quality_for_small_screens(int64 x) {
set_option(x, &image_jpeg_recompress_quality_for_small_screens_);
}
void set_image_jpeg_quality_for_save_data(int64 x) {
set_option(x, &image_jpeg_quality_for_save_data_);
}
int64 image_recompress_quality() const {
return image_recompress_quality_.value();
}
void set_image_recompress_quality(int64 x) {
set_option(x, &image_recompress_quality_);
}
int image_limit_optimized_percent() const {
return image_limit_optimized_percent_.value();
}
void set_image_limit_optimized_percent(int x) {
set_option(x, &image_limit_optimized_percent_);
}
int image_limit_resize_area_percent() const {
return image_limit_resize_area_percent_.value();
}
void set_image_limit_resize_area_percent(int x) {
set_option(x, &image_limit_resize_area_percent_);
}
int image_limit_rendered_area_percent() const {
return image_limit_rendered_area_percent_.value();
}
void set_image_limit_rendered_area_percent(int x) {
set_option(x, &image_limit_rendered_area_percent_);
}
int64 image_jpeg_num_progressive_scans() const {
return image_jpeg_num_progressive_scans_.value();
}
void set_image_jpeg_num_progressive_scans(int64 x) {
set_option(x, &image_jpeg_num_progressive_scans_);
}
void set_image_jpeg_num_progressive_scans_for_small_screens(int64 x) {
set_option(x, &image_jpeg_num_progressive_scans_for_small_screens_);
}
void set_image_webp_recompress_quality(int64 x) {
set_option(x, &image_webp_recompress_quality_);
}
void set_image_webp_recompress_quality_for_small_screens(int64 x) {
set_option(x, &image_webp_recompress_quality_for_small_screens_);
}
void set_image_webp_animated_recompress_quality(int64 x) {
set_option(x, &image_webp_animated_recompress_quality_);
}
void set_image_webp_quality_for_save_data(int64 x) {
set_option(x, &image_webp_quality_for_save_data_);
}
int64 image_webp_timeout_ms() const {
return image_webp_timeout_ms_.value();
}
void set_image_webp_timeout_ms(int64 x) {
set_option(x, &image_webp_timeout_ms_);
}
bool domain_rewrite_hyperlinks() const {
return CheckMobilizeFiltersOption(domain_rewrite_hyperlinks_);
}
void set_domain_rewrite_hyperlinks(bool x) {
set_option(x, &domain_rewrite_hyperlinks_);
}
bool domain_rewrite_cookies() const {
return CheckMobilizeFiltersOption(domain_rewrite_cookies_);
}
void set_domain_rewrite_cookies(bool x) {
set_option(x, &domain_rewrite_cookies_);
}
bool client_domain_rewrite() const {
return client_domain_rewrite_.value();
}
void set_client_domain_rewrite(bool x) {
set_option(x, &client_domain_rewrite_);
}
void set_flush_more_resources_early_if_time_permits(bool x) {
set_option(x, &flush_more_resources_early_if_time_permits_);
}
bool flush_more_resources_early_if_time_permits() const {
return flush_more_resources_early_if_time_permits_.value();
}
void set_flush_more_resources_in_ie_and_firefox(bool x) {
set_option(x, &flush_more_resources_in_ie_and_firefox_);
}
bool flush_more_resources_in_ie_and_firefox() const {
return flush_more_resources_in_ie_and_firefox_.value();
}
void set_max_prefetch_js_elements(int x) {
set_option(x, &max_prefetch_js_elements_);
}
int max_prefetch_js_elements() const {
return max_prefetch_js_elements_.value();
}
void set_enable_defer_js_experimental(bool x) {
set_option(x, &enable_defer_js_experimental_);
}
bool enable_defer_js_experimental() const {
return enable_defer_js_experimental_.value();
}
void set_disable_rewrite_on_no_transform(bool x) {
set_option(x, &disable_rewrite_on_no_transform_);
}
bool disable_rewrite_on_no_transform() const {
return disable_rewrite_on_no_transform_.value();
}
void set_disable_background_fetches_for_bots(bool x) {
set_option(x, &disable_background_fetches_for_bots_);
}
bool disable_background_fetches_for_bots() const {
return disable_background_fetches_for_bots_.value();
}
void set_enable_cache_purge(bool x) {
set_option(x, &enable_cache_purge_);
}
bool enable_cache_purge() const {
return enable_cache_purge_.value();
}
void set_proactive_resource_freshening(bool x) {
set_option(x, &proactive_resource_freshening_);
}
bool proactive_resource_freshening() const {
return proactive_resource_freshening_.value();
}
void set_lazyload_highres_images(bool x) {
set_option(x, &lazyload_highres_images_);
}
bool lazyload_highres_images() const {
return lazyload_highres_images_.value();
}
void set_enable_blink_debug_dashboard(bool x) {
set_option(x, &enable_blink_debug_dashboard_);
}
bool enable_blink_debug_dashboard() const {
return enable_blink_debug_dashboard_.value();
}
void set_enable_blink_html_change_detection(bool x) {
set_option(x, &enable_blink_html_change_detection_);
}
bool enable_blink_html_change_detection() const {
return enable_blink_html_change_detection_.value();
}
void set_enable_blink_html_change_detection_logging(bool x) {
set_option(x, &enable_blink_html_change_detection_logging_);
}
bool enable_blink_html_change_detection_logging() const {
return enable_blink_html_change_detection_logging_.value();
}
void set_use_smart_diff_in_blink(bool x) {
set_option(x, &use_smart_diff_in_blink_);
}
bool use_smart_diff_in_blink() const {
return use_smart_diff_in_blink_.value();
}
void set_use_fallback_property_cache_values(bool x) {
set_option(x, &use_fallback_property_cache_values_);
}
bool use_fallback_property_cache_values() const {
return use_fallback_property_cache_values_.value();
}
void set_await_pcache_lookup(bool x) {
set_option(x, &await_pcache_lookup_);
}
bool await_pcache_lookup() const {
return await_pcache_lookup_.value();
}
void set_enable_prioritizing_scripts(bool x) {
set_option(x, &enable_prioritizing_scripts_);
}
bool enable_prioritizing_scripts() const {
return enable_prioritizing_scripts_.value();
}
void set_blink_html_change_detection_time_ms(int64 x) {
set_option(x, &blink_html_change_detection_time_ms_);
}
int64 blink_html_change_detection_time_ms() const {
return blink_html_change_detection_time_ms_.value();
}
const GoogleString& blocking_rewrite_key() const {
return blocking_rewrite_key_.value();
}
void set_blocking_rewrite_key(StringPiece p) {
set_option(p.as_string(), &blocking_rewrite_key_);
}
void EnableBlockingRewriteForRefererUrlPattern(
StringPiece url_pattern) {
Modify();
blocking_rewrite_referer_urls_.MakeWriteable()->Allow(url_pattern);
}
bool IsBlockingRewriteEnabledForReferer(StringPiece url) const {
return blocking_rewrite_referer_urls_->Match(url, false);
}
bool IsBlockingRewriteRefererUrlPatternPresent() const {
return blocking_rewrite_referer_urls_->num_wildcards() > 0;
}
bool rewrite_uncacheable_resources() const {
return rewrite_uncacheable_resources_.value();
}
void set_rewrite_uncacheable_resources(bool x) {
set_option(x, &rewrite_uncacheable_resources_);
}
void set_running_experiment(bool x) {
set_option(x, &running_experiment_);
}
bool running_experiment() const {
return running_experiment_.value();
}
// x should be between 1 and 5 inclusive.
void set_experiment_ga_slot(int x) {
set_option(x, &experiment_ga_slot_);
}
int experiment_ga_slot() const { return experiment_ga_slot_.value(); }
void set_enroll_experiment_id(int x) {
set_option(x, &enroll_experiment_id_);
}
int enroll_experiment_id() const { return enroll_experiment_id_.value(); }
void set_report_unload_time(bool x) {
set_option(x, &report_unload_time_);
}
bool report_unload_time() const {
return report_unload_time_.value();
}
void set_implicit_cache_ttl_ms(int64 x) {
set_option(x, &implicit_cache_ttl_ms_);
}
int64 implicit_cache_ttl_ms() const {
return implicit_cache_ttl_ms_.value();
}
void set_load_from_file_cache_ttl_ms(int64 x) {
set_option(x, &load_from_file_cache_ttl_ms_);
}
int64 load_from_file_cache_ttl_ms() const {
return load_from_file_cache_ttl_ms_.value();
}
bool load_from_file_cache_ttl_ms_was_set() const {
return load_from_file_cache_ttl_ms_.was_set();
}
void set_x_header_value(StringPiece p) {
set_option(p.as_string(), &x_header_value_);
}
const GoogleString& x_header_value() const {
return x_header_value_.value();
}
void set_distributed_rewrite_key(StringPiece p) {
set_option(p.as_string(), &distributed_rewrite_key_);
}
const GoogleString& distributed_rewrite_key() const {
return distributed_rewrite_key_.value();
}
void set_distribute_fetches(bool x) {
set_option(x, &distribute_fetches_);
}
bool distribute_fetches() const {
return distribute_fetches_.value();
}
void set_distributed_rewrite_servers(StringPiece p) {
set_option(p.as_string(), &distributed_rewrite_servers_);
}
const GoogleString& distributed_rewrite_servers() const {
return distributed_rewrite_servers_.value();
}
void set_distributed_rewrite_timeout_ms(const int64 x) {
set_option(x, &distributed_rewrite_timeout_ms_);
}
int64 distributed_rewrite_timeout_ms() const {
return distributed_rewrite_timeout_ms_.value();
}
void set_avoid_renaming_introspective_javascript(bool x) {
set_option(x, &avoid_renaming_introspective_javascript_);
}
bool avoid_renaming_introspective_javascript() const {
return avoid_renaming_introspective_javascript_.value();
}
int64 blink_max_html_size_rewritable() const {
return blink_max_html_size_rewritable_.value();
}
void set_blink_max_html_size_rewritable(int64 x) {
set_option(x, &blink_max_html_size_rewritable_);
}
void set_critical_line_config(StringPiece p) {
set_option(GoogleString(p.data(), p.size()), &critical_line_config_);
}
const GoogleString& critical_line_config() const {
return critical_line_config_.value();
}
void set_forbid_all_disabled_filters(bool x) {
set_option(x, &forbid_all_disabled_filters_);
}
bool forbid_all_disabled_filters() const {
return forbid_all_disabled_filters_.value();
}
bool reject_blacklisted() const { return reject_blacklisted_.value(); }
void set_reject_blacklisted(bool x) {
set_option(x, &reject_blacklisted_);
}
HttpStatus::Code reject_blacklisted_status_code() const {
return static_cast<HttpStatus::Code>(
reject_blacklisted_status_code_.value());
}
void set_reject_blacklisted_status_code(HttpStatus::Code x) {
set_option(static_cast<int>(x), &reject_blacklisted_status_code_);
}
bool support_noscript_enabled() const {
return support_noscript_enabled_.value();
}
void set_support_noscript_enabled(bool x) {
set_option(x, &support_noscript_enabled_);
}
bool enable_extended_instrumentation() const {
return enable_extended_instrumentation_.value();
}
void set_enable_extended_instrumentation(bool x) {
set_option(x, &enable_extended_instrumentation_);
}
bool use_experimental_js_minifier() const {
return use_experimental_js_minifier_.value();
}
void set_use_experimental_js_minifier(bool x) {
set_option(x, &use_experimental_js_minifier_);
}
void set_max_combined_css_bytes(int64 x) {
set_option(x, &max_combined_css_bytes_);
}
int64 max_combined_css_bytes() const {
return max_combined_css_bytes_.value();
}
void set_max_combined_js_bytes(int64 x) {
set_option(x, &max_combined_js_bytes_);
}
int64 max_combined_js_bytes() const {
return max_combined_js_bytes_.value();
}
void set_pre_connect_url(StringPiece p) {
set_option(GoogleString(p.data(), p.size()), &pre_connect_url_);
}
const GoogleString& pre_connect_url() const {
return pre_connect_url_.value();
}
void set_property_cache_http_status_stability_threshold(int x) {
set_option(x, &property_cache_http_status_stability_threshold_);
}
int property_cache_http_status_stability_threshold() const {
return property_cache_http_status_stability_threshold_.value();
}
void set_max_rewrite_info_log_size(int x) {
set_option(x, &max_rewrite_info_log_size_);
}
int max_rewrite_info_log_size() const {
return max_rewrite_info_log_size_.value();
}
void set_enable_aggressive_rewriters_for_mobile(bool x) {
set_option(x, &enable_aggressive_rewriters_for_mobile_);
}
bool enable_aggressive_rewriters_for_mobile() const {
return enable_aggressive_rewriters_for_mobile_.value();
}
void set_allow_logging_urls_in_log_record(bool x) {
set_option(x, &allow_logging_urls_in_log_record_);
}
bool allow_logging_urls_in_log_record() const {
return allow_logging_urls_in_log_record_.value();
}
void set_allow_options_to_be_set_by_cookies(bool x) {
set_option(x, &allow_options_to_be_set_by_cookies_);
}
bool allow_options_to_be_set_by_cookies() const {
return allow_options_to_be_set_by_cookies_.value();
}
void set_non_cacheables_for_cache_partial_html(StringPiece p) {
set_option(p.as_string(), &non_cacheables_for_cache_partial_html_);
}
const GoogleString& non_cacheables_for_cache_partial_html() const {
return non_cacheables_for_cache_partial_html_.value();
}
void set_no_transform_optimized_images(bool x) {
set_option(x, &no_transform_optimized_images_);
}
bool no_transform_optimized_images() const {
return no_transform_optimized_images_.value();
}
void set_access_control_allow_origins(StringPiece p) {
set_option(p.as_string(), &access_control_allow_origins_);
}
const GoogleString& access_control_allow_origins() const {
return access_control_allow_origins_.value();
}
void set_hide_referer_using_meta(bool x) {
set_option(x, &hide_referer_using_meta_);
}
bool hide_referer_using_meta() const {
return hide_referer_using_meta_.value();
}
void set_max_low_res_image_size_bytes(int64 x) {
set_option(x, &max_low_res_image_size_bytes_);
}
int64 max_low_res_image_size_bytes() const {
return max_low_res_image_size_bytes_.value();
}
void set_max_low_res_to_full_res_image_size_percentage(int x) {
set_option(x, &max_low_res_to_full_res_image_size_percentage_);
}
int max_low_res_to_full_res_image_size_percentage() const {
return max_low_res_to_full_res_image_size_percentage_.value();
}
void set_serve_rewritten_webp_urls_to_any_agent(bool x) {
set_option(x, &serve_rewritten_webp_urls_to_any_agent_);
}
bool serve_rewritten_webp_urls_to_any_agent() const {
return serve_rewritten_webp_urls_to_any_agent_.value();
}
void set_cache_fragment(StringPiece p) {
set_option(p.as_string(), &cache_fragment_);
}
const GoogleString& cache_fragment() const {
return cache_fragment_.value();
}
void set_sticky_query_parameters(StringPiece p) {
set_option(p.as_string(), &sticky_query_parameters_);
}
const GoogleString& sticky_query_parameters() const {
return sticky_query_parameters_.value();
}
void set_option_cookies_duration_ms(int64 x) {
set_option(x, &option_cookies_duration_ms_);
}
int64 option_cookies_duration_ms() const {
return option_cookies_duration_ms_.value();
}
void set_responsive_image_densities(const ResponsiveDensities& x) {
set_option(x, &responsive_image_densities_);
}
const ResponsiveDensities& responsive_image_densities() const {
return responsive_image_densities_.value();
}
bool mob_always() const { return mob_always_.value(); }
void set_mob_always(bool x) { set_option(x, &mob_always_); }
bool mob_config() const { return mob_config_.value(); }
bool mob_iframe() const { return mob_iframe_.value(); }
const GoogleString& mob_iframe_viewport() const {
return mob_iframe_viewport_.value();
}
bool mob_iframe_disable() const { return mob_iframe_disable_.value(); }
bool mob_layout() const { return mob_layout_.value(); }
void set_mob_beacon_url(StringPiece x) {
set_option(x.as_string(), &mob_beacon_url_);
}
const GoogleString& mob_beacon_url() const { return mob_beacon_url_.value(); }
void set_mob_beacon_category(StringPiece x) {
set_option(x.as_string(), &mob_beacon_category_);
}
const GoogleString& mob_beacon_category() const {
return mob_beacon_category_.value();
}
void set_mob_phone_number(StringPiece x) {
set_option(x.as_string(), &mob_phone_number_);
}
const GoogleString& mob_phone_number() const {
return mob_phone_number_.value();
}
void set_mob_map_location(StringPiece x) {
set_option(x.as_string(), &mob_map_location_);
}
const GoogleString& mob_map_location() const {
return mob_map_location_.value();
}
void set_mob_config(bool x) { set_option(x, &mob_config_); }
void set_mob_iframe(bool x) { set_option(x, &mob_iframe_); }
void set_mob_iframe_disable(bool x) { set_option(x, &mob_iframe_disable_); }
void set_mob_iframe_viewport(StringPiece x) {
set_option(x.as_string(), &mob_iframe_viewport_);
}
void set_mob_layout(bool x) { set_option(x, &mob_layout_); }
bool mob_nav() const {
return CheckMobilizeFiltersOption(mob_nav_);
}
void set_mob_nav(bool x) { set_option(x, &mob_nav_); }
bool mob_labeled_mode() const { return mob_labeled_mode_.value(); }
void set_mob_labeled_mode(bool x) { set_option(x, &mob_labeled_mode_); }
const GoogleString& mob_nav_classes() const {
return mob_nav_classes_.value();
}
void set_mob_nav_classes(StringPiece p) {
set_option(p.as_string(), &mob_nav_classes_);
}
bool has_mob_nav_classes() const { return mob_nav_classes_.was_set(); }
// Should menu extraction be run?
bool MobRenderServerSideMenus() const {
return (Enabled(kMobilize) && !mob_labeled_mode());
}
// Should labeling be run in the request flow?
bool MobUseLabelFilter() const {
// We use the label filter if we're doing mobilization. But we don't run
// it in iframe mode, ever, because that doesn't see the page we'd be
// extracting mobilization data from. We used to not run it if we were
// doing nav server side, and should consider doing that again -- but if
// something goes wrong we can't then fall back to client-side navigation.
return (Enabled(kMobilize) && !mob_iframe() && !mob_labeled_mode());
}
bool mob_static() const { return mob_static_.value(); }
void set_mob_static(bool x) { set_option(x, &mob_static_); }
const MobTheme& mob_theme() const { return mob_theme_.value(); }
void set_mob_theme(const MobTheme& x) {
set_option(x, &mob_theme_);
}
bool has_mob_theme() const { return mob_theme_.was_set(); }
int64 mob_conversion_id() const { return mob_conversion_id_.value(); }
void set_mob_conversion_id(int64 x) { set_option(x, &mob_conversion_id_); }
const GoogleString& mob_map_conversion_label() const {
return mob_map_conversion_label_.value();
}
void set_mob_map_conversion_label(StringPiece x) {
set_option(x.as_string(), &mob_map_conversion_label_);
}
const GoogleString& mob_phone_conversion_label() const {
return mob_phone_conversion_label_.value();
}
void set_mob_phone_conversion_label(StringPiece x) {
set_option(x.as_string(), &mob_phone_conversion_label_);
}
// Merge src into 'this'. Generally, options that are explicitly
// set in src will override those explicitly set in 'this' (except that
// filters forbidden in 'this' cannot be enabled by 'src'), although
// option Merge implementations can be redefined by specific Option
// class implementations (e.g. OptionInt64MergeWithMax). One
// semantic subject to interpretation is when a core-filter is
// disabled in the first set and not in the second. My judgement is
// that the 'disable' from 'this' should override the core-set
// membership in the 'src', but not an 'enable' in the 'src'.
//
// You can make an exact duplicate of RewriteOptions object 'src' via
// (new 'typeof src')->Merge(src), aka Clone().
//
// Merge expects that 'src' and 'this' are the same type. If that's
// not true, this function will DCHECK.
virtual void Merge(const RewriteOptions& src);
// Merge the process scope options (including strict ones) from src into
// this.
void MergeOnlyProcessScopeOptions(const RewriteOptions& src);
// Registers a wildcard pattern for to be allowed, potentially overriding
// previous Disallow wildcards.
void Allow(StringPiece wildcard_pattern) {
Modify();
allow_resources_.MakeWriteable()->Allow(wildcard_pattern);
}
// Registers a wildcard pattern for to be disallowed, potentially overriding
// previous Allow wildcards.
void Disallow(StringPiece wildcard_pattern) {
Modify();
allow_resources_.MakeWriteable()->Disallow(wildcard_pattern);
}
// Like Allow(). See IsAllowedWhenInlining().
void AllowWhenInlining(StringPiece wildcard_pattern) {
Modify();
allow_when_inlining_resources_.MakeWriteable()->Allow(wildcard_pattern);
}
// Helper function to Disallow something except when inlining. Useful for
// resources that you expect to be on good CDNs but may still be worth
// inlining if small enough.
void AllowOnlyWhenInlining(StringPiece wildcard_pattern) {
Disallow(wildcard_pattern);
AllowWhenInlining(wildcard_pattern);
}
// Like Disallow(). See IsAllowedWhenInlining().
void DisallowWhenInlining(StringPiece wildcard_pattern) {
Modify();
allow_when_inlining_resources_.MakeWriteable()->Disallow(wildcard_pattern);
}
// Blacklist of javascript files that don't like their names changed.
// This should be called for root options to set defaults.
// TODO(sligocki): Rename to allow for more general initialization.
virtual void DisallowTroublesomeResources();
// Disallows resources that are served on well-distributed CDNs
// already, and are likely to be in browser-caches, or that are
// troublesome resources stored on external domains. Note: this is
// not currently called by mod_pagespeed.
virtual void DisallowResourcesForProxy();
// When someone asks for a readonly lawyer, we can return a pointer to
// the potentially shared DomainLawyer* object. But if you want a mutable
// one, we clone whatever Lawyer we had and detach it from the shared
// group. Here are several scenarios.
// 1. We are setting up the global_options() for a ServerContext on
// startup. There will be no concurrent access, and at this point
// there will be no sharing with other RewriteOptions.
// 2. We are merging down global_options() based on the
// vhost/directory/.htaccess data and need to update (among
// other things) the settings. This may happen concurrently for
// several different server-scoped, directory-scoped, or request-scoped
// RewriteOptions objects. Those will all be attached to their
// parent when the options get created. However writing to these
// will effectively detach them.
// One case that would be problematic is a mutation of a parent
// RewriteOptions->WriteableDomainLawyer() concurrent with instantiating
// a new child RewriteOptions. However this does not occur in our system.
//
// The only similar place this does occur is cache_invalidation_timestamp_
// which can be mutated when there are active children.
const DomainLawyer* domain_lawyer() const { return domain_lawyer_.get(); }
DomainLawyer* WriteableDomainLawyer();
FileLoadPolicy* file_load_policy() { return &file_load_policy_; }
const FileLoadPolicy* file_load_policy() const { return &file_load_policy_; }
// Determines, based on the sequence of Allow/Disallow calls above, whether
// a url is allowed.
bool IsAllowed(StringPiece url) const {
return allow_resources_->Match(url, true /* default allow */);
}
// Call this when:
//
// 1. IsAllowed() returns false and
// 2. The url is for a resource we're planning to inline if successful.
//
// If it returns true, it's ok to fetch, rewrite, and inline this resource as
// if IsAllowed() had returned true.
bool IsAllowedWhenInlining(StringPiece url) const {
return allow_when_inlining_resources_->Match(
url, false /* default disallow */);
}
// Adds a new comment wildcard pattern to be retained.
void RetainComment(StringPiece comment) {
Modify();
retain_comments_.MakeWriteable()->Allow(comment);
}
// If enabled, the 'remove_comments' filter will remove all HTML comments.
// As discussed in Issue 237, some comments have semantic value and must
// be retained.
bool IsRetainedComment(StringPiece comment) const {
return retain_comments_->Match(comment, false);
}
// Adds a new class name for which lazyload should be disabled.
void DisableLazyloadForClassName(StringPiece class_name) {
Modify();
lazyload_enabled_classes_.MakeWriteable()->Disallow(class_name);
}
// Checks if lazyload images is enabled for the specified class.
bool IsLazyloadEnabledForClassName(StringPiece class_name) const {
return lazyload_enabled_classes_->Match(class_name, true);
}
void set_override_caching_ttl_ms(int64 x) {
set_option(x, &override_caching_ttl_ms_);
}
int64 override_caching_ttl_ms() const {
return override_caching_ttl_ms_.value();
}
// Overrides the cache ttl for all urls matching the wildcard with
// override_caching_ttl_ms().
void AddOverrideCacheTtl(StringPiece wildcard) {
Modify();
override_caching_wildcard_.MakeWriteable()->Allow(wildcard);
}
// Is the cache TTL overridden for the given url?
bool IsCacheTtlOverridden(StringPiece url) const {
return override_caching_wildcard_->Match(url, false);
}
void AddRejectedUrlWildcard(const GoogleString& wildcard) {
AddRejectedHeaderWildcard(kRejectedRequestUrlKeyName, wildcard);
}
void AddRejectedHeaderWildcard(StringPiece header_name,
const GoogleString& wildcard) {
Modify();
std::pair<FastWildcardGroupMap::iterator, bool> insert_result =
rejected_request_map_.insert(std::make_pair(
header_name, static_cast<FastWildcardGroup*>(NULL)));
if (insert_result.second) {
insert_result.first->second = new FastWildcardGroup;
}
insert_result.first->second->Allow(wildcard);
}
void set_min_cache_ttl_ms(int64 x) {
set_option(x, &min_cache_ttl_ms_);
}
int64 min_cache_ttl_ms() const {
return min_cache_ttl_ms_.value();
}
// Determine if the request url needs to be declined based on the url,
// request headers and rewrite options.
bool IsRequestDeclined(const GoogleString& url,
const RequestHeaders* request_headers) const;
// Make an identical copy of these options and return it. This does
// *not* copy the signature, and the returned options are not in
// a frozen state.
virtual RewriteOptions* Clone() const;
// Make an empty options object of the same type as this.
virtual RewriteOptions* NewOptions() const;
// Computes a signature for the RewriteOptions object, including all
// contained classes (DomainLawyer, FileLoadPolicy, WildCardGroups).
//
// Computing a signature "freezes" the class instance. Attempting
// to modify a RewriteOptions after freezing will DCHECK.
void ComputeSignature() LOCKS_EXCLUDED(cache_purge_mutex_.get());
void ComputeSignatureLockHeld() SHARED_LOCKS_REQUIRED(cache_purge_mutex_);
// If you subclass RewriteOptions and store any configuration data that's not
// an Option, use this hook to include the signature of your additional data.
virtual GoogleString SubclassSignatureLockHeld() { return ""; }
// Freeze a RewriteOptions so we can't modify it anymore and thus
// know that it's safe to read it from multiple threads, but don't
// bother calculating its signature since we will only be using this
// instance for merging and cloning.
void Freeze();
// Clears the computed signature, unfreezing the options object.
// Warning: Please note that using this method is extremely risky and should
// be avoided as much as possible. If you are planning to use this, please
// discuss this with your team-mates and ensure that you clearly understand
// its implications. Also, please do repeat this warning at every place you
// use this method.
//
// Returns true if the signature was previously computed, and thus should
// be recomputed after modification.
bool ClearSignatureWithCaution();
bool frozen() const { return frozen_; }
// Clears a computed signature, unfreezing the options object. This
// is intended for testing. Returns whether the options were frozen
// in the first place.
bool ClearSignatureForTesting() {
bool frozen = frozen_;
ClearSignatureWithCaution();
return frozen;
}
// Returns the computed signature.
const GoogleString& signature() const {
// We take a reader-lock because we may be looking at the
// global_options signature concurrent with updating it if someone
// flushes cache. Note that the default mutex implementation is
// NullRWLock, which isn't actually a mutex. Only (currently) for the
// Apache global_options() object do we create a real mutex. We
// don't expect contention here because we take a reader-lock and the
// only time we Write is if someone flushes the cache.
ThreadSystem::ScopedReader lock(cache_purge_mutex_.get());
DCHECK(frozen_);
DCHECK(!signature_.empty());
return signature_;
}
virtual GoogleString OptionsToString() const;
GoogleString FilterSetToString(const FilterSet& filter_set) const;
GoogleString EnabledFiltersToString() const;
// Returns a string containing the enabled options which do not leak sensitive
// information about the server state.
GoogleString SafeEnabledOptionsToString() const;
// Returns a string identifying the currently running experiment to be used in
// tagging Google Analytics data.
virtual GoogleString ToExperimentString() const;
// Returns a string with more information about the currently running
// experiment. Primarily used for tagging Google Analytics data. This format
// is not at all specific to Google Analytics, however.
virtual GoogleString ToExperimentDebugString() const;
// Convert an id string like "ah" to a Filter enum like kAddHead.
// Returns kEndOfFilters if the id isn't known.
static Filter LookupFilterById(const StringPiece& filter_id);
// Convert the filter name to a Filter.
static Filter LookupFilter(const StringPiece& filter_name);
// Looks up an option id/name and returns the corresponding PropertyBase if
// found, or NULL if the id/name is not found.
static const PropertyBase* LookupOptionById(StringPiece option_id);
static const PropertyBase* LookupOptionByName(StringPiece option_name);
// Looks up an option id and returns the corresponding name, or kNullOption
// if the id is not found. Example: for "ii" it returns "ImageInlineMaxBytes".
static const StringPiece LookupOptionNameById(StringPiece option_id);
// Determine if the given option name is valid/known.
static bool IsValidOptionName(StringPiece name);
// Return the list of all options. Used to initialize the configuration
// vector to the Apache configuration system.
const OptionBaseVector& all_options() const {
return all_options_;
}
// Determines whether this and that are the same. Uses the signature() to
// short-cut most of the deep comparisons, but then compares directly some
// options and other fields that are omitted from the signature.
bool IsEqual(const RewriteOptions& that) const;
// Returns the hasher used for signatures and URLs to purge.
const Hasher* hasher() const { return &hasher_; }
const SHA1Signature* sha1signature() const { return &sha1signature_; }
ThreadSystem* thread_system() const { return thread_system_; }
// Produces a new HttpOptions each time this is called, shouldn't be a big
// deal since we don't call it very often and HttpOptions are pretty light,
// but we might want to reconsider if those assumptions change.
HttpOptions ComputeHttpOptions() const;
protected:
// Helper class to represent an Option, whose value is held in some class T.
// An option is explicitly initialized with its default value, although the
// default value can be altered later. It keeps track of whether a
// value has been explicitly set (independent of whether that happens to
// coincide with the default value).
//
// It can use this knowledge to intelligently merge a 'base' option value
// into a 'new' option value, allowing explicitly set values from 'base'
// to override default values from 'new'.
template<class T> class OptionTemplateBase : public OptionBase {
public:
typedef T ValueType;
OptionTemplateBase() : was_set_(false), property_(NULL) {}
virtual bool was_set() const { return was_set_; }
void set(const T& val) {
was_set_ = true;
value_ = val;
}
void set_default(const T& val) {
if (!was_set_) {
value_ = val;
}
}
const T& value() const { return value_; }
T& mutable_value() { was_set_ = true; return value_; }
// The signature of the Merge implementation must match the base-class. The
// caller is responsible for ensuring that only the same typed Options are
// compared. In RewriteOptions::Merge this is guaranteed because the
// vector<OptionBase*> all_options_ is sorted on option_name(). We DCHECK
// that the option_name of this and src are the same.
virtual void Merge(const OptionBase* src) {
DCHECK(option_name() == src->option_name());
MergeHelper(static_cast<const OptionTemplateBase*>(src));
}
void MergeHelper(const OptionTemplateBase* src) {
// Even if !src->was_set, the default value needs to be transferred
// over in case it was changed with set_default or SetDefaultRewriteLevel.
if (src->was_set_ || !was_set_) {
value_ = src->value_;
was_set_ = src->was_set_;
}
}
// The static properties of an Option are held in a Property<T>*.
void set_property(const Property<T>* property) {
property_ = property;
// Note that the copying of default values here is only required
// to support SetDefaultRewriteLevel, which it should be
// possible to remove. Otherwise we could just pull the
// default value out of properties_ when !was_set_;
value_ = property->default_value();
}
virtual const PropertyBase* property() const { return property_; }
// Sets a the option default value globally. This is thread-unsafe,
// and reaches into the option property_ field via a const-cast to
// mutate it. Note that this method does not affect the current value
// of the instantiated option.
//
// TODO(jmarantz): consider an alternate structure where the
// Property<T>* can be easily located programmatically
// rather than going through a dummy Option object.
void set_global_default(const T& val) {
Property<T>* property = const_cast<Property<T>*>(property_);
property->set_default(val);
}
// Sets a the option's participation in Signatures globally. This
// is thread-unsafe, and reaches into the option property_ field
// via a const-cast to mutate it. Note that this method does not
// affect the current value of the instantiated option.
//
// TODO(jmarantz): consider an alternate structure where the
// Property<T>* can be easily located programmatically
// rather than going through a dummy Option object.
void DoNotUseForSignatureComputation() {
Property<T>* property = const_cast<Property<T>*>(property_);
property->set_do_not_use_for_signature_computation(true);
}
private:
bool was_set_;
T value_;
const Property<T>* property_;
DISALLOW_COPY_AND_ASSIGN(OptionTemplateBase);
};
// Subclassing OptionTemplateBase so that the conversion functions that need
// to invoke static overloaded functions are declared only here. Enables
// subclasses of RewriteOptions to override these in case they use Option
// types not visible here.
template<class T> class Option : public OptionTemplateBase<T> {
public:
Option() {}
// Sets value_ from value_string.
virtual bool SetFromString(StringPiece value_string,
GoogleString* error_detail) {
T value;
bool success = RewriteOptions::ParseFromString(value_string, &value);
if (success) {
this->set(value);
}
return success;
}
virtual GoogleString Signature(const Hasher* hasher) const {
return RewriteOptions::OptionSignature(this->value(), hasher);
}
virtual GoogleString ToString() const {
return RewriteOptions::ToString(this->value());
}
private:
DISALLOW_COPY_AND_ASSIGN(Option);
};
protected:
// Adds a new Property to 'properties' (the last argument).
template<class RewriteOptionsSubclass, class OptionClass>
static void AddProperty(
typename OptionClass::ValueType default_value,
OptionClass RewriteOptionsSubclass::*offset,
const char* id,
StringPiece option_name,
OptionScope scope,
const char* help_text,
bool safe_to_print,
Properties* properties) {
PropertyBase* property =
new PropertyLeaf<RewriteOptionsSubclass, OptionClass>(
default_value, offset, id, option_name);
property->set_scope(scope);
property->set_help_text(help_text);
property->set_safe_to_print(safe_to_print);
properties->push_back(property);
}
// Merges properties into all_properties so that
// RewriteOptions::Merge and SetOptionFromName can work across
// options from RewriteOptions and all relevant subclasses.
//
// Each RewriteOptions subclass keeps its own property lists using
// its own private Properties* member variables. The private lists
// are used for initialization of default-values during
// construction. We cannot initialize subclass default option
// values during RewriteOptions construction because options with
// non-POD ValueType (e.g. GoogleString) have not yet been
// initialized, so we have to keep separate per-class property-lists
// for use during construction. However, we use a global sorted
// list for fast merging and setting-by-option-name.
static void MergeSubclassProperties(Properties* properties);
// Populates all_options_, based on the passed-in index, which
// should correspond to the property index calculated after
// sorting all_properties_. This enables us to sort the all_properties_
// vector once, and use that to give us all_options_ that is sorted
// the same way.
void set_option_at(int index, OptionBase* option) {
all_options_[index] = option;
}
// When setting an option, however, we generally are doing so
// with a variable rather than a constant so it makes sense to pass
// it by reference.
template<class T>
void set_option(const T& new_value, OptionTemplateBase<T>* option) {
option->set(new_value);
Modify();
}
// Marks the config as modified.
void Modify();
// Sets the global default value for 'x_header_value'. Note that setting
// this Option reaches through to the underlying property and sets the
// default value there, and in fact does *not affect the value of the
// instantiated RewriteOptions object.
//
// TODO(jmarantz): Remove this method and make another one that operate
// directly on the Property.
void set_default_x_header_value(StringPiece x_header_value) {
x_header_value_.set_global_default(x_header_value.as_string());
}
// Enable/disable filters and set options according to the current
// ExperimentSpec that experiment_id_ matches. Returns true if the state was
// set successfully.
bool SetupExperimentRewriters();
// Enables filters needed by Experiment regardless of experiment.
virtual void SetRequiredExperimentFilters();
// Helper method to add pre-configured ExperimentSpec objects to the internal
// vector of ExperimentSpec's. Returns true if the experiment was added
// successfully. Takes ownership of (and may delete) spec.
bool InsertExperimentSpecInVector(ExperimentSpec* spec);
// Protected option values so that derived class can modify.
Option<BeaconUrl> beacon_url_;
// The value we put for the X-Mod-Pagespeed header. Default is our version.
Option<GoogleString> x_header_value_;
protected:
// The base class for a Property. This class contains fields of
// Properties that are independent of type.
class PropertyBase {
public:
PropertyBase(const char* id, StringPiece option_name)
: id_(id),
help_text_(NULL),
option_name_(option_name),
scope_(kDirectoryScope),
do_not_use_for_signature_computation_(false),
index_(-1) {
}
virtual ~PropertyBase();
// Connect the specified RewriteOption to this property.
// set_index() must previously have been called on this.
virtual void InitializeOption(RewriteOptions* options) const = 0;
void set_do_not_use_for_signature_computation(bool x) {
do_not_use_for_signature_computation_ = x;
}
bool is_used_for_signature_computation() const {
return !do_not_use_for_signature_computation_;
}
void set_scope(OptionScope x) { scope_ = x; }
OptionScope scope() const { return scope_; }
void set_help_text(const char* x) { help_text_ = x; }
const char* help_text() const { return help_text_; }
void set_index(int index) { index_ = index; }
const char* id() const { return id_; }
StringPiece option_name() const { return option_name_; }
int index() const { return index_; }
bool safe_to_print() const { return safe_to_print_; }
void set_safe_to_print(bool safe_to_print) {
safe_to_print_ = safe_to_print;
}
private:
const char* id_;
const char* help_text_;
StringPiece option_name_; // Key into all_options_.
OptionScope scope_;
bool do_not_use_for_signature_computation_; // Default is false.
bool safe_to_print_; // Safe to print in debug filter output.
int index_;
DISALLOW_COPY_AND_ASSIGN(PropertyBase);
};
// Type-specific class of Property. This subclass of PropertyBase
// knows what sort of value the Option will hold, and so we can put
// the default value here.
template<class ValueType>
class Property : public PropertyBase {
public:
// When adding a new Property, we take the default_value by value,
// not const-reference. This is because when calling AddProperty
// we may want to use a compile-time constant
// (e.g. Timer::kHourMs) which does not have a linkable address.
Property(ValueType default_value,
const char* id,
StringPiece option_name)
: PropertyBase(id, option_name),
default_value_(default_value) {
}
void set_default(ValueType value) { default_value_ = value; }
const ValueType& default_value() const { return default_value_; }
private:
ValueType default_value_;
DISALLOW_COPY_AND_ASSIGN(Property);
};
// Leaf subclass of Property<ValueType>, which is templated on the class of
// the corresponding Option. The template parameters here are
// RewriteOptionsSubclass -- the subclass of RewriteOptions in which
// this option is instantiated, e.g. ApacheConfig.
// OptionClass -- the subclass of OptionBase that is being instantiated
// in each RewriteOptionsSubclass.
// These template parameters are generally automatically discovered by
// the compiler when AddProperty is called.
//
// TODO(jmarantz): It looks tempting to fold Property<T> and
// PropertyLeaf<T> together, but this is difficult because of the
// way that the Option class hiearchy is structured and the
// precision of C++ pointers-to-members. Attempting that is
// probably a worthwhile follow-up task.
template<class RewriteOptionsSubclass, class OptionClass>
class PropertyLeaf : public Property<typename OptionClass::ValueType> {
public:
// Fancy C++ pointers to members; a typesafe version of offsetof. See
// http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?
// topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr034.htm
typedef OptionClass RewriteOptionsSubclass::*OptionOffset;
typedef typename OptionClass::ValueType ValueType;
PropertyLeaf(ValueType default_value,
OptionOffset offset,
const char* id,
StringPiece option_name)
: Property<ValueType>(default_value, id, option_name),
offset_(offset) {
}
virtual void InitializeOption(RewriteOptions* options) const {
RewriteOptionsSubclass* options_subclass =
static_cast<RewriteOptionsSubclass*>(options);
OptionClass& option = options_subclass->*offset_;
option.set_property(this);
DCHECK_NE(-1, this->index()) << "Call Property::set_index first.";
options->set_option_at(this->index(), &option);
}
private:
OptionOffset offset_;
DISALLOW_COPY_AND_ASSIGN(PropertyLeaf);
};
private:
// We need to check for valid settings with CacheFragment.
class CacheFragmentOption : public Option<GoogleString> {
public:
virtual bool SetFromString(StringPiece value_string,
GoogleString* error_detail);
};
struct OptionIdCompare;
// Enum type used to record what action must be taken to resolve conflicts
// between "preserve URLs" and "extend cache" directives at different levels
// of the merge. The lower priority wins. These must be calculated before
// option/filter merging, and then performed after option/filter merging.
enum MergeOverride { kNoAction, kDisablePreserve, kDisableFilter };
static Properties* properties_; // from RewriteOptions only
static Properties* all_properties_; // includes subclass properties
FRIEND_TEST(RewriteOptionsTest, ExperimentMergeTest);
FRIEND_TEST(RewriteOptionsTest, LookupOptionByNameTest);
FRIEND_TEST(RewriteOptionsTest, ColorUtilTest);
FRIEND_TEST(RewriteOptionsTest, ParseFloats);
// Helper functions to check if given header need to be blocked.
bool HasRejectedHeader(const StringPiece& header_name,
const RequestHeaders* request_headers) const;
bool IsRejectedUrl(const GoogleString& url) const {
return IsRejectedRequest(kRejectedRequestUrlKeyName, url);
}
bool IsRejectedRequest(StringPiece header_name,
StringPiece value) const {
FastWildcardGroupMap::const_iterator it = rejected_request_map_.find(
header_name);
if (it != rejected_request_map_.end()) {
return it->second->Match(value, false);
}
return false;
}
// Makes sure that javascript_library_identification_ points to an object
// owned only by us, so that we can modify it; and returns the pointer to it.
JavascriptLibraryIdentification* WriteableJavascriptLibraryIdentification();
// A family of urls for which prioritize_visible_content filter can be
// applied. url_pattern represents the actual set of urls,
// cache_time_ms is the duration for which the cacheable portions of pages of
// the family can be cached, and non_cacheable_elements is a comma-separated
// list of elements (e.g., "id:foo,class:bar") that cannot be cached for the
// family.
struct PrioritizeVisibleContentFamily {
PrioritizeVisibleContentFamily(StringPiece url_pattern_string,
int64 cache_time_ms_in,
StringPiece non_cacheable_elements_in)
: url_pattern(url_pattern_string),
cache_time_ms(cache_time_ms_in),
non_cacheable_elements(non_cacheable_elements_in.data(),
non_cacheable_elements_in.size()) {}
PrioritizeVisibleContentFamily* Clone() const {
return new PrioritizeVisibleContentFamily(
url_pattern.spec(), cache_time_ms, non_cacheable_elements);
}
GoogleString ComputeSignature() const {
return StrCat(url_pattern.spec(), ";", Integer64ToString(cache_time_ms),
";", non_cacheable_elements);
}
GoogleString ToString() const {
return StrCat("URL pattern: ", url_pattern.spec(), ", Cache time (ms): ",
Integer64ToString(cache_time_ms), ", Non-cacheable: ",
non_cacheable_elements);
}
Wildcard url_pattern;
int64 cache_time_ms;
GoogleString non_cacheable_elements;
};
// A URL pattern cache invalidation entry. All values cached for an URL that
// matches url_pattern before timestamp_ms should be evicted.
struct UrlCacheInvalidationEntry {
UrlCacheInvalidationEntry(StringPiece url_pattern_in,
int64 timestamp_ms_in,
bool ignores_metadata_and_pcache_in)
: url_pattern(url_pattern_in),
timestamp_ms(timestamp_ms_in),
ignores_metadata_and_pcache(ignores_metadata_and_pcache_in) {}
UrlCacheInvalidationEntry* Clone() const {
return new UrlCacheInvalidationEntry(
url_pattern.spec(), timestamp_ms, ignores_metadata_and_pcache);
}
GoogleString ComputeSignature() const {
if (ignores_metadata_and_pcache) {
return "";
}
return StrCat(url_pattern.spec(), "@", Integer64ToString(timestamp_ms));
}
GoogleString ToString() const {
return StrCat(
url_pattern.spec(), ", ",
(ignores_metadata_and_pcache ? "STRICT" : "REFERENCE"), " @ ",
Integer64ToString(timestamp_ms));
}
Wildcard url_pattern;
int64 timestamp_ms;
bool ignores_metadata_and_pcache;
};
typedef std::vector<UrlCacheInvalidationEntry*>
UrlCacheInvalidationEntryVector;
typedef dense_hash_map<GoogleString, int64> UrlCacheInvalidationMap;
// Sigh. The folding Hash struct is required so that we ignore case when
// inserting. The folding Equal struct is required for looking up. Damned
// if I know why one needs to specify both.
typedef rde::hash_map<StringPiece, const PropertyBase*,
CaseFoldStringPieceHash, /* TLoadFactor4 = */ 6,
CaseFoldStringPieceEqual> PropertyNameMap;
// Private methods to help add properties to
// RewriteOptions::properties_. Subclasses define their own
// versions of these to add to their own private property-lists, and
// subsequently merge them into RewriteOptions::all_properties_ via
// MergeSubclassProperties.
//
// This version is for a property without a unique option_name_ field.
// kNullOption will be used for the name, and thus SetOptionFromName cannot
// be used for options associated with such properties.
//
// TODO(jmarantz): This method should be removed and such properties
// should be moved into RequestContext.
template<class OptionClass>
static void AddRequestProperty(typename OptionClass::ValueType default_value,
OptionClass RewriteOptions::*offset,
const char* id, bool safe_to_print) {
AddProperty(default_value, offset, id, kNullOption, kProcessScope,
NULL, safe_to_print, properties_);
}
// Adds a property with a unique option_name_ field, allowing use of
// SetOptionFromName.
template<class OptionClass>
static void AddBaseProperty(typename OptionClass::ValueType default_value,
OptionClass RewriteOptions::*offset,
const char* id,
StringPiece option_name,
OptionScope scope,
const char* help,
bool safe_to_print) {
AddProperty(default_value, offset, id, option_name, scope, help,
safe_to_print, properties_);
}
static void AddProperties();
bool AddCommaSeparatedListToFilterSetState(
const StringPiece& filters, FilterSet* set, MessageHandler* handler);
static bool AddCommaSeparatedListToFilterSet(
const StringPiece& filters, FilterSet* set, MessageHandler* handler);
// Initialize the Filter id to enum reverse array used for fast lookups.
static void InitFilterIdToEnumArray();
static void InitOptionIdToPropertyArray();
static void InitOptionNameToPropertyArray();
// Helper for converting the result of SetOptionFromNameInternal into
// a status/message pair. The returned result may be adjusted from the passed
// in one (in particular when option_name is kNullOption).
OptionSettingResult FormatSetOptionMessage(
OptionSettingResult result, StringPiece name, StringPiece value,
StringPiece error_detail, GoogleString* msg);
// Backend to SetOptionFromName that doesn't do full message
// formatting. *error_detail may not be always set.
OptionSettingResult SetOptionFromNameInternal(
StringPiece name, StringPiece value, OptionScope max_scope,
GoogleString* error_detail);
// These static methods enable us to generate signatures for all
// instantiated option-types from Option<T>::Signature().
static GoogleString OptionSignature(bool x, const Hasher* hasher) {
return x ? "T" : "F";
}
static GoogleString OptionSignature(int x, const Hasher* hasher) {
return IntegerToString(x);
}
static GoogleString OptionSignature(int64 x, const Hasher* hasher) {
return Integer64ToString(x);
}
static GoogleString OptionSignature(const GoogleString& x,
const Hasher* hasher);
static GoogleString OptionSignature(RewriteLevel x,
const Hasher* hasher);
static GoogleString OptionSignature(ResourceCategorySet x,
const Hasher* hasher);
static GoogleString OptionSignature(const BeaconUrl& beacon_url,
const Hasher* hasher);
static GoogleString OptionSignature(const MobTheme& mob_theme,
const Hasher* hasher);
static GoogleString OptionSignature(const ResponsiveDensities& densities,
const Hasher* hasher);
static GoogleString OptionSignature(const AllowVaryOn& allow_vary_on,
const Hasher* hasher);
static GoogleString OptionSignature(
const protobuf::MessageLite& proto,
const Hasher* hasher);
// These static methods enable us to generate strings for all
// instantiated option-types from Option<T>::Signature().
static GoogleString ToString(bool x) {
return x ? "True" : "False";
}
static GoogleString ToString(int x) {
return IntegerToString(x);
}
static GoogleString ToString(int64 x) {
return Integer64ToString(x);
}
static GoogleString ToString(const GoogleString& x) {
return x;
}
static GoogleString ToString(RewriteLevel x);
static GoogleString ToString(const ResourceCategorySet &x);
static GoogleString ToString(const BeaconUrl& beacon_url);
static GoogleString ToString(const MobTheme& mob_theme);
static GoogleString ToString(const Color& color);
static GoogleString ToString(const ResponsiveDensities& densities);
static GoogleString ToString(const protobuf::MessageLite& proto);
static GoogleString ToString(const AllowVaryOn& allow_vary_on);
// Returns true if p1's option_name is less than p2's. Used to order
// all_properties_ and all_options_.
static bool PropertyLessThanByOptionName(PropertyBase* p1, PropertyBase* p2) {
return StringCaseCompare(p1->option_name(), p2->option_name()) < 0;
}
// Returns true if option's name is less than arg.
static bool OptionNameLessThanArg(OptionBase* option, StringPiece arg) {
return StringCaseCompare(option->option_name(), arg) < 0;
}
// Returns true if e1's timestamp is less than e2's.
static bool CompareUrlCacheInvalidationEntry(UrlCacheInvalidationEntry* e1,
UrlCacheInvalidationEntry* e2) {
return e1->timestamp_ms < e2->timestamp_ms;
}
// Returns true if the first entry's id is less than the second's id.
static bool FilterEnumToIdAndNameEntryLessThanById(
const FilterEnumToIdAndNameEntry* e1,
const FilterEnumToIdAndNameEntry* e2) {
return strcmp(e1->filter_id, e2->filter_id) < 0;
}
// Return the effective option name. If the name is deprecated, the new name
// will be returned; otherwise the name will be returned as is.
static StringPiece GetEffectiveOptionName(StringPiece name);
// Returns value of this option if it has been set; otherwise, returns true
// if the rewrite level matches the argument. If nothing applies, returns
// false.
bool CheckLevelSpecificOption(RewriteLevel rewrite_level,
const Option<bool>& option) const;
// In OptimizeForBandwidth mode, this sets up certain default filters
// and options, which take effect only if not explicitly overridden.
bool CheckBandwidthOption(const Option<bool>& option) const {
return CheckLevelSpecificOption(kOptimizeForBandwidth, option);
}
// In MobilizeFilters mode, this sets up certain default filters and options,
// which take effect only if not explicitly overridden.
bool CheckMobilizeFiltersOption(const Option<bool>& option) const {
return CheckLevelSpecificOption(kMobilizeFilters, option);
}
// Helps resolve the conflict between explicit extend_cache filters and
// preserve settings, but does not perform the action itself. This is so
// that the standard option-merging and filter-merging that works over
// all filters can function. This function is called prior to merging
// options and filters. The resulting value is then passed to
// ApplyMergeOverride, which must be run after the filter/option merging.
MergeOverride ComputeMergeOverride(
Filter filter,
const Option<bool>& src_preserve_option,
const Option<bool>& preserve_option,
const RewriteOptions& src);
// Applies the results of ComputeMergeOverride.
void ApplyMergeOverride(
MergeOverride merge_override,
Filter filter,
Option<bool>* preserve_option);
bool modified_;
bool frozen_;
FilterSet enabled_filters_;
FilterSet disabled_filters_;
FilterSet forbidden_filters_;
// The set of filters that can be distributed to other tasks.
// For experimentation, may be removed later.
FilterIdSet distributable_filters_;
// Note: using the template class Option here saves a lot of repeated
// and error-prone merging code. However, it is not space efficient as
// we are alternating int64s and bools in the structure. If we cared
// about that, then we would keep the bools in a bitmask. But since
// we don't really care we'll try to keep the code structured better.
Option<RewriteLevel> level_;
// List of URL wildcard patterns and timestamp for which it should be
// invalidated. In increasing order of timestamp.
UrlCacheInvalidationEntryVector url_cache_invalidation_entries_;
// Map of exact URLs to be invalidated; no wildcards. Note that the
// cache_purge_mutex_ is, by default, a NullRWLock. You must call
// set_cache_invalidation_timestamp_mutex to make it be a real mutex.
// This is generally done only for the global context for each server,
// so that we can atomically propagate cache flush updates into it while
// it's running.
CopyOnWrite<PurgeSet> purge_set_ GUARDED_BY(cache_purge_mutex_);
scoped_ptr<ThreadSystem::RWLock> cache_purge_mutex_;
Option<int64> css_flatten_max_bytes_;
Option<bool> cache_small_images_unrewritten_;
Option<bool> no_transform_optimized_images_;
// Sets limit for image optimization
Option<int64> image_resolution_limit_bytes_;
Option<int64> css_image_inline_max_bytes_;
Option<int64> css_inline_max_bytes_;
Option<int64> css_outline_min_bytes_;
Option<int64> google_font_css_inline_max_bytes_;
// Preserve URL options
Option<bool> css_preserve_urls_;
Option<bool> js_preserve_urls_;
Option<bool> image_preserve_urls_;
Option<int64> image_inline_max_bytes_;
Option<int64> js_inline_max_bytes_;
Option<int64> js_outline_min_bytes_;
Option<int64> progressive_jpeg_min_bytes_;
// The max Cache-Control TTL for HTML.
Option<int64> max_html_cache_time_ms_;
// The maximum number of bytes of HTML that we parse, before redirecting to
// ?ModPagespeed=off.
Option<int64> max_html_parse_bytes_;
// The maximum size of an image in CSS, which we convert to webp.
Option<int64> max_image_bytes_for_webp_in_css_;
// Resources with Cache-Control TTL less than this will not be rewritten.
Option<int64> min_resource_cache_time_to_rewrite_ms_;
Option<int64> idle_flush_time_ms_;
Option<int64> flush_buffer_limit_bytes_;
// How long to wait in blocking fetches before timing out.
// Applies to ResourceFetch::BlockingFetch() and class SyncFetcherAdapter.
// Does not apply to async fetches.
Option<int64> blocking_fetch_timeout_ms_;
// Option related to generic image quality. This is overridden by
// image(jpeg/webp) specific options.
Option<int64> image_recompress_quality_;
// Options related to jpeg compression.
Option<int64> image_jpeg_recompress_quality_;
Option<int64> image_jpeg_recompress_quality_for_small_screens_;
Option<int64> image_jpeg_quality_for_save_data_;
Option<int64> image_jpeg_num_progressive_scans_;
Option<int64> image_jpeg_num_progressive_scans_for_small_screens_;
// Options governing when to retain optimized images vs keep original
Option<int> image_limit_optimized_percent_;
Option<int> image_limit_resize_area_percent_;
Option<int> image_limit_rendered_area_percent_;
// Options related to webp compression.
Option<int64> image_webp_recompress_quality_;
Option<int64> image_webp_recompress_quality_for_small_screens_;
Option<int64> image_webp_animated_recompress_quality_;
Option<int64> image_webp_quality_for_save_data_;
Option<int64> image_webp_timeout_ms_;
Option<int> image_max_rewrites_at_once_;
Option<int> max_url_segment_size_; // For http://a/b/c.d, use strlen("c.d").
Option<int> max_url_size_; // This is strlen("http://a/b/c.d").
// The interval to wait for async rewrites to complete before flushing
// content. This deadline is per flush.
Option<int> rewrite_deadline_ms_;
// Maximum number of shards for rewritten resources in a directory.
Option<int> domain_shard_count_;
Option<EnabledEnum> enabled_;
Option<bool> distributable_;
// Encode relevant rewrite options as URL query-parameters so that resources
// can be reconstructed on servers without the same configuration file.
Option<bool> add_options_to_urls_;
// If this option is enabled, serves .pagespeed. resource URLs with
// mismatching hashes with the same cache expiration as the inputs.
// By default, we convert resources requests with the wrong hash to
// Cache-Control:private,max-age=300 to avoid caching stale content
// in proxies.
Option<bool> publicly_cache_mismatched_hashes_experimental_;
// Should in-place-resource-optimization(IPRO) be enabled?
Option<bool> in_place_rewriting_enabled_;
// Optimize before responding in in-place flow?
Option<bool> in_place_wait_for_optimized_;
// Interval to delay serving on the IPRO path while waiting for optimizations.
// After this interval, the unoptimized resource will be served.
Option<int> in_place_rewrite_deadline_ms_;
// If set, preemptively rewrite images in CSS files on the HTML serving path
// when IPRO of CSS is enabled.
Option<bool> in_place_preemptive_rewrite_css_;
// If set, preemptively rewrite images in CSS files on the IPRO serving path.
Option<bool> in_place_preemptive_rewrite_css_images_;
// If set, preemptively rewrite images in image files on the HTML serving path
// when IPRO of images is enabled.
Option<bool> in_place_preemptive_rewrite_images_;
// If set, preemptively rewrite images in JS files on the HTML serving path
// when IPRO of JS is enabled.
Option<bool> in_place_preemptive_rewrite_javascript_;
// Use cache-control:private rather than vary:accept when serving IPRO
// resources to IE. This avoids the need for an if-modified-since request
// from IE on each cache hit. The flip side is no proxy cache will store it
// (though few or no proxy caches will store Vary: accept data in any case
// unless they are specially configured to do so).
Option<bool> private_not_vary_for_ie_;
Option<bool> combine_across_paths_;
Option<bool> log_background_rewrites_;
Option<bool> log_mobilization_samples_;
Option<bool> log_rewrite_timing_; // Should we time HtmlParser?
Option<bool> log_url_indices_;
Option<bool> lowercase_html_names_;
Option<bool> always_rewrite_css_; // For tests/debugging.
Option<bool> respect_vary_;
Option<bool> respect_x_forwarded_proto_;
Option<bool> flush_html_;
// Should we serve the split html response in two chunks - above the fold and
// below the fold. If set to false, we serve the above the fold and below the
// fold in a single response.
Option<bool> serve_split_html_in_two_chunks_;
// Should we serve stale responses if the fetch results in a server side
// error.
Option<bool> serve_stale_if_fetch_error_;
// Should we serve ghost click buster code when split html is enabled.
Option<bool> serve_ghost_click_buster_with_split_html_;
// Should we serve access control headers in response headers.
Option<bool> serve_xhr_access_control_headers_;
// Proactively freshen user facing request if it is about to expire. So, that
// subsequent requests will experience a cache hit.
Option<bool> proactively_freshen_user_facing_request_;
// Threshold for serving stale responses while revalidating in background.
// 0 means don't serve stale content.
Option<int64> serve_stale_while_revalidate_threshold_sec_;
// Whether to flush the inlined critical css rules early.
Option<bool> enable_flush_early_critical_css_;
// Whether to use CriticalSelectorFilter for prioritize_critical_css filter.
Option<bool> use_selectors_for_critical_css_;
// When default_cache_html_ is false (default) we do not cache
// input HTML which lacks Cache-Control headers. But, when set true,
// we will cache those inputs for the implicit lifetime just like we
// do for resources.
Option<bool> default_cache_html_;
// In general, we rewrite Cache-Control headers for HTML. We do this
// for several reasons, but at least one is that our rewrites are not
// necessarily publicly cacheable.
// Some people don't like this, so we allow them to disable it.
Option<bool> modify_caching_headers_;
// In general, lazyload images loads images on scroll. However, some people
// may want to load images when the onload event is fired instead. If set to
// true, images are loaded when onload is fired.
Option<bool> lazyload_images_after_onload_;
// The initial image url to load in the lazyload images filter. If this is not
// specified, we use a 1x1 inlined image.
Option<GoogleString> lazyload_images_blank_url_;
// Whether inline preview should use a blank image instead of a low resolution
// version of the original image.
Option<bool> use_blank_image_for_inline_preview_;
// By default, inline_images will inline only critical images. However, some
// people may want to inline all images (both critical and non-critical). If
// set to false, all images will be inlined within the html.
Option<bool> inline_only_critical_images_;
// Indicates whether image rewriting filters should insert the critical images
// beacon code.
Option<bool> critical_images_beacon_enabled_;
// Indicates whether the DomainRewriteFilter should also do client side
// rewriting.
Option<bool> client_domain_rewrite_;
// Indicates whether DomainRewriteFilter should rewrite domain information
// in Set-Cookie: headers.
Option<bool> domain_rewrite_cookies_;
// Indicates whether the DomainRewriteFilter should rewrite all tags,
// including <a href> and <form action>.
Option<bool> domain_rewrite_hyperlinks_;
// Are we running the A/B experiment framework that uses cookies and Google
// Analytics to track page speed statistics with multiple sets of rewriters?
Option<bool> running_experiment_;
// The experiment framework reports to Google Analytice in a custom variable
// slot. Specify which one to use.
Option<int> experiment_ga_slot_;
// For testing purposes you can force users to be enrolled in a specific
// experiment. This makes most sense in a query param.
Option<int> enroll_experiment_id_;
// When running a content experiment, which IDs should we use when logging to
// Google Analytics?
Option<GoogleString> content_experiment_id_;
Option<GoogleString> content_experiment_variant_id_;
// Log to analytics.js instead of ga.js.
Option<bool> use_analytics_js_;
// Increase the percentage of hits to 10% (current max) that have
// site speed tracking in Google Analytics.
Option<bool> increase_speed_tracking_;
// If enabled we will report time taken before navigating to a new page. This
// won't have effect, if onload beacon is sent before unload event is
// trigggered.
Option<bool> report_unload_time_;
Option<bool> serve_rewritten_webp_urls_to_any_agent_;
// Flush more resources if origin is slow to respond.
Option<bool> flush_more_resources_early_if_time_permits_;
// Flush more resources in IE and Firefox.
Option<bool> flush_more_resources_in_ie_and_firefox_;
// Number of script elements to prefetch early. Applicable when defer_js
// filter is enabled.
Option<int> max_prefetch_js_elements_;
// Enables experimental code in defer js.
Option<bool> enable_defer_js_experimental_;
// Option to disable rewrite optimizations on no-transform header.
Option<bool> disable_rewrite_on_no_transform_;
// Option to disable pre-emptive background fetches for bot requests.
Option<bool> disable_background_fetches_for_bots_;
// Enables the Cache Purge API. This is not on by default because
// it requires saving input URLs to each metadata cache entry to
// facilitate fast URL cache invalidation.
//
// Note that in the absence of this API, purging URLs can still
// work, but it will invalidate either the entire metadata cache
// (ignores_metadata_and_pcache==false in the call to
// AddUrlCacheInvalidationEntry) or will not invalidate the metadata
// cache entries at all (ignores_metadata_and_pcache==false).
Option<bool> enable_cache_purge_;
// If set, the urls of the inputs to the resource are saved in the metadata
// cache entry. This increases the size of the cache entry, but can be used in
// freshening of the embedded resources.
Option<bool> proactive_resource_freshening_;
// Enables the code to lazy load high res images.
Option<bool> lazyload_highres_images_;
// Some introspective javascript is very brittle and may break if we
// make any changes. Enables code to detect such cases and avoid renaming.
Option<bool> avoid_renaming_introspective_javascript_;
// Overrides the IE document mode to use the highest mode available.
Option<bool> override_ie_document_mode_;
// Test-only flag to get fetch deadlines to trigger instantly.
Option<bool> test_instant_fetch_rewrite_deadline_;
// Indicates whether the prioritize_critical_css filter should invoke its
// JavaScript function to load all the "hidden" CSS files at onload.
// Intended for testing only.
Option<bool> test_only_prioritize_critical_css_dont_apply_original_css_;
// Enables blocking rewrite of html. RewriteDriver provides a flag
// fully_rewrite_on_flush which makes sure that all rewrites are done before
// the response is flushed to the client. If the value of the
// X-PSA-Blocking-Rewrite header matches this key, the
// RewriteDriver::fully_rewrite_on_flush flag will be set.
Option<GoogleString> blocking_rewrite_key_;
// Indicates how often we should reinstrument pages with the critical images
// beacon, based on the time since the last write to the property cache by a
// beacon response.
Option<int> beacon_reinstrument_time_sec_;
// Number of first N images for which low res image is generated. Negative
// values will bypass image index check.
Option<int> max_inlined_preview_images_index_;
// Minimum image size above which low res image is generated.
Option<int64> min_image_size_low_resolution_bytes_;
// Maximum image size below which low res image is generated.
Option<int64> max_image_size_low_resolution_bytes_;
// Percentage (an integer between 0 and 100 inclusive) of images rewrites to
// drop.
Option<int> rewrite_random_drop_percentage_;
// For proxies operating in in-place mode this allows fetching optimized
// resources from sites that have MPS, etc configured.
Option<bool> oblivious_pagespeed_urls_;
// Cache expiration time in msec for properties of finders.
Option<int64> finder_properties_cache_expiration_time_ms_;
// Cache refresh time in msec for properties of finders. The properties are
// refreshed when their age is larger than the specified value. However, the
// property will be used until finder_properties_cache_expiration_time_ms_.
Option<int64> finder_properties_cache_refresh_time_ms_;
// Duration after which the experiment cookie will expire on the user's
// browser (in msec).
Option<int64> experiment_cookie_duration_ms_;
// The maximum time beyond expiry for which a metadata cache entry may be
// used.
Option<int64> metadata_cache_staleness_threshold_ms_;
// The metadata cache ttl for input resources which are 4xx errors.
Option<int64> metadata_input_errors_cache_ttl_ms_;
// The HTTP method to use ("PURGE", "GET" etc.) for purge requests sent to
// downstream caches (e.g. proxy_cache, Varnish).
Option<GoogleString> downstream_cache_purge_method_;
// The host:port/path prefix to be used for purging the cached responses.
Option<GoogleString> downstream_cache_purge_location_prefix_;
// The webmaster-provided key used to authenticate rebeaconing requests from
// downstream caches.
Option<GoogleString> downstream_cache_rebeaconing_key_;
// Threshold for amount of rewriting finished before the response was served
// out (expressed as a percentage) and simultaneously stored in the downstream
// cache beyond which the response will not be purged from the cache even if
// more rewriting is possible now. If the threshold is exceeded, this means
// that the version in the cache is good enough and hence need not be purged.
Option<int64> downstream_cache_rewritten_percentage_threshold_;
// The number of milliseconds of cache TTL we assign to resources that
// are "likely cacheable" (e.g. images, js, css, not html) and have no
// explicit cache ttl or expiration date.
Option<int64> implicit_cache_ttl_ms_;
// The number of miliseconds of cache TTL we assign to resources that are
// loaded from file and "likely cacheable" and have no explicit cache ttl or
// expiration date. If this option is not set explicitly, fall back to using
// implicit_cache_ttl_ms for load from file cache ttl.
Option<int64> load_from_file_cache_ttl_ms_;
// Maximum length (in bytes) of response content.
Option<int64> max_cacheable_response_content_length_;
// The timestamp when blink blacklist expires.
Option<int64> blink_blacklist_end_timestamp_ms_;
// Keep the original subresource hints
Option<bool> preserve_subresource_hints_;
// Keep rewritten URLs as relative as the original resource URL was.
// TODO(sligocki): Remove this option once we know it's always safe.
Option<bool> preserve_url_relativity_;
Option<GoogleString> ga_id_;
Option<int64> blink_max_html_size_rewritable_;
// Time after which we should try to detect if publisher html in blink
// has changed.
Option<int64> blink_html_change_detection_time_ms_;
// Show the blink debug dashboard.
Option<bool> enable_blink_debug_dashboard_;
// Enable automatic detection of publisher changes in html in blink.
Option<bool> enable_blink_html_change_detection_;
// Enable logging of publisher changes detected in html in blink flow.
Option<bool> enable_blink_html_change_detection_logging_;
// Use smart diff to detect publisher changes in html in blink.
Option<bool> use_smart_diff_in_blink_;
// Use fallback values from property cache.
Option<bool> use_fallback_property_cache_values_;
// Always wait for property cache lookup to finish.
Option<bool> await_pcache_lookup_;
// Enable Prioritizing of scripts in defer javascript.
Option<bool> enable_prioritizing_scripts_;
// Enables rewriting of uncacheable resources.
Option<bool> rewrite_uncacheable_resources_;
// Specification for critical line.
Option<GoogleString> critical_line_config_;
// The user-provided key used to authenticate requests from one rewrite task
// to another. Right now only used to validate meta-data headers.
Option<GoogleString> distributed_rewrite_key_;
// A comma delimited list of hosts that can be used to rewrite resources.
Option<GoogleString> distributed_rewrite_servers_;
// Whether or not to distribute IPRO and .pagespeed. resource fetch requests
// from the RewriteDriver before checking the cache. If this is false,
// then a distribution will only occur for a fetch if a nested
// RewriteContext is created and its id is distributable.
Option<bool> distribute_fetches_;
// Time to wait for a distributed rewrite to complete before giving up on the
// request.
Option<int64> distributed_rewrite_timeout_ms_;
// Forbid turning on of any disabled (not enabled) filters either via query
// parameters or request headers or .htaccess for Directory. Note that this
// is a latch so that setting it at some directory level forces it on for
// that and all lower levels, as otherwise someone could just create a
// sub-directory and enable it in a .htaccess in there.
Option<bool> forbid_all_disabled_filters_;
// Enables aggressive rewriters for mobile user agents.
Option<bool> enable_aggressive_rewriters_for_mobile_;
// If this is true (it defaults to false) ProxyInterface frontend will
// reject requests where PSA is not enabled or URL is blacklisted with
// status code reject_blacklisted_status_code_ (default 403) rather than
// proxy them in passthrough mode. This does not affect behavior for
// resource rewriting.
Option<bool> reject_blacklisted_;
Option<int> reject_blacklisted_status_code_;
// Support handling of clients without javascript support. This is applicable
// only if any filter that inserts new javascript (e.g., lazyload_images) is
// enabled.
Option<bool> support_noscript_enabled_;
// If this set to true, we add additional instrumentation code to page that
// reports more information in the beacon.
Option<bool> enable_extended_instrumentation_;
Option<bool> use_experimental_js_minifier_;
// Maximum size allowed for the combined CSS resource.
// Negative value will bypass the size check.
Option<int64> max_combined_css_bytes_;
// Maximum size allowed for the combined js resource.
// Negative value will bypass the size check.
Option<int64> max_combined_js_bytes_;
// Url to which pre connect requests will be sent.
Option<GoogleString> pre_connect_url_;
// The number of requests for which the status code should remain same so that
// we consider it to be stable.
Option<int> property_cache_http_status_stability_threshold_;
// The maximum number of rewrite info logs stored for a single request.
Option<int> max_rewrite_info_log_size_;
// The cache TTL with which to override the urls matching the
// override_caching_ WildCardGroup. Note that we do not override the cache TTL
// for any urls if this value is negative. The same TTL value is used for all
// urls that match override_caching_wildcard_.
Option<int64> override_caching_ttl_ms_;
CopyOnWrite<FastWildcardGroup> override_caching_wildcard_;
// The minimum milliseconds of cache TTL for all resources that are
// explicitly cacheable. This overrides the max-age even when it is set on
// Cache-Control headers.
Option<int64> min_cache_ttl_ms_;
// Whether to allow logging urls as part of LogRecord.
Option<bool> allow_logging_urls_in_log_record_;
// Whether to allow options to be set by cookies.
Option<bool> allow_options_to_be_set_by_cookies_;
// Non cacheables used when partial HTML is cached.
Option<GoogleString> non_cacheables_for_cache_partial_html_;
// Comma seperated list of origins that are allowed to make cross-origin
// requests. These domain requests are served with
// Access-Control-Allow-Origin header.
Option<GoogleString> access_control_allow_origins_;
// If set to true, hides the referer by adding meta tag to the HTML.
Option<bool> hide_referer_using_meta_;
// Options to control the edge-case behaviour of inline-previewed images. The
// idea is to avoid inline-previewing when:
// a. low-res image is large.
// b. low-res image is not small enough compared to the full-res version.
Option<int64> max_low_res_image_size_bytes_;
Option<int> max_low_res_to_full_res_image_size_percentage_;
// The URL from which to pull remote configurations.
Option<GoogleString> remote_configuration_url_;
// The timeout, in milliseconds for the remote configuration file fetch.
Option<int64> remote_configuration_timeout_ms_;
// The level to set the gzip compression of HTTPCache items.
Option<int> http_cache_compression_level_;
// Pass this string in url to allow for pagespeed options.
Option<GoogleString> request_option_override_;
// The key used to sign .pagespeed resources if URL signing is enabled.
Option<GoogleString> url_signing_key_;
// If set to true, accepts urls with invalid signatures.
Option<bool> accept_invalid_signatures_;
// sticky_query_parameters_ is the token specified in the configuration that
// must be specified in a request's query parameters/headers for the other
// options in the request to be converted to cookies.
// option_cookies_duration_ms_ is how long the cookie will live for when set.
Option<GoogleString> sticky_query_parameters_;
Option<int64> option_cookies_duration_ms_;
// Comma separated list of densities to use for responsive images.
Option<ResponsiveDensities> responsive_image_densities_;
// If set, how to fragment the http cache. Otherwise the server's hostname,
// from the Host header, is used.
CacheFragmentOption cache_fragment_;
// Be sure to update constructor when new fields are added so that they are
// added to all_options_, which is used for Merge, and eventually, Compare.
OptionBaseVector all_options_;
size_t initialized_options_; // Counts number of options initialized so far.
// Reverse map from filter id string to corresponding Filter enum. Note
// that this is not indexed by filter enum; it's indexed alphabetically by id.
static const FilterEnumToIdAndNameEntry* filter_id_to_enum_array_[
kEndOfFilters];
// Reverse map from option name string to corresponding PropertyBase.
static PropertyNameMap* option_name_to_property_map_;
// Reverse map from option id string to corresponding PropertyBase.
static const PropertyBase** option_id_to_property_array_;
// When compiled for debug, we lazily check whether the all the Option<>
// member variables in all_options have unique IDs.
//
// Note that we include this member-variable in the structrue even under
// optimization as otherwise it might be very bad news indeed if someone
// mixed debug/opt object files in an executable.
bool options_uniqueness_checked_;
bool need_to_store_experiment_data_;
int experiment_id_; // Which experiment configuration are we in?
int experiment_percent_; // Total traffic going through experiments.
std::vector<ExperimentSpec*> experiment_specs_;
// Headers to add to subresource requests.
std::vector<NameValue*> custom_fetch_headers_;
// If this is non-NULL it tells us additional attributes that should be
// interpreted as containing urls.
scoped_ptr<std::vector<ElementAttributeCategory> > url_valued_attributes_;
Option<ResourceCategorySet> inline_unauthorized_resource_types_;
Option<bool> mob_always_;
Option<bool> mob_config_;
Option<bool> mob_iframe_;
Option<bool> mob_iframe_disable_;
Option<GoogleString> mob_iframe_viewport_;
Option<bool> mob_layout_;
Option<bool> mob_nav_;
Option<bool> mob_labeled_mode_;
Option<GoogleString> mob_nav_classes_;
Option<bool> mob_static_;
Option<GoogleString> mob_beacon_url_;
Option<GoogleString> mob_beacon_category_;
Option<GoogleString> mob_map_location_;
Option<GoogleString> mob_phone_number_;
Option<int64> mob_conversion_id_;
Option<GoogleString> mob_map_conversion_label_;
Option<GoogleString> mob_phone_conversion_label_;
Option<MobTheme> mob_theme_;
Option<int64> noop_;
// Comma separated list of headers which we can vary-on, or "Auto", or "None".
Option<AllowVaryOn> allow_vary_on_;
CopyOnWrite<JavascriptLibraryIdentification>
javascript_library_identification_;
CopyOnWrite<DomainLawyer> domain_lawyer_;
FileLoadPolicy file_load_policy_;
CopyOnWrite<FastWildcardGroup> allow_resources_;
CopyOnWrite<FastWildcardGroup> allow_when_inlining_resources_;
CopyOnWrite<FastWildcardGroup> retain_comments_;
CopyOnWrite<FastWildcardGroup> lazyload_enabled_classes_;
// When certain url patterns are in the referer we want to do a blocking
// rewrite.
CopyOnWrite<FastWildcardGroup> blocking_rewrite_referer_urls_;
// Using StringPiece here is safe since all entries in this map have static
// strings as the key.
typedef std::map<StringPiece, FastWildcardGroup*> FastWildcardGroupMap;
FastWildcardGroupMap rejected_request_map_;
GoogleString signature_;
MD5Hasher hasher_; // Used to compute named signatures.
SHA1Signature sha1signature_;
ThreadSystem* thread_system_;
// When compiled for debug, keep track of the last thread to modify
// this object. If cloned or merged from prior to
// ComputeSignature(), we check that the thread doing the Merge is
// in the same thread that modified it.
//
// We also ensure that only one thread modifies a RewriteOptions
// object.
//
// Note: we don't ifdef the member variable declaration as having the
// structure-size dependent on debug-ifdef seems dangerous when used
// as a library against externally compiled code. We do ifdef its
// usage within the class implementation, however.
scoped_ptr<ThreadSystem::ThreadId> last_thread_id_;
DISALLOW_COPY_AND_ASSIGN(RewriteOptions);
};
} // namespace net_instaweb
#endif // NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_OPTIONS_H_