Commit abc94c12 authored by Robert Ogden's avatar Robert Ogden Committed by Commit Bot

Add response reactions to HTTPS Server Previews

Loads the original page on a 404 or 503 server response. Further actions
for these response types will be in follow up CLs.

Bug: 864656
Change-Id: I861685e0d19f5597ade3ed814e9847a3595d9e31
Reviewed-on: https://chromium-review.googlesource.com/1171799
Commit-Queue: Robert Ogden <robertogden@chromium.org>
Reviewed-by: default avatarRyan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583424}
parent 915ab7e9
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/previews/previews_lite_page_decider.h" #include "chrome/browser/previews/previews_lite_page_decider.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/time/default_tick_clock.h"
#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" #include "chrome/browser/previews/previews_lite_page_navigation_throttle.h"
...@@ -17,7 +18,8 @@ ...@@ -17,7 +18,8 @@
#include "content/public/browser/navigation_throttle.h" #include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
PreviewsLitePageDecider::PreviewsLitePageDecider() = default; PreviewsLitePageDecider::PreviewsLitePageDecider()
: clock_(base::DefaultTickClock::GetInstance()) {}
PreviewsLitePageDecider::~PreviewsLitePageDecider() = default; PreviewsLitePageDecider::~PreviewsLitePageDecider() = default;
...@@ -54,6 +56,10 @@ PreviewsLitePageDecider::MaybeCreateThrottleFor( ...@@ -54,6 +56,10 @@ PreviewsLitePageDecider::MaybeCreateThrottleFor(
return nullptr; return nullptr;
} }
void PreviewsLitePageDecider::SetClockForTesting(const base::TickClock* clock) {
clock_ = clock;
}
bool PreviewsLitePageDecider::IsDataSaverEnabled( bool PreviewsLitePageDecider::IsDataSaverEnabled(
content::NavigationHandle* handle) const { content::NavigationHandle* handle) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
...@@ -84,3 +90,34 @@ bool PreviewsLitePageDecider::IsServerUnavailable(base::TimeTicks now) { ...@@ -84,3 +90,34 @@ bool PreviewsLitePageDecider::IsServerUnavailable(base::TimeTicks now) {
retry_at_.reset(); retry_at_.reset();
return server_loadshedding; return server_loadshedding;
} }
void PreviewsLitePageDecider::AddSingleBypass(std::string url) {
// Garbage collect any old entries while looking for the one for |url|.
auto entry = single_bypass_.end();
for (auto iter = single_bypass_.begin(); iter != single_bypass_.end();
/* no increment */) {
if (iter->second < clock_->NowTicks()) {
iter = single_bypass_.erase(iter);
continue;
}
if (iter->first == url)
entry = iter;
++iter;
}
// Update the entry for |url|.
const base::TimeTicks ttl =
clock_->NowTicks() + base::TimeDelta::FromMinutes(5);
if (entry == single_bypass_.end()) {
single_bypass_.emplace(url, ttl);
return;
}
entry->second = ttl;
}
bool PreviewsLitePageDecider::CheckSingleBypass(std::string url) {
auto entry = single_bypass_.find(url);
if (entry == single_bypass_.end())
return false;
return entry->second >= clock_->NowTicks();
}
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
#ifndef CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_DECIDER_H_ #ifndef CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_DECIDER_H_
#define CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_DECIDER_H_ #define CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_DECIDER_H_
#include <map>
#include <memory> #include <memory>
#include <unordered_map>
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h" #include "chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h"
...@@ -35,20 +36,33 @@ class PreviewsLitePageDecider ...@@ -35,20 +36,33 @@ class PreviewsLitePageDecider
static std::unique_ptr<content::NavigationThrottle> MaybeCreateThrottleFor( static std::unique_ptr<content::NavigationThrottle> MaybeCreateThrottleFor(
content::NavigationHandle* handle); content::NavigationHandle* handle);
// Sets the internal clock for testing.
void SetClockForTesting(const base::TickClock* clock);
protected: protected:
// Virtual for testing. // Virtual for testing.
virtual bool IsDataSaverEnabled(content::NavigationHandle* handle) const; virtual bool IsDataSaverEnabled(content::NavigationHandle* handle) const;
private: private:
FRIEND_TEST_ALL_PREFIXES(PreviewsLitePageDeciderTest, TestServerUnavailable); FRIEND_TEST_ALL_PREFIXES(PreviewsLitePageDeciderTest, TestServerUnavailable);
FRIEND_TEST_ALL_PREFIXES(PreviewsLitePageDeciderTest, TestSingleBypass);
// PreviewsLitePageNavigationThrottleManager: // PreviewsLitePageNavigationThrottleManager:
void SetServerUnavailableUntil(base::TimeTicks retry_at) override; void SetServerUnavailableUntil(base::TimeTicks retry_at) override;
bool IsServerUnavailable(base::TimeTicks now) override; bool IsServerUnavailable(base::TimeTicks now) override;
void AddSingleBypass(std::string url) override;
bool CheckSingleBypass(std::string url) override;
// The time after which it is ok to send the server more preview requests. // The time after which it is ok to send the server more preview requests.
base::Optional<base::TimeTicks> retry_at_; base::Optional<base::TimeTicks> retry_at_;
// A map that tracks the time at which a URL will stop being bypassed.
std::unordered_map<std::string, base::TimeTicks> single_bypass_;
// The clock used for getting the current time ticks. Use |SetClockForTesting|
// in tests.
const base::TickClock* clock_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(PreviewsLitePageDecider); DISALLOW_COPY_AND_ASSIGN(PreviewsLitePageDecider);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
class PreviewsLitePageDeciderTest : public testing::Test { class PreviewsLitePageDeciderTest : public testing::Test {
...@@ -43,3 +44,46 @@ TEST_F(PreviewsLitePageDeciderTest, TestServerUnavailable) { ...@@ -43,3 +44,46 @@ TEST_F(PreviewsLitePageDeciderTest, TestServerUnavailable) {
test_case.want_is_unavailable); test_case.want_is_unavailable);
} }
} }
TEST_F(PreviewsLitePageDeciderTest, TestSingleBypass) {
const std::string kUrl = "http://test.com";
struct TestCase {
std::string add_url;
base::TimeDelta clock_advance;
std::string check_url;
bool want_check;
};
const TestCase kTestCases[]{
{
kUrl, base::TimeDelta::FromMinutes(1), kUrl, true,
},
{
kUrl, base::TimeDelta::FromMinutes(6), kUrl, false,
},
{
"bad", base::TimeDelta::FromMinutes(1), kUrl, false,
},
{
"bad", base::TimeDelta::FromMinutes(6), kUrl, false,
},
{
kUrl, base::TimeDelta::FromMinutes(1), "bad", false,
},
{
kUrl, base::TimeDelta::FromMinutes(6), "bad", false,
},
};
for (const TestCase& test_case : kTestCases) {
std::unique_ptr<PreviewsLitePageDecider> decider =
std::make_unique<PreviewsLitePageDecider>();
std::unique_ptr<base::SimpleTestTickClock> clock =
std::make_unique<base::SimpleTestTickClock>();
decider->SetClockForTesting(clock.get());
decider->AddSingleBypass(test_case.add_url);
clock->Advance(test_case.clock_advance);
EXPECT_EQ(decider->CheckSingleBypass(test_case.check_url),
test_case.want_check);
}
}
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
#include "content/public/common/referrer.h" #include "content/public/common/referrer.h"
#include "crypto/sha2.h" #include "crypto/sha2.h"
#include "net/base/escape.h" #include "net/base/escape.h"
#include "net/base/url_util.h"
#include "net/http/http_status_code.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace { namespace {
...@@ -26,6 +29,19 @@ bool IsPreviewsDomain(const GURL& url) { ...@@ -26,6 +29,19 @@ bool IsPreviewsDomain(const GURL& url) {
url.EffectiveIntPort() == previews_host.EffectiveIntPort(); url.EffectiveIntPort() == previews_host.EffectiveIntPort();
} }
content::OpenURLParams MakeOpenURLParams(content::NavigationHandle* handle,
GURL url) {
content::OpenURLParams url_params(
url, handle->GetReferrer(), WindowOpenDisposition::CURRENT_TAB,
handle->GetPageTransition(), handle->IsRendererInitiated());
// TODO(crbug.com/864652): Add chrome-proxy headers if this is a Preview.
url_params.redirect_chain = handle->GetRedirectChain();
url_params.frame_tree_node_id = handle->GetFrameTreeNodeId();
url_params.user_gesture = handle->HasUserGesture();
url_params.started_from_context_menu = handle->WasStartedFromContextMenu();
return url_params;
}
} // namespace } // namespace
class WebContentsLifetimeHelper class WebContentsLifetimeHelper
...@@ -79,6 +95,24 @@ bool PreviewsLitePageNavigationThrottle::IsEligibleForPreview() const { ...@@ -79,6 +95,24 @@ bool PreviewsLitePageNavigationThrottle::IsEligibleForPreview() const {
return true; return true;
} }
// static
bool PreviewsLitePageNavigationThrottle::GetOriginalURL(
GURL url,
std::string* original_url) {
if (!url.is_valid())
return false;
if (!IsPreviewsDomain(url))
return false;
std::string original_url_query_param;
if (!net::GetValueForKeyInQuery(url, "u", &original_url_query_param))
return false;
*original_url = original_url_query_param;
return true;
}
GURL PreviewsLitePageNavigationThrottle::GetPreviewsURL() const { GURL PreviewsLitePageNavigationThrottle::GetPreviewsURL() const {
GURL original_url = navigation_handle()->GetURL(); GURL original_url = navigation_handle()->GetURL();
DCHECK(original_url.is_valid()); DCHECK(original_url.is_valid());
...@@ -101,23 +135,8 @@ GURL PreviewsLitePageNavigationThrottle::GetPreviewsURL() const { ...@@ -101,23 +135,8 @@ GURL PreviewsLitePageNavigationThrottle::GetPreviewsURL() const {
} }
content::NavigationThrottle::ThrottleCheckResult content::NavigationThrottle::ThrottleCheckResult
PreviewsLitePageNavigationThrottle::MaybeNavigateToPreview() const { PreviewsLitePageNavigationThrottle::CreateNewNavigation(
if (!IsEligibleForPreview()) { content::OpenURLParams url_params) const {
return content::NavigationThrottle::PROCEED;
}
content::OpenURLParams url_params(GetPreviewsURL(),
navigation_handle()->GetReferrer(),
WindowOpenDisposition::CURRENT_TAB,
navigation_handle()->GetPageTransition(),
navigation_handle()->IsRendererInitiated());
// TODO(crbug.com/864652): Add chrome-proxy headers.
url_params.redirect_chain = navigation_handle()->GetRedirectChain();
url_params.frame_tree_node_id = navigation_handle()->GetFrameTreeNodeId();
url_params.user_gesture = navigation_handle()->HasUserGesture();
url_params.started_from_context_menu =
navigation_handle()->WasStartedFromContextMenu();
// The helper class and its weak pointer protect against the WebContents // The helper class and its weak pointer protect against the WebContents
// dying in-between the PostTask and its execution, resulting in a use after // dying in-between the PostTask and its execution, resulting in a use after
// free bug. Since the helper is a WebContentsUserData, it will be // free bug. Since the helper is a WebContentsUserData, it will be
...@@ -134,6 +153,26 @@ PreviewsLitePageNavigationThrottle::MaybeNavigateToPreview() const { ...@@ -134,6 +153,26 @@ PreviewsLitePageNavigationThrottle::MaybeNavigateToPreview() const {
return content::NavigationThrottle::CANCEL; return content::NavigationThrottle::CANCEL;
} }
content::NavigationThrottle::ThrottleCheckResult
PreviewsLitePageNavigationThrottle::TriggerPreview() const {
content::OpenURLParams url_params =
MakeOpenURLParams(navigation_handle(), GetPreviewsURL());
return CreateNewNavigation(url_params);
}
content::NavigationThrottle::ThrottleCheckResult
PreviewsLitePageNavigationThrottle::MaybeNavigateToPreview() const {
const GURL url = navigation_handle()->GetURL();
if (!IsEligibleForPreview())
return content::NavigationThrottle::PROCEED;
// Make sure we're not trying to bypass this navigation.
if (manager_->CheckSingleBypass(url.spec()))
return content::NavigationThrottle::PROCEED;
return TriggerPreview();
}
content::NavigationThrottle::ThrottleCheckResult content::NavigationThrottle::ThrottleCheckResult
PreviewsLitePageNavigationThrottle::WillStartRequest() { PreviewsLitePageNavigationThrottle::WillStartRequest() {
return MaybeNavigateToPreview(); return MaybeNavigateToPreview();
...@@ -146,12 +185,50 @@ PreviewsLitePageNavigationThrottle::WillRedirectRequest() { ...@@ -146,12 +185,50 @@ PreviewsLitePageNavigationThrottle::WillRedirectRequest() {
content::NavigationThrottle::ThrottleCheckResult content::NavigationThrottle::ThrottleCheckResult
PreviewsLitePageNavigationThrottle::WillFailRequest() { PreviewsLitePageNavigationThrottle::WillFailRequest() {
return content::NavigationThrottle::PROCEED; std::string original_url;
if (!GetOriginalURL(navigation_handle()->GetURL(), &original_url))
return content::NavigationThrottle::PROCEED;
// The Preview was triggered but there was some irrecoverable issue (like
// there is no network connection). Load the original page and let it go
// through the normal process for whatever error it is.
manager_->AddSingleBypass(original_url);
content::OpenURLParams url_params =
MakeOpenURLParams(navigation_handle(), GURL(original_url));
return CreateNewNavigation(url_params);
} }
content::NavigationThrottle::ThrottleCheckResult content::NavigationThrottle::ThrottleCheckResult
PreviewsLitePageNavigationThrottle::WillProcessResponse() { PreviewsLitePageNavigationThrottle::WillProcessResponse() {
return content::NavigationThrottle::PROCEED; const net::HttpResponseHeaders* response_headers =
navigation_handle()->GetResponseHeaders();
if (!response_headers)
return content::NavigationThrottle::PROCEED;
std::string original_url;
if (!GetOriginalURL(navigation_handle()->GetURL(), &original_url)) {
// Return early if this request was not for a Preview.
return content::NavigationThrottle::PROCEED;
}
// After this point, the given response is known to be for a Preview.
// The Previews server will only send the following response codes: 200, 307,
// 404, and 503. 200 and 307 should proceed as normal, 404 and 503 request the
// client to load the original page instead because the server is not capable
// of generating a lite page. All other response codes are treated as a 404.
const int response_code = response_headers->response_code();
if (response_code == net::HTTP_OK ||
response_code == net::HTTP_TEMPORARY_REDIRECT)
return content::NavigationThrottle::PROCEED;
manager_->AddSingleBypass(original_url);
content::OpenURLParams url_params =
MakeOpenURLParams(navigation_handle(), GURL(original_url));
return CreateNewNavigation(url_params);
} }
const char* PreviewsLitePageNavigationThrottle::GetNameForLogging() { const char* PreviewsLitePageNavigationThrottle::GetNameForLogging() {
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
#include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h" #include "content/public/browser/navigation_throttle.h"
namespace content {
struct OpenURLParams;
}
// This class does the actual decision making about when to serve a Lite Page // This class does the actual decision making about when to serve a Lite Page
// Server Preview, and the legwork to trigger the Preview navigation. When a // Server Preview, and the legwork to trigger the Preview navigation. When a
// Preview is triggered, it will cancel the incoming navigation and PostTask a // Preview is triggered, it will cancel the incoming navigation and PostTask a
...@@ -22,6 +26,10 @@ class PreviewsLitePageNavigationThrottle : public content::NavigationThrottle { ...@@ -22,6 +26,10 @@ class PreviewsLitePageNavigationThrottle : public content::NavigationThrottle {
~PreviewsLitePageNavigationThrottle() override; ~PreviewsLitePageNavigationThrottle() override;
// Attempts to extract the original URL from the given Previews URL. Returns
// false if |url| is not a valid Preview URL.
static bool GetOriginalURL(GURL url, std::string* original_url);
private: private:
FRIEND_TEST_ALL_PREFIXES(PreviewsLitePageNavigationThrottleTest, FRIEND_TEST_ALL_PREFIXES(PreviewsLitePageNavigationThrottleTest,
TestGetPreviewsURL); TestGetPreviewsURL);
...@@ -44,6 +52,19 @@ class PreviewsLitePageNavigationThrottle : public content::NavigationThrottle { ...@@ -44,6 +52,19 @@ class PreviewsLitePageNavigationThrottle : public content::NavigationThrottle {
content::NavigationThrottle::ThrottleCheckResult MaybeNavigateToPreview() content::NavigationThrottle::ThrottleCheckResult MaybeNavigateToPreview()
const; const;
// Can be called by any of the content::NavigationThrottle implementation
// methods to create a new navigation with the give |content::OpenURLParams|.
// Returns the |content::NavigationThrottle::ThrottleCheckResult| for the
// implemented method to return.
content::NavigationThrottle::ThrottleCheckResult CreateNewNavigation(
content::OpenURLParams url_params) const;
// Can be called by any of the content::NavigationThrottle implementation
// methods to trigger the preview. Returns the
// |content::NavigationThrottle::ThrottleCheckResult| for the implemented
// method to return.
content::NavigationThrottle::ThrottleCheckResult TriggerPreview() const;
// content::NavigationThrottle implementation: // content::NavigationThrottle implementation:
content::NavigationThrottle::ThrottleCheckResult WillStartRequest() override; content::NavigationThrottle::ThrottleCheckResult WillStartRequest() override;
content::NavigationThrottle::ThrottleCheckResult WillRedirectRequest() content::NavigationThrottle::ThrottleCheckResult WillRedirectRequest()
......
...@@ -21,6 +21,13 @@ class PreviewsLitePageNavigationThrottleManager { ...@@ -21,6 +21,13 @@ class PreviewsLitePageNavigationThrottleManager {
// Returns true if a Preview should not be triggered because the server is // Returns true if a Preview should not be triggered because the server is
// unavailable. // unavailable.
virtual bool IsServerUnavailable(base::TimeTicks now) = 0; virtual bool IsServerUnavailable(base::TimeTicks now) = 0;
// Informs the manager that the given URL should be bypassed one time.
virtual void AddSingleBypass(std::string url) = 0;
// Queries the manager if the given URL should be bypassed one time, returning
// true if yes.
virtual bool CheckSingleBypass(std::string url) = 0;
}; };
#endif // CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_MANAGER_H_ #endif // CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_MANAGER_H_
...@@ -135,3 +135,48 @@ TEST_F(PreviewsLitePageNavigationThrottleTest, TestGetPreviewsURL) { ...@@ -135,3 +135,48 @@ TEST_F(PreviewsLitePageNavigationThrottleTest, TestGetPreviewsURL) {
SimulateWillProcessResponse(); SimulateWillProcessResponse();
CallDidFinishNavigation(); CallDidFinishNavigation();
} }
TEST_F(PreviewsLitePageNavigationThrottleTest, TestGetOriginalURL) {
struct TestCase {
std::string previews_host;
std::string original_url;
std::string previews_url;
bool want_ok;
};
const TestCase kTestCases[]{
// Use https://play.golang.org/p/HUM2HxmUTOW to compute |previews_url|.
{
"https://previews.host.com",
"https://original.host.com/path/path/path?query=yes",
"https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua."
"previews.host.com/p?u="
"https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes",
true,
},
{
"https://previews.host.com",
"http://original.host.com/path/path/path?query=yes",
"https://6p7dar4ju6r4ynz7x3pucmlcltuqsf7z5auhvckzln7voglkt56q."
"previews.host.com/p?u="
"http%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes",
true,
},
};
for (const TestCase& test_case : kTestCases) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
previews::features::kLitePageServerPreviews,
{{"previews_host", test_case.previews_host}});
std::string original_url;
bool got_ok = PreviewsLitePageNavigationThrottle::GetOriginalURL(
GURL(test_case.previews_url), &original_url);
EXPECT_EQ(got_ok, test_case.want_ok);
EXPECT_EQ(original_url, test_case.original_url);
}
// Boilerplate navigation to keep the test harness happy.
SimulateWillProcessResponse();
CallDidFinishNavigation();
}
...@@ -129,6 +129,12 @@ base::TimeDelta OfflinePreviewFreshnessDuration() { ...@@ -129,6 +129,12 @@ base::TimeDelta OfflinePreviewFreshnessDuration() {
"offline_preview_freshness_duration_in_days", 7)); "offline_preview_freshness_duration_in_days", 7));
} }
base::TimeDelta LitePagePreviewsSingleBypassDuration() {
return base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
features::kLitePageServerPreviews, "single_bypass_duration_in_seconds",
60 * 5));
}
GURL GetLitePagePreviewsDomainURL() { GURL GetLitePagePreviewsDomainURL() {
std::string variable_host_str = GetFieldTrialParamValueByFeature( std::string variable_host_str = GetFieldTrialParamValueByFeature(
features::kLitePageServerPreviews, "previews_host"); features::kLitePageServerPreviews, "previews_host");
......
...@@ -92,6 +92,9 @@ base::TimeDelta OfflinePreviewFreshnessDuration(); ...@@ -92,6 +92,9 @@ base::TimeDelta OfflinePreviewFreshnessDuration();
// The host for Lite Page server previews. // The host for Lite Page server previews.
GURL GetLitePagePreviewsDomainURL(); GURL GetLitePagePreviewsDomainURL();
// The duration of a single bypass for Lite Page Server Previews.
base::TimeDelta LitePagePreviewsSingleBypassDuration();
// The threshold of EffectiveConnectionType above which preview |type| will be // The threshold of EffectiveConnectionType above which preview |type| will be
// triggered. // triggered.
net::EffectiveConnectionType GetECTThresholdForPreview( net::EffectiveConnectionType GetECTThresholdForPreview(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment