| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/renderer/ash_merge_session_loader_throttle.h" |
| |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/functional/bind.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/renderer/chrome_render_thread_observer.h" |
| #include "components/google/core/common/google_util.h" |
| #include "net/url_request/redirect_info.h" |
| #include "services/network/public/cpp/resource_request.h" |
| #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" |
| |
| namespace { |
| bool ShouldDelayUrl(const GURL& url) { |
| // TODO(b/320891641) - We should ideally call |
| // `ash::merge_session_throttling_utils::ShouldDelayUrl()` but can't because |
| // of include dependencies issues. Figure out how to extract the common |
| // components. |
| // We need to throttle requests to Google web properties while cookie minting |
| // is in progress (Signalled by |
| // `chromeos_listener_->IsMergeSessionRunning()`). If we do not do this, users |
| // will get a "Sign in to Google" prompt while visiting Google web properties |
| // - which is not the expected user experience on ChromeOS / Ash. Users expect |
| // a Single Sign On experience on ChromeOS - i.e. when they sign-in to |
| // ChromeOS at the ChromeOS login screen, they expect to be signed into Google |
| // web properties inside their session. Since there can be a delay in minting |
| // Google cookies on the user's behalf - and they can navigate to Google web |
| // properties in the browser while cookies are being minted, we need to |
| // throttle these requests. At the same time, we do not want to throttle |
| // requests for non-Google web properties (see http://b/315072145 [note: |
| // Google-internal link, but the context matches what's described in this |
| // comment]). |
| return google_util::IsGoogleDomainUrl(url, google_util::ALLOW_SUBDOMAIN, |
| google_util::ALLOW_NON_STANDARD_PORTS); |
| } |
| } // namespace |
| |
| // static |
| base::TimeDelta AshMergeSessionLoaderThrottle::GetMergeSessionTimeout() { |
| if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kShortMergeSessionTimeoutForTest)) { |
| return base::Seconds(1); |
| } else { |
| return base::Seconds(20); |
| } |
| } |
| |
| AshMergeSessionLoaderThrottle::AshMergeSessionLoaderThrottle( |
| scoped_refptr<ChromeRenderThreadObserver::ChromeOSListener> |
| chromeos_listener) |
| : chromeos_listener_(std::move(chromeos_listener)) {} |
| |
| AshMergeSessionLoaderThrottle::~AshMergeSessionLoaderThrottle() = default; |
| |
| bool AshMergeSessionLoaderThrottle::MaybeDeferForMergeSession( |
| const GURL& url, |
| DelayedCallbackGroup::Callback resume_callback) { |
| if (!chromeos_listener_ || !chromeos_listener_->IsMergeSessionRunning()) { |
| return false; |
| } |
| |
| if (!ShouldDelayUrl(url)) { |
| return false; |
| } |
| |
| chromeos_listener_->RunWhenMergeSessionFinished(std::move(resume_callback)); |
| return true; |
| } |
| |
| void AshMergeSessionLoaderThrottle::WillStartRequest( |
| network::ResourceRequest* request, |
| bool* defer) { |
| is_xhr_ = request->resource_type == |
| static_cast<int>(blink::mojom::ResourceType::kXhr); |
| if (is_xhr_ && request->url.SchemeIsHTTPOrHTTPS() && |
| MaybeDeferForMergeSession( |
| request->url, |
| base::BindOnce(&AshMergeSessionLoaderThrottle::ResumeLoader, |
| weak_ptr_factory_.GetWeakPtr()))) { |
| *defer = true; |
| } |
| } |
| |
| void AshMergeSessionLoaderThrottle::WillRedirectRequest( |
| net::RedirectInfo* redirect_info, |
| const network::mojom::URLResponseHead& /* response_head */, |
| bool* defer, |
| std::vector<std::string>* to_be_removed_headers, |
| net::HttpRequestHeaders* modified_headers, |
| net::HttpRequestHeaders* modified_cors_exempt_headers) { |
| if (is_xhr_ && redirect_info->new_url.SchemeIsHTTPOrHTTPS() && |
| MaybeDeferForMergeSession( |
| redirect_info->new_url, |
| base::BindOnce(&AshMergeSessionLoaderThrottle::ResumeLoader, |
| weak_ptr_factory_.GetWeakPtr()))) { |
| *defer = true; |
| } |
| } |
| |
| void AshMergeSessionLoaderThrottle::DetachFromCurrentSequence() {} |
| |
| void AshMergeSessionLoaderThrottle::ResumeLoader( |
| DelayedCallbackGroup::RunReason run_reason) { |
| LOG_IF(ERROR, run_reason == DelayedCallbackGroup::RunReason::TIMEOUT) |
| << "Merge session loader throttle timeout."; |
| DVLOG(1) << "Resuming deferred XHR request."; |
| delegate_->Resume(); |
| } |