File: service_worker_main_resource_handle.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (130 lines) | stat: -rw-r--r-- 5,687 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/service_worker/service_worker_main_resource_handle.h"

#include <utility>

#include "base/functional/bind.h"
#include "content/browser/preloading/prefetch/prefetch_features.h"
#include "content/browser/renderer_host/policy_container_host.h"
#include "content/browser/service_worker/service_worker_client.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_routing_id.h"
#include "net/base/isolation_info.h"
#include "net/base/url_util.h"
#include "net/cookies/site_for_cookies.h"
#include "services/network/public/cpp/cross_origin_embedder_policy.h"

namespace content {

ServiceWorkerMainResourceHandle::ServiceWorkerMainResourceHandle(
    scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
    ServiceWorkerAccessedCallback on_service_worker_accessed,
    std::string fetch_event_client_id,
    base::WeakPtr<ServiceWorkerClient> parent_service_worker_client)
    : parent_service_worker_client_(std::move(parent_service_worker_client)),
      fetch_event_client_id_(std::move(fetch_event_client_id)),
      service_worker_accessed_callback_(std::move(on_service_worker_accessed)),
      context_wrapper_(std::move(context_wrapper)) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

ServiceWorkerMainResourceHandle::~ServiceWorkerMainResourceHandle() = default;

void ServiceWorkerMainResourceHandle::set_service_worker_client(
    ScopedServiceWorkerClient scoped_service_worker_client,
    const net::IsolationInfo& isolation_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  CHECK(!scoped_service_worker_client_);

  scoped_service_worker_client_ = std::make_unique<ScopedServiceWorkerClient>(
      std::move(scoped_service_worker_client));
  isolation_info_ = isolation_info;

  CHECK(service_worker_client());
}

base::WeakPtr<ServiceWorkerClient>
ServiceWorkerMainResourceHandle::service_worker_client() {
  if (!scoped_service_worker_client_) {
    return nullptr;
  }
  return scoped_service_worker_client_->AsWeakPtr();
}

bool ServiceWorkerMainResourceHandle::InitializeForRequest(
    const network::ResourceRequest& tentative_resource_request,
    const ServiceWorkerClient* client_for_prefetch) {
  CHECK(service_worker_client());

  // Update `isolation_info_`  to equal the net::IsolationInfo needed for any
  // service worker intercepting this request. Here, `isolation_info_` directly
  // corresponds to the StorageKey used to look up the service worker's
  // registration. That StorageKey will then be used later to recreate this
  // net::IsolationInfo for use by the ServiceWorker itself.
  url::Origin new_origin = url::Origin::Create(tentative_resource_request.url);
  net::SiteForCookies new_site_for_cookies = isolation_info_.site_for_cookies();
  new_site_for_cookies.CompareWithFrameTreeOriginAndRevise(new_origin);
  auto new_isolation_info = net::IsolationInfo::Create(
      isolation_info_.request_type(),
      isolation_info_.top_frame_origin().value(), new_origin,
      new_site_for_cookies, isolation_info_.nonce());

  // The storage key only has a top_level_site, not an origin, so we must
  // extract the origin from trusted_params.
  auto top_frame_origin = tentative_resource_request.trusted_params
                              ? tentative_resource_request.trusted_params
                                    ->isolation_info.top_frame_origin()
                              : std::nullopt;

  auto key = service_worker_client()->CalculateStorageKeyForUpdateUrls(
      tentative_resource_request.url, new_isolation_info);

  if (client_for_prefetch) {
    CHECK(base::FeatureList::IsEnabled(features::kPrefetchServiceWorker));
    CHECK(service_worker_client()->IsContainerForWindowClient());
    CHECK(client_for_prefetch->IsContainerForWindowClient());
    // If top_frame_origin/key don't match, do not use the prefetch result.
    // `this` remains unmodified, and `InitializeForRequest` will be called
    // later in the non-prefetch code path.
    if (client_for_prefetch->top_frame_origin() != top_frame_origin ||
        client_for_prefetch->key() != key) {
      return false;
    }
  }

  isolation_info_ = std::move(new_isolation_info);

  // Clear old controller state if this is a redirect.
  service_worker_client()->SetControllerRegistration(
      nullptr,
      /*notify_controllerchange=*/false);

  // Update the service worker client. This is important to do this on every
  // requests/redirects before falling back to network below, so service worker
  // APIs still work even if the service worker is bypassed for request
  // interception.
  service_worker_client()->UpdateUrls(tentative_resource_request.url,
                                      std::move(top_frame_origin),
                                      std::move(key));

  // Inherit the controller used for prefetching from `client_for_prefetch`.
  if (client_for_prefetch && client_for_prefetch->controller_registration()) {
    service_worker_client()->AddMatchingRegistration(
        client_for_prefetch->controller_registration());
    // `client_for_prefetch` shouldn't be in back forward cache because it's for
    // prefetch.
    CHECK(!client_for_prefetch->is_in_back_forward_cache());
    service_worker_client()->SetControllerRegistration(
        client_for_prefetch->controller_registration(),
        /*notify_controllerchange=*/false);
  }

  return true;
}

}  // namespace content