910e62b5创建于 1月15日历史提交
// Copyright 2014 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/renderer/worker/embedded_shared_worker_stub.h"

#include <stdint.h>

#include <algorithm>
#include <utility>

#include "base/containers/to_vector.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "content/renderer/content_security_policy_util.h"
#include "content/renderer/policy_container_util.h"
#include "content/renderer/worker/fetch_client_settings_object_helpers.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/worker_main_script_load_parameters.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
#include "third_party/blink/public/mojom/browser_interface_broker.mojom.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h"
#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h"
#include "third_party/blink/public/platform/child_url_loader_factory_bundle.h"
#include "third_party/blink/public/platform/web_dedicated_or_shared_worker_global_scope_context.h"
#include "third_party/blink/public/platform/web_fetch_client_settings_object.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_shared_worker.h"
#include "url/origin.h"

namespace content {

EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
    blink::mojom::SharedWorkerInfoPtr info,
    const blink::SharedWorkerToken& token,
    const blink::StorageKey& constructor_key,
    const url::Origin& origin,
    bool is_constructor_secure_context,
    const std::string& user_agent,
    const blink::UserAgentMetadata& ua_metadata,
    bool pause_on_start,
    const base::UnguessableToken& devtools_worker_token,
    const blink::RendererPreferences& renderer_preferences,
    mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
        preference_watcher_receiver,
    mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
        content_settings,
    blink::mojom::ServiceWorkerContainerInfoForClientPtr
        service_worker_container_info,
    blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
    std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
        pending_subresource_loader_factory_bundle,
    blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
    blink::mojom::PolicyContainerPtr policy_container,
    mojo::PendingRemote<blink::mojom::SharedWorkerHost> host,
    mojo::PendingReceiver<blink::mojom::SharedWorker> receiver,
    mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
        browser_interface_broker,
    ukm::SourceId ukm_source_id,
    bool require_cross_site_request_for_cookies,
    mojo::PendingReceiver<blink::mojom::ReportingObserver>
        coep_reporting_observer,
    mojo::PendingReceiver<blink::mojom::ReportingObserver>
        dip_reporting_observer,
    const std::vector<std::string>& cors_exempt_header_list)
    : receiver_(this, std::move(receiver)) {
  DCHECK(main_script_load_params);
  DCHECK(pending_subresource_loader_factory_bundle);

  // Initialize the loading parameters for the main worker script loaded by
  // the browser process.
  auto worker_main_script_load_params =
      std::make_unique<blink::WorkerMainScriptLoadParameters>();
  worker_main_script_load_params->request_id =
      main_script_load_params->request_id;
  worker_main_script_load_params->response_head =
      std::move(main_script_load_params->response_head);
  worker_main_script_load_params->response_body =
      std::move(main_script_load_params->response_body);
  worker_main_script_load_params->redirect_responses =
      std::move(main_script_load_params->redirect_response_heads);
  worker_main_script_load_params->redirect_infos =
      main_script_load_params->redirect_infos;
  worker_main_script_load_params->url_loader_client_endpoints =
      std::move(main_script_load_params->url_loader_client_endpoints);

  // If the network service crashes, then self-destruct so clients don't get
  // stuck with a worker with a broken loader. Self-destruction is effectively
  // the same as the worker's process crashing.
  default_factory_disconnect_handler_holder_.Bind(std::move(
      pending_subresource_loader_factory_bundle->pending_default_factory()));
  default_factory_disconnect_handler_holder_->Clone(
      pending_subresource_loader_factory_bundle->pending_default_factory()
          .InitWithNewPipeAndPassReceiver());
  default_factory_disconnect_handler_holder_.set_disconnect_handler(
      base::BindOnce(&EmbeddedSharedWorkerStub::Terminate,
                     base::Unretained(this)));

  // Initialize the subresource loader factory bundle passed by the browser
  // process.
  subresource_loader_factory_bundle_ =
      base::MakeRefCounted<blink::ChildURLLoaderFactoryBundle>(
          std::make_unique<blink::ChildPendingURLLoaderFactoryBundle>(
              std::move(pending_subresource_loader_factory_bundle)));

  if (service_worker_container_info) {
    service_worker_provider_context_ =
        base::MakeRefCounted<ServiceWorkerProviderContext>(
            blink::mojom::ServiceWorkerContainerType::kForSharedWorker,
            std::move(service_worker_container_info->client_receiver),
            std::move(service_worker_container_info->host_remote),
            std::move(controller_info), subresource_loader_factory_bundle_);
    service_worker_provider_context_->set_container_is_blob_url_shared_worker(
        info->url.SchemeIsBlob());
  }

  scoped_refptr<blink::WebWorkerFetchContext> web_worker_fetch_context =
      CreateWorkerFetchContext(constructor_key, std::move(renderer_preferences),
                               std::move(preference_watcher_receiver),
                               cors_exempt_header_list,
                               require_cross_site_request_for_cookies);

  impl_ = blink::WebSharedWorker::CreateAndStart(
      token, info->url, info->options->type, info->options->credentials,
      blink::WebString::FromUTF8(info->options->name),
      blink::WebSecurityOrigin(constructor_key.origin()),
      blink::WebSecurityOrigin(origin), is_constructor_secure_context,
      blink::WebString::FromUTF8(user_agent), ua_metadata,
      ToWebContentSecurityPolicies(std::move(info->content_security_policies)),
      FetchClientSettingsObjectFromMojomToWeb(
          info->outside_fetch_client_settings_object),
      devtools_worker_token, std::move(content_settings),
      std::move(browser_interface_broker), pause_on_start,
      std::move(worker_main_script_load_params),
      ToWebPolicyContainer(std::move(policy_container)),
      std::move(web_worker_fetch_context), std::move(host), this, ukm_source_id,
      require_cross_site_request_for_cookies,
      std::move(coep_reporting_observer), std::move(dip_reporting_observer));

  // If the host drops its connection, then self-destruct.
  receiver_.set_disconnect_handler(base::BindOnce(
      &EmbeddedSharedWorkerStub::Terminate, base::Unretained(this)));
}

EmbeddedSharedWorkerStub::~EmbeddedSharedWorkerStub() {
  // Destruction closes our connection to the host, triggering the host to
  // cleanup and notify clients of this worker going away.
}

void EmbeddedSharedWorkerStub::WorkerContextDestroyed() {
  delete this;
}

scoped_refptr<blink::WebWorkerFetchContext>
EmbeddedSharedWorkerStub::CreateWorkerFetchContext(
    const blink::StorageKey& constructor_key,
    const blink::RendererPreferences& renderer_preferences,
    mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
        preference_watcher_receiver,
    const std::vector<std::string>& cors_exempt_header_list,
    bool require_cross_site_request_for_cookies) {
  // Make the factory used for service worker network fallback.
  std::unique_ptr<network::PendingSharedURLLoaderFactory> fallback_factory =
      subresource_loader_factory_bundle_->Clone();

  std::vector<blink::WebString> web_cors_exempt_header_list =
      base::ToVector(cors_exempt_header_list, &blink::WebString::FromLatin1);

  // |pending_subresource_loader_updater| and
  // |pending_resource_load_info_notifier| are not used for shared workers.
  scoped_refptr<blink::WebDedicatedOrSharedWorkerGlobalScopeContext>
      web_dedicated_or_shared_worker_global_scope_context =
          blink::WebDedicatedOrSharedWorkerGlobalScopeContext::Create(
              service_worker_provider_context_.get(), renderer_preferences,
              std::move(preference_watcher_receiver),
              subresource_loader_factory_bundle_->Clone(),
              std::move(fallback_factory),
              /*pending_subresource_loader_updater=*/mojo::NullReceiver(),
              web_cors_exempt_header_list,
              /*pending_resource_load_info_notifier=*/mojo::NullRemote());

  web_dedicated_or_shared_worker_global_scope_context->set_site_for_cookies(
      require_cross_site_request_for_cookies
          ? net::SiteForCookies()
          : constructor_key.ToNetSiteForCookies());
  // Since this is within `EmbeddedSharedWorkerStub`, the flag should be
  // definitely true.
  // TODO(crbug.com/324939068): remove the code when the feature launched.
  web_dedicated_or_shared_worker_global_scope_context
      ->set_container_is_shared_worker(true);

  return web_dedicated_or_shared_worker_global_scope_context;
}

void EmbeddedSharedWorkerStub::Connect(int connection_request_id,
                                       blink::MessagePortDescriptor port) {
  impl_->Connect(connection_request_id, std::move(port));
}

void EmbeddedSharedWorkerStub::Terminate() {
  impl_->TerminateWorkerContext();
}

}  // namespace content