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

ash / webui / annotator / untrusted_annotator_ui.cc [blame]

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "ash/webui/annotator/untrusted_annotator_ui.h"

#include "ash/webui/grit/ash_annotator_untrusted_resources.h"
#include "ash/webui/grit/ash_annotator_untrusted_resources_map.h"
#include "ash/webui/grit/ash_projector_common_resources.h"
#include "ash/webui/grit/ash_projector_common_resources_map.h"
#include "ash/webui/media_app_ui/buildflags.h"
#include "ash/webui/projector_app/public/cpp/projector_app_constants.h"
#include "ash/webui/annotator/untrusted_annotator_page_handler_impl.h"
#include "chromeos/grit/chromeos_projector_app_bundle_resources.h"
#include "chromeos/grit/chromeos_projector_app_bundle_resources_map.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/url_constants.h"
#include "url/gurl.h"

#if BUILDFLAG(ENABLE_CROS_MEDIA_APP)
#include "chromeos/grit/chromeos_media_app_bundle_resources.h"
#endif  // BUILDFLAG(ENABLE_CROS_MEDIA_APP)

namespace ash {

namespace {

void CreateAndAddAnnotatorHTMLSource(
    content::WebUI* web_ui,
    UntrustedAnnotatorUIDelegate* delegate) {
  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
      web_ui->GetWebContents()->GetBrowserContext(),
      kChromeUIUntrustedAnnotatorUrl);

  // TODO(b/216523790): Split untrusted annotator resources into a separate
  // bundle.
  source->AddResourcePaths(kAshAnnotatorUntrustedResources);
  source->AddResourcePaths(kChromeosProjectorAppBundleResources);
  source->AddResourcePaths(kAshProjectorCommonResources);
  source->AddResourcePath("",
                          IDR_ASH_ANNOTATOR_UNTRUSTED_ANNOTATOR_HTML);

#if BUILDFLAG(ENABLE_CROS_MEDIA_APP)
  // Loads WASM resources shipped to Chromium by chrome://media-app.
  source->AddResourcePath("ink_engine_ink.worker.js",
                          IDR_MEDIA_APP_INK_ENGINE_INK_WORKER_JS);
  source->AddResourcePath("ink_engine_ink.wasm",
                          IDR_MEDIA_APP_INK_ENGINE_INK_WASM);
  source->AddResourcePath("ink.js", IDR_MEDIA_APP_INK_JS);
#endif  // BUILDFLAG(ENABLE_CROS_MEDIA_APP)

  // Provide a list of specific script resources (javascript files and inlined
  // scripts inside html) or their sha-256 hashes to allow to be executed.
  // "wasm-eval" is added to allow wasm.
  source->OverrideContentSecurityPolicy(
      network::mojom::CSPDirectiveName::ScriptSrc,
      "script-src 'self' 'wasm-eval' chrome-untrusted://resources;");
  // Need to explicitly set |worker-src| because CSP falls back to |child-src|
  // which is none.
  source->OverrideContentSecurityPolicy(
      network::mojom::CSPDirectiveName::WorkerSrc, "worker-src 'self';");
  // Allow styles to include inline styling needed for Polymer elements.
  source->OverrideContentSecurityPolicy(
      network::mojom::CSPDirectiveName::StyleSrc,
      "style-src 'self' 'unsafe-inline';");
  // Allow images to also handle data urls.
  source->OverrideContentSecurityPolicy(
      network::mojom::CSPDirectiveName::ImgSrc, "img-src blob: data: 'self';");
  source->OverrideContentSecurityPolicy(
      network::mojom::CSPDirectiveName::ConnectSrc, "connect-src 'self';");

  // Allow use of SharedArrayBuffer (required by the wasm).
  source->OverrideCrossOriginOpenerPolicy("same-origin");
  source->OverrideCrossOriginEmbedderPolicy("require-corp");

  // chrome://projector-annotator and chrome-untrusted://projector-annotator are
  // different origins, so allow resources in the untrusted origin to be loaded
  // cross-origin.
  source->OverrideCrossOriginResourcePolicy("cross-origin");

  // Loading WASM in chrome-untrusted://projector-annotator/annotator/ink.js is
  // not compatible with trusted types.
  source->DisableTrustedTypesCSP();
  delegate->PopulateLoadTimeData(source);
  source->UseStringsJs();
}

}  // namespace

UntrustedAnnotatorUI::UntrustedAnnotatorUI(
    content::WebUI* web_ui,
    UntrustedAnnotatorUIDelegate* delegate)
    : UntrustedWebUIController(web_ui) {
  CreateAndAddAnnotatorHTMLSource(web_ui, delegate);
}

UntrustedAnnotatorUI::~UntrustedAnnotatorUI() = default;

void UntrustedAnnotatorUI::BindInterface(
    mojo::PendingReceiver<
        annotator::mojom::UntrustedAnnotatorPageHandlerFactory> factory) {
  if (receiver_.is_bound()) {
    receiver_.reset();
  }
  receiver_.Bind(std::move(factory));
}

void UntrustedAnnotatorUI::Create(
    mojo::PendingReceiver<annotator::mojom::UntrustedAnnotatorPageHandler>
        annotator_handler,
    mojo::PendingRemote<annotator::mojom::UntrustedAnnotatorPage> annotator) {
  handler_ = std::make_unique<UntrustedAnnotatorPageHandlerImpl>(
      std::move(annotator_handler), std::move(annotator), web_ui());
}

WEB_UI_CONTROLLER_TYPE_IMPL(UntrustedAnnotatorUI)

}  // namespace ash