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
  131
  132

content / browser / service_worker / service_worker_main_resource_loader_interceptor.h [blame]

// 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.

#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_LOADER_INTERCEPTOR_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_LOADER_INTERCEPTOR_H_

#include <memory>

#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/service_worker_client_info.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/isolation_info.h"
#include "services/network/public/cpp/single_request_url_loader_factory.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"

namespace content {

class ServiceWorkerMainResourceHandle;
struct NavigationRequestInfo;

// Handles navigations for service worker clients (windows and web workers).
// Lives on the UI thread.
//
// The corresponding legacy class is ServiceWorkerControlleeRequestHandler which
// used to live on a different thread. Currently, this class just delegates to
// the legacy class.
// TODO(crbug.com/40725202): Merge the classes together now that they are on
// the same thread.
class CONTENT_EXPORT ServiceWorkerMainResourceLoaderInterceptor final
    : public NavigationLoaderInterceptor {
 public:
  // Creates a ServiceWorkerMainResourceLoaderInterceptor for a navigation.
  // Returns nullptr if the interceptor could not be created for this |url|.
  static std::unique_ptr<NavigationLoaderInterceptor> CreateForNavigation(
      const GURL& url,
      base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle,
      const NavigationRequestInfo& request_info);

  // Creates a ServiceWorkerMainResourceLoaderInterceptor for a worker.
  // Returns nullptr if the interceptor could not be created for the URL of the
  // worker.
  static std::unique_ptr<ServiceWorkerMainResourceLoaderInterceptor>
  CreateForWorker(
      const network::ResourceRequest& resource_request,
      const net::IsolationInfo& isolation_info,
      int process_id,
      const DedicatedOrSharedWorkerToken& worker_token,
      base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle);

  ServiceWorkerMainResourceLoaderInterceptor(
      const ServiceWorkerMainResourceLoaderInterceptor&) = delete;
  ServiceWorkerMainResourceLoaderInterceptor& operator=(
      const ServiceWorkerMainResourceLoaderInterceptor&) = delete;

  ~ServiceWorkerMainResourceLoaderInterceptor() override;

  // NavigationLoaderInterceptor overrides:

  // This could get called multiple times during the lifetime in redirect
  // cases. (In fallback-to-network cases we basically forward the request
  // to the request to the next request handler)
  void MaybeCreateLoader(const network::ResourceRequest& tentative_request,
                         BrowserContext* browser_context,
                         LoaderCallback callback,
                         FallbackCallback fallback_callback) override;

  // MaybeCreateLoaderForResponse() should NOT overridden here, because
  // `WorkerScriptLoader` assumes so.

  static void CompleteWithoutLoader(
      NavigationLoaderInterceptor::LoaderCallback loader_callback,
      base::WeakPtr<ServiceWorkerClient> service_worker_client);

 private:
  friend class ServiceWorkerMainResourceLoaderInterceptorTest;

  ServiceWorkerMainResourceLoaderInterceptor(
      base::WeakPtr<ServiceWorkerMainResourceHandle> handle,
      bool skip_service_worker,
      FrameTreeNodeId frame_tree_node_id,
      const net::IsolationInfo& isolation_info);

  // Returns true if a ServiceWorkerMainResourceLoaderInterceptor should be
  // created for a navigation to |url|.
  static bool ShouldCreateForNavigation(
      const GURL& url,
      network::mojom::RequestDestination request_destination,
      BrowserContext* browser_context);

  // Given as a callback to NavigationURLLoaderImpl.
  void RequestHandlerWrapper(
      network::SingleRequestURLLoaderFactory::RequestHandler handler,
      const network::ResourceRequest& resource_request,
      mojo::PendingReceiver<network::mojom::URLLoader> receiver,
      mojo::PendingRemote<network::mojom::URLLoaderClient> client);

  // For navigations, |handle_| outlives |this|. It's owned by
  // NavigationRequest which outlives NavigationURLLoaderImpl which owns |this|.
  // For workers, |handle_| may be destroyed during interception. It's owned by
  // DedicatedWorkerHost or SharedWorkerHost which may be destroyed before
  // WorkerScriptLoader which owns |this|.
  // TODO(falken): Arrange things so |handle_| outlives |this| for workers too.
  const base::WeakPtr<ServiceWorkerMainResourceHandle> handle_;

  // For all clients:
  const bool skip_service_worker_;

  // Updated on redirects.
  net::IsolationInfo isolation_info_;

  // For window clients:
  // If the intercepted resource load is on behalf
  // of a window, the |frame_tree_node_id_| will be set.
  const FrameTreeNodeId frame_tree_node_id_;

  // Handles a single request. Set to a new instance on redirects.
  std::unique_ptr<ServiceWorkerControlleeRequestHandler> request_handler_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_LOADER_INTERCEPTOR_H_