123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "fuchsia_web/webengine/browser/frame_impl.h"
- #include <fuchsia/ui/gfx/cpp/fidl.h>
- #include <lib/fpromise/result.h>
- #include <lib/sys/cpp/component_context.h>
- #include <lib/ui/scenic/cpp/view_ref_pair.h>
- #include <algorithm>
- #include <limits>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/command_line.h"
- #include "base/fuchsia/fuchsia_logging.h"
- #include "base/fuchsia/mem_buffer_util.h"
- #include "base/fuchsia/process_context.h"
- #include "base/json/json_writer.h"
- #include "base/metrics/user_metrics.h"
- #include "base/strings/strcat.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "content/public/browser/browser_accessibility_state.h"
- #include "content/public/browser/browser_context.h"
- #include "content/public/browser/browser_task_traits.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/host_zoom_map.h"
- #include "content/public/browser/media_session.h"
- #include "content/public/browser/message_port_provider.h"
- #include "content/public/browser/navigation_entry.h"
- #include "content/public/browser/navigation_handle.h"
- #include "content/public/browser/permission_controller.h"
- #include "content/public/browser/render_frame_host.h"
- #include "content/public/browser/render_process_host.h"
- #include "content/public/browser/render_view_host.h"
- #include "content/public/browser/render_widget_host.h"
- #include "content/public/browser/render_widget_host_view.h"
- #include "content/public/browser/renderer_preferences_util.h"
- #include "content/public/browser/web_contents.h"
- #include "fuchsia_web/webengine/browser/accessibility_bridge.h"
- #include "fuchsia_web/webengine/browser/context_impl.h"
- #include "fuchsia_web/webengine/browser/event_filter.h"
- #include "fuchsia_web/webengine/browser/frame_layout_manager.h"
- #include "fuchsia_web/webengine/browser/frame_window_tree_host.h"
- #include "fuchsia_web/webengine/browser/media_player_impl.h"
- #include "fuchsia_web/webengine/browser/message_port.h"
- #include "fuchsia_web/webengine/browser/navigation_policy_handler.h"
- #include "fuchsia_web/webengine/browser/receiver_session_client.h"
- #include "fuchsia_web/webengine/browser/url_request_rewrite_type_converters.h"
- #include "fuchsia_web/webengine/browser/web_engine_devtools_controller.h"
- #include "fuchsia_web/webengine/common/cast_streaming.h"
- #include "mojo/public/cpp/bindings/associated_remote.h"
- #include "mojo/public/cpp/system/platform_handle.h"
- #include "net/base/net_errors.h"
- #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
- #include "third_party/blink/public/common/logging/logging_utils.h"
- #include "third_party/blink/public/common/messaging/web_message_port.h"
- #include "third_party/blink/public/common/page/page_zoom.h"
- #include "third_party/blink/public/common/permissions/permission_utils.h"
- #include "third_party/blink/public/common/web_preferences/web_preferences.h"
- #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
- #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
- #include "third_party/blink/public/mojom/navigation/was_activated_option.mojom.h"
- #include "ui/accessibility/platform/fuchsia/semantic_provider_impl.h"
- #include "ui/aura/window.h"
- #include "ui/compositor/compositor.h"
- #include "ui/gfx/switches.h"
- #include "ui/ozone/public/ozone_switches.h"
- #include "ui/wm/core/base_focus_rules.h"
- #include "url/gurl.h"
- #include "url/origin.h"
- namespace {
- // Simulated screen bounds to use when headless rendering is enabled.
- constexpr gfx::Size kHeadlessWindowSize = {1, 1};
- // Name of the Inspect node that holds accessibility information.
- constexpr char kAccessibilityInspectNodeName[] = "accessibility";
- // A special value which matches all origins when specified in an origin list.
- constexpr char kWildcardOrigin[] = "*";
- // Used for attaching popup-related metadata to a WebContents.
- constexpr char kPopupCreationInfo[] = "popup-creation-info";
- class PopupFrameCreationInfoUserData : public base::SupportsUserData::Data {
- public:
- fuchsia::web::PopupFrameCreationInfo info;
- };
- class FrameFocusRules : public wm::BaseFocusRules {
- public:
- FrameFocusRules() = default;
- FrameFocusRules(const FrameFocusRules&) = delete;
- FrameFocusRules& operator=(const FrameFocusRules&) = delete;
- ~FrameFocusRules() override = default;
- // wm::BaseFocusRules implementation.
- bool SupportsChildActivation(const aura::Window*) const override;
- };
- bool FrameFocusRules::SupportsChildActivation(const aura::Window*) const {
- // TODO(crbug.com/878439): Return a result based on window properties such as
- // visibility.
- return true;
- }
- // TODO(crbug.com/1113289): Use OnLoadScriptInjectorHost's origin matching code.
- bool IsUrlMatchedByOriginList(const GURL& url,
- const std::vector<std::string>& allowed_origins) {
- for (const std::string& origin : allowed_origins) {
- if (origin == kWildcardOrigin)
- return true;
- GURL origin_url(origin);
- if (!origin_url.is_valid()) {
- DLOG(WARNING)
- << "Ignored invalid origin spec when checking allowed list: "
- << origin;
- continue;
- }
- if (origin_url != url.DeprecatedGetOriginAsURL())
- continue;
- return true;
- }
- return false;
- }
- FuchsiaLogSeverity FuchsiaWebConsoleLogLevelToFxLogSeverity(
- fuchsia::web::ConsoleLogLevel level) {
- switch (level) {
- case fuchsia::web::ConsoleLogLevel::DEBUG:
- return FUCHSIA_LOG_DEBUG;
- case fuchsia::web::ConsoleLogLevel::INFO:
- return FUCHSIA_LOG_INFO;
- case fuchsia::web::ConsoleLogLevel::WARN:
- return FUCHSIA_LOG_WARNING;
- case fuchsia::web::ConsoleLogLevel::ERROR:
- return FUCHSIA_LOG_ERROR;
- case fuchsia::web::ConsoleLogLevel::NONE:
- return FUCHSIA_LOG_NONE;
- default:
- // Cope gracefully with callers setting undefined levels.
- DLOG(ERROR) << "Unknown log level:"
- << static_cast<std::underlying_type<decltype(level)>::type>(
- level);
- return FUCHSIA_LOG_NONE;
- }
- }
- FuchsiaLogSeverity BlinkConsoleMessageLevelToFxLogSeverity(
- blink::mojom::ConsoleMessageLevel level) {
- switch (level) {
- case blink::mojom::ConsoleMessageLevel::kVerbose:
- return FUCHSIA_LOG_DEBUG;
- case blink::mojom::ConsoleMessageLevel::kInfo:
- return FUCHSIA_LOG_INFO;
- case blink::mojom::ConsoleMessageLevel::kWarning:
- return FUCHSIA_LOG_WARNING;
- case blink::mojom::ConsoleMessageLevel::kError:
- return FUCHSIA_LOG_ERROR;
- }
- // Cope gracefully with callers setting undefined levels.
- DLOG(ERROR) << "Unknown log level:"
- << static_cast<std::underlying_type<decltype(level)>::type>(
- level);
- return FUCHSIA_LOG_NONE;
- }
- bool IsHeadless() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless);
- }
- using FrameImplMap =
- base::small_map<std::map<content::WebContents*, FrameImpl*>>;
- FrameImplMap& WebContentsToFrameImplMap() {
- static FrameImplMap frame_impl_map;
- return frame_impl_map;
- }
- blink::PermissionType FidlPermissionTypeToContentPermissionType(
- fuchsia::web::PermissionType fidl_type) {
- switch (fidl_type) {
- case fuchsia::web::PermissionType::MICROPHONE:
- return blink::PermissionType::AUDIO_CAPTURE;
- case fuchsia::web::PermissionType::CAMERA:
- return blink::PermissionType::VIDEO_CAPTURE;
- case fuchsia::web::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
- return blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER;
- case fuchsia::web::PermissionType::PERSISTENT_STORAGE:
- return blink::PermissionType::DURABLE_STORAGE;
- }
- }
- // Permission request callback for FrameImpl::RequestMediaAccessPermission.
- void HandleMediaPermissionsRequestResult(
- const content::MediaStreamRequest& request,
- content::MediaResponseCallback callback,
- const std::vector<blink::mojom::PermissionStatus>& result) {
- // TODO(crbug.com/1300883): Generalize to multiple streams.
- blink::mojom::StreamDevicesPtr devices = blink::mojom::StreamDevices::New();
- int result_pos = 0;
- if (request.audio_type ==
- blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
- if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) {
- devices->audio_device = blink::MediaStreamDevice(
- request.audio_type, request.requested_audio_device_id,
- /*name=*/"");
- }
- result_pos++;
- }
- if (request.video_type ==
- blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
- if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) {
- devices->video_device = blink::MediaStreamDevice(
- request.video_type, request.requested_video_device_id,
- /*name=*/"");
- }
- }
- blink::mojom::StreamDevicesSet stream_devices_set;
- if (devices->audio_device.has_value() || devices->video_device.has_value()) {
- stream_devices_set.stream_devices.emplace_back(std::move(devices));
- }
- std::move(callback).Run(
- stream_devices_set,
- stream_devices_set.stream_devices.empty()
- ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE
- : blink::mojom::MediaStreamRequestResult::OK,
- nullptr);
- }
- absl::optional<url::Origin> ParseAndValidateWebOrigin(
- const std::string& origin_str) {
- GURL origin_url(origin_str);
- if (!origin_url.username().empty() || !origin_url.password().empty() ||
- !origin_url.query().empty() || !origin_url.ref().empty()) {
- return absl::nullopt;
- }
- if (!origin_url.path().empty() && origin_url.path() != "/")
- return absl::nullopt;
- auto origin = url::Origin::Create(origin_url);
- if (origin.opaque())
- return absl::nullopt;
- return origin;
- }
- } // namespace
- FrameImpl::PendingPopup::PendingPopup(
- FrameImpl* frame_ptr,
- fidl::InterfaceHandle<fuchsia::web::Frame> handle,
- fuchsia::web::PopupFrameCreationInfo creation_info)
- : frame_ptr(std::move(frame_ptr)),
- handle(std::move(handle)),
- creation_info(std::move(creation_info)) {}
- FrameImpl::PendingPopup::PendingPopup(PendingPopup&& other) = default;
- FrameImpl::PendingPopup::~PendingPopup() = default;
- // static
- FrameImpl* FrameImpl::FromWebContents(content::WebContents* web_contents) {
- if (!web_contents)
- return nullptr;
- auto& map = WebContentsToFrameImplMap();
- auto it = map.find(web_contents);
- if (it == map.end())
- return nullptr;
- return it->second;
- }
- // static
- FrameImpl* FrameImpl::FromRenderFrameHost(
- content::RenderFrameHost* render_frame_host) {
- return FromWebContents(
- content::WebContents::FromRenderFrameHost(render_frame_host));
- }
- FrameImpl::FrameImpl(std::unique_ptr<content::WebContents> web_contents,
- ContextImpl* context,
- fuchsia::web::CreateFrameParams params,
- inspect::Node inspect_node,
- fidl::InterfaceRequest<fuchsia::web::Frame> frame_request)
- : web_contents_(std::move(web_contents)),
- context_(context),
- console_log_tag_(params.has_debug_name() ? params.debug_name()
- : std::string()),
- params_for_popups_(std::move(params)),
- navigation_controller_(web_contents_.get()),
- permission_controller_(web_contents_.get()),
- binding_(this, std::move(frame_request)),
- media_blocker_(web_contents_.get()),
- theme_manager_(web_contents_.get(),
- base::BindOnce(&FrameImpl::OnThemeManagerError,
- base::Unretained(this))),
- inspect_node_(std::move(inspect_node)),
- inspect_name_property_(
- params_for_popups_.has_debug_name()
- ? inspect_node_.CreateString("name",
- params_for_popups_.debug_name())
- : inspect::StringProperty()) {
- DCHECK(!WebContentsToFrameImplMap()[web_contents_.get()]);
- WebContentsToFrameImplMap()[web_contents_.get()] = this;
- web_contents_->SetDelegate(this);
- web_contents_->SetPageBaseBackgroundColor(SK_AlphaTRANSPARENT);
- Observe(web_contents_.get());
- url_request_rewrite_rules_manager_.AddWebContents(web_contents_.get());
- binding_.set_error_handler([this](zx_status_t status) {
- ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
- << " Frame disconnected.";
- context_->DestroyFrame(this);
- });
- content::UpdateFontRendererPreferencesFromSystemSettings(
- web_contents_->GetMutableRendererPrefs());
- // TODO(http://crbug.com/1254073): Deprecate autoplay_policy in
- // CreateFrameParams.
- if (params_for_popups_.has_autoplay_policy()) {
- content_area_settings_.set_autoplay_policy(
- params_for_popups_.autoplay_policy());
- }
- }
- FrameImpl::~FrameImpl() {
- DestroyWindowTreeHost();
- context_->devtools_controller()->OnFrameDestroyed(web_contents_.get());
- auto& map = WebContentsToFrameImplMap();
- auto it = WebContentsToFrameImplMap().find(web_contents_.get());
- DCHECK(it != map.end() && it->second == this);
- map.erase(it);
- }
- zx::unowned_channel FrameImpl::GetBindingChannelForTest() const {
- return zx::unowned_channel(binding_.channel());
- }
- aura::Window* FrameImpl::root_window() const {
- return window_tree_host_->window();
- }
- void FrameImpl::ExecuteJavaScriptInternal(std::vector<std::string> origins,
- fuchsia::mem::Buffer script,
- ExecuteJavaScriptCallback callback,
- bool need_result) {
- if (!context_->IsJavaScriptInjectionAllowed()) {
- callback(fpromise::error(fuchsia::web::FrameError::INTERNAL_ERROR));
- return;
- }
- // Prevents script injection into the wrong document if the renderer recently
- // navigated to a different origin.
- if (!IsUrlMatchedByOriginList(web_contents_->GetLastCommittedURL(),
- origins)) {
- callback(fpromise::error(fuchsia::web::FrameError::INVALID_ORIGIN));
- return;
- }
- absl::optional<std::u16string> script_utf16 =
- base::ReadUTF8FromVMOAsUTF16(script);
- if (!script_utf16) {
- callback(fpromise::error(fuchsia::web::FrameError::BUFFER_NOT_UTF8));
- return;
- }
- content::RenderFrameHost::JavaScriptResultCallback result_callback;
- if (need_result) {
- result_callback = base::BindOnce(
- [](ExecuteJavaScriptCallback callback, base::Value result_value) {
- std::string result_json;
- if (!base::JSONWriter::Write(result_value, &result_json)) {
- callback(fpromise::error(fuchsia::web::FrameError::INTERNAL_ERROR));
- return;
- }
- callback(fpromise::ok(base::MemBufferFromString(
- std::move(result_json), "cr-execute-js-response")));
- },
- std::move(callback));
- }
- web_contents_->GetPrimaryMainFrame()->ExecuteJavaScript(
- *script_utf16, std::move(result_callback));
- if (!need_result) {
- // If no result is required then invoke callback() immediately.
- callback(fpromise::ok(fuchsia::mem::Buffer()));
- }
- }
- bool FrameImpl::IsWebContentsCreationOverridden(
- content::SiteInstance* source_site_instance,
- content::mojom::WindowContainerType window_container_type,
- const GURL& opener_url,
- const std::string& frame_name,
- const GURL& target_url) {
- // Specify a generous upper bound for unacknowledged popup windows, so that we
- // can catch bad client behavior while not interfering with normal operation.
- constexpr size_t kMaxPendingWebContentsCount = 10;
- if (!popup_listener_)
- return true;
- if (pending_popups_.size() >= kMaxPendingWebContentsCount) {
- // The content is producing popups faster than the embedder can process
- // them. Drop the popups so as to prevent resource exhaustion.
- LOG(WARNING) << "Too many pending popups, ignoring request.";
- // Don't produce a WebContents for this popup.
- return true;
- }
- return false;
- }
- void FrameImpl::AddNewContents(
- content::WebContents* source,
- std::unique_ptr<content::WebContents> new_contents,
- const GURL& target_url,
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_rect,
- bool user_gesture,
- bool* was_blocked) {
- DCHECK_EQ(source, web_contents_.get());
- // TODO(crbug.com/995395): Add window disposition to the FIDL interface.
- switch (disposition) {
- case WindowOpenDisposition::NEW_FOREGROUND_TAB:
- case WindowOpenDisposition::NEW_BACKGROUND_TAB:
- case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE:
- case WindowOpenDisposition::NEW_POPUP:
- case WindowOpenDisposition::NEW_WINDOW: {
- if (url_request_rewrite_rules_manager_.GetCachedRules()) {
- // There is no support for URL request rules rewriting with popups.
- *was_blocked = true;
- return;
- }
- auto* popup_creation_info =
- reinterpret_cast<PopupFrameCreationInfoUserData*>(
- new_contents->GetUserData(kPopupCreationInfo));
- fuchsia::web::PopupFrameCreationInfo popup_frame_creation_info =
- std::move(popup_creation_info->info);
- popup_frame_creation_info.set_initiated_by_user(user_gesture);
- // The PopupFrameCreationInfo won't be needed anymore, so clear it out.
- new_contents->SetUserData(kPopupCreationInfo, nullptr);
- // ContextImpl::CreateFrameInternal() verified that |params_for_popups_|
- // can be cloned, so it cannot fail here.
- fuchsia::web::CreateFrameParams params;
- zx_status_t status = params_for_popups_.Clone(¶ms);
- ZX_DCHECK(status == ZX_OK, status);
- fidl::InterfaceHandle<fuchsia::web::Frame> frame_handle;
- auto* popup_frame = context_->CreateFrameForWebContents(
- std::move(new_contents), std::move(params),
- frame_handle.NewRequest());
- fuchsia::web::ContentAreaSettings settings;
- status = content_area_settings_.Clone(&settings);
- ZX_DCHECK(status == ZX_OK, status);
- popup_frame->SetContentAreaSettings(std::move(settings));
- pending_popups_.emplace_back(popup_frame, std::move(frame_handle),
- std::move(popup_frame_creation_info));
- MaybeSendPopup();
- return;
- }
- // These kinds of windows don't produce Frames.
- case WindowOpenDisposition::CURRENT_TAB:
- case WindowOpenDisposition::SINGLETON_TAB:
- case WindowOpenDisposition::SAVE_TO_DISK:
- case WindowOpenDisposition::OFF_THE_RECORD:
- case WindowOpenDisposition::IGNORE_ACTION:
- case WindowOpenDisposition::SWITCH_TO_TAB:
- case WindowOpenDisposition::UNKNOWN:
- NOTIMPLEMENTED() << "Dropped new web contents (disposition: "
- << static_cast<int>(disposition) << ")";
- return;
- }
- }
- void FrameImpl::WebContentsCreated(content::WebContents* source_contents,
- int opener_render_process_id,
- int opener_render_frame_id,
- const std::string& frame_name,
- const GURL& target_url,
- content::WebContents* new_contents) {
- auto creation_info = std::make_unique<PopupFrameCreationInfoUserData>();
- creation_info->info.set_initial_url(target_url.spec());
- new_contents->SetUserData(kPopupCreationInfo, std::move(creation_info));
- }
- void FrameImpl::MaybeSendPopup() {
- if (!popup_listener_)
- return;
- if (popup_ack_outstanding_ || pending_popups_.empty())
- return;
- auto popup = std::move(pending_popups_.front());
- pending_popups_.pop_front();
- popup_listener_->OnPopupFrameCreated(std::move(popup.handle),
- std::move(popup.creation_info), [this] {
- popup_ack_outstanding_ = false;
- MaybeSendPopup();
- });
- popup_ack_outstanding_ = true;
- }
- void FrameImpl::DestroyWindowTreeHost() {
- if (!window_tree_host_)
- return;
- aura::client::SetFocusClient(root_window(), nullptr);
- wm::SetActivationClient(root_window(), nullptr);
- root_window()->RemovePreTargetHandler(&event_filter_);
- root_window()->RemovePreTargetHandler(focus_controller_.get());
- web_contents_->GetNativeView()->Hide();
- window_tree_host_->Hide();
- window_tree_host_->compositor()->SetVisible(false);
- window_tree_host_.reset();
- accessibility_bridge_.reset();
- v2_accessibility_bridge_.reset();
- // Allows posted focus events to process before the FocusController is torn
- // down.
- content::GetUIThreadTaskRunner({})->DeleteSoon(FROM_HERE,
- std::move(focus_controller_));
- }
- void FrameImpl::CloseAndDestroyFrame(zx_status_t error) {
- DCHECK(binding_.is_bound());
- binding_.Close(error);
- context_->DestroyFrame(this);
- }
- void FrameImpl::OnPopupListenerDisconnected(zx_status_t status) {
- ZX_LOG_IF(WARNING, status != ZX_ERR_PEER_CLOSED, status)
- << "Popup listener disconnected.";
- pending_popups_.clear();
- }
- void FrameImpl::OnMediaPlayerDisconnect() {
- media_player_ = nullptr;
- }
- bool FrameImpl::OnAccessibilityError(zx_status_t error) {
- // The task is posted so |accessibility_bridge_| does not tear |this| down
- // while events are still being processed.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&FrameImpl::CloseAndDestroyFrame,
- weak_factory_.GetWeakPtr(), error));
- // The return value indicates to the accessibility bridge whether we should
- // attempt to reconnect. Since the frame has been destroyed, no reconnect
- // attempt should be made.
- return false;
- }
- bool FrameImpl::MaybeHandleCastStreamingMessage(
- std::string* origin,
- fuchsia::web::WebMessage* message,
- PostMessageCallback* callback) {
- if (!context_->has_cast_streaming_enabled()) {
- return false;
- }
- if (!IsCastStreamingAppOrigin(*origin)) {
- return false;
- }
- if (receiver_session_client_ || !IsValidCastStreamingMessage(*message)) {
- // The Cast Streaming MessagePort should only be set once and |message|
- // should be a valid Cast Streaming Message.
- (*callback)(fpromise::error(fuchsia::web::FrameError::INVALID_ORIGIN));
- return true;
- }
- receiver_session_client_ = std::make_unique<ReceiverSessionClient>(
- std::move((*message->mutable_outgoing_transfer())[0].message_port()),
- IsCastStreamingVideoOnlyAppOrigin(*origin));
- (*callback)(fpromise::ok());
- return true;
- }
- void FrameImpl::MaybeStartCastStreaming(
- content::NavigationHandle* navigation_handle) {
- if (!context_->has_cast_streaming_enabled() || !receiver_session_client_ ||
- receiver_session_client_->HasReceiverSession()) {
- return;
- }
- mojo::AssociatedRemote<cast_streaming::mojom::DemuxerConnector>
- demuxer_connector;
- navigation_handle->GetRenderFrameHost()
- ->GetRemoteAssociatedInterfaces()
- ->GetInterface(&demuxer_connector);
- receiver_session_client_->SetDemuxerConnector(std::move(demuxer_connector));
- }
- void FrameImpl::UpdateRenderViewZoomLevel(
- content::RenderViewHost* render_view_host) {
- float page_scale = content_area_settings_.has_page_scale()
- ? content_area_settings_.page_scale()
- : 1.0;
- content::HostZoomMap* host_zoom_map =
- content::HostZoomMap::GetForWebContents(web_contents_.get());
- host_zoom_map->SetTemporaryZoomLevel(
- render_view_host->GetProcess()->GetID(), render_view_host->GetRoutingID(),
- blink::PageZoomFactorToZoomLevel(page_scale));
- }
- void FrameImpl::ConnectToAccessibilityBridge() {
- if (use_v2_accessibility_bridge_) {
- // TODO(crbug.com/1291613): Replace callbacks with an interface that
- // FrameImpl implements.
- v2_accessibility_bridge_ =
- std::make_unique<ui::AccessibilityBridgeFuchsiaImpl>(
- root_window(), window_tree_host_->CreateViewRef(),
- base::BindRepeating(&FrameImpl::SetAccessibilityEnabled,
- base::Unretained(this)),
- base::BindRepeating(&FrameImpl::OnAccessibilityError,
- base::Unretained(this)),
- inspect_node_.CreateChild(kAccessibilityInspectNodeName));
- } else {
- fuchsia::accessibility::semantics::SemanticsManagerPtr semantics_manager;
- if (!semantics_manager_for_test_) {
- semantics_manager =
- base::ComponentContextForProcess()
- ->svc()
- ->Connect<fuchsia::accessibility::semantics::SemanticsManager>();
- }
- // If the SemanticTree owned by |accessibility_bridge_| is disconnected, it
- // will cause |this| to be closed.
- accessibility_bridge_ = std::make_unique<AccessibilityBridge>(
- semantics_manager_for_test_ ? semantics_manager_for_test_
- : semantics_manager.get(),
- window_tree_host_.get(), web_contents_.get(),
- base::BindOnce(&FrameImpl::OnAccessibilityError,
- base::Unretained(this)),
- inspect_node_.CreateChild(kAccessibilityInspectNodeName));
- }
- }
- void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) {
- scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
- CreateViewWithViewRef(std::move(view_token),
- std::move(view_ref_pair.control_ref),
- std::move(view_ref_pair.view_ref));
- }
- void FrameImpl::CreateViewWithViewRef(
- fuchsia::ui::views::ViewToken view_token,
- fuchsia::ui::views::ViewRefControl control_ref,
- fuchsia::ui::views::ViewRef view_ref) {
- if (IsHeadless()) {
- LOG(WARNING) << "CreateView() called on a HEADLESS Context.";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- if (!view_token.value.is_valid()) {
- LOG(WARNING) << "CreateView() called with invalid view_token.";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- // If a View to this Frame is already active then disconnect it.
- DestroyWindowTreeHost();
- scenic::ViewRefPair view_ref_pair;
- view_ref_pair.control_ref = std::move(control_ref);
- view_ref_pair.view_ref = std::move(view_ref);
- SetupWindowTreeHost(std::move(view_token), std::move(view_ref_pair));
- ConnectToAccessibilityBridge();
- }
- void FrameImpl::CreateView2(fuchsia::web::CreateView2Args view_args) {
- if (IsHeadless()) {
- LOG(WARNING) << "CreateView2() called on a HEADLESS Context.";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- if (!view_args.has_view_creation_token() ||
- !view_args.view_creation_token().value.is_valid()) {
- LOG(WARNING) << "CreateView2() called with invalid view_creation_token.";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- // If a View to this Frame is already active then disconnect it.
- DestroyWindowTreeHost();
- scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
- SetupWindowTreeHost(std::move(*view_args.mutable_view_creation_token()),
- std::move(view_ref_pair));
- ConnectToAccessibilityBridge();
- }
- void FrameImpl::GetMediaPlayer(
- fidl::InterfaceRequest<fuchsia::media::sessions2::Player> player) {
- media_player_ = std::make_unique<MediaPlayerImpl>(
- content::MediaSession::Get(web_contents_.get()), std::move(player),
- base::BindOnce(&FrameImpl::OnMediaPlayerDisconnect,
- base::Unretained(this)));
- }
- void FrameImpl::GetNavigationController(
- fidl::InterfaceRequest<fuchsia::web::NavigationController> controller) {
- navigation_controller_.AddBinding(std::move(controller));
- }
- void FrameImpl::ExecuteJavaScript(std::vector<std::string> origins,
- fuchsia::mem::Buffer script,
- ExecuteJavaScriptCallback callback) {
- ExecuteJavaScriptInternal(std::move(origins), std::move(script),
- std::move(callback), true);
- }
- void FrameImpl::ExecuteJavaScriptNoResult(
- std::vector<std::string> origins,
- fuchsia::mem::Buffer script,
- ExecuteJavaScriptNoResultCallback callback) {
- ExecuteJavaScriptInternal(
- std::move(origins), std::move(script),
- [callback = std::move(callback)](
- fuchsia::web::Frame_ExecuteJavaScript_Result result_with_value) {
- if (result_with_value.is_err()) {
- callback(fpromise::error(result_with_value.err()));
- } else {
- callback(fpromise::ok());
- }
- },
- false);
- }
- void FrameImpl::AddBeforeLoadJavaScript(
- uint64_t id,
- std::vector<std::string> origins,
- fuchsia::mem::Buffer script,
- AddBeforeLoadJavaScriptCallback callback) {
- constexpr char kWildcardOrigin[] = "*";
- if (!context_->IsJavaScriptInjectionAllowed()) {
- callback(fpromise::error(fuchsia::web::FrameError::INTERNAL_ERROR));
- return;
- }
- absl::optional<std::string> script_as_string =
- base::StringFromMemBuffer(script);
- if (!script_as_string) {
- LOG(ERROR) << "Couldn't read script from buffer.";
- callback(fpromise::error(fuchsia::web::FrameError::INTERNAL_ERROR));
- return;
- }
- // TODO(crbug.com/1108607): Only allow wildcards to be specified standalone.
- if (std::any_of(origins.begin(), origins.end(),
- [kWildcardOrigin](base::StringPiece origin) {
- return origin == kWildcardOrigin;
- })) {
- script_injector_.AddScriptForAllOrigins(id, *script_as_string);
- } else {
- std::vector<url::Origin> origins_converted;
- for (const std::string& origin : origins) {
- url::Origin origin_parsed = url::Origin::Create(GURL(origin));
- if (origin_parsed.opaque()) {
- callback(fpromise::error(fuchsia::web::FrameError::INVALID_ORIGIN));
- return;
- }
- origins_converted.push_back(origin_parsed);
- }
- script_injector_.AddScript(id, origins_converted, *script_as_string);
- }
- callback(fpromise::ok());
- }
- void FrameImpl::RemoveBeforeLoadJavaScript(uint64_t id) {
- script_injector_.RemoveScript(id);
- }
- void FrameImpl::PostMessage(std::string origin,
- fuchsia::web::WebMessage message,
- PostMessageCallback callback) {
- if (MaybeHandleCastStreamingMessage(&origin, &message, &callback))
- return;
- fuchsia::web::Frame_PostMessage_Result result;
- if (origin.empty()) {
- callback(fpromise::error(fuchsia::web::FrameError::INVALID_ORIGIN));
- return;
- }
- if (!message.has_data()) {
- callback(fpromise::error(fuchsia::web::FrameError::NO_DATA_IN_MESSAGE));
- return;
- }
- absl::optional<std::u16string> origin_utf16;
- if (origin != kWildcardOrigin)
- origin_utf16 = base::UTF8ToUTF16(origin);
- absl::optional<std::u16string> data_utf16 =
- base::ReadUTF8FromVMOAsUTF16(message.data());
- if (!data_utf16) {
- callback(fpromise::error(fuchsia::web::FrameError::BUFFER_NOT_UTF8));
- return;
- }
- // Convert and pass along any MessagePorts contained in the message.
- std::vector<blink::WebMessagePort> message_ports;
- if (message.has_outgoing_transfer()) {
- for (const fuchsia::web::OutgoingTransferable& outgoing :
- message.outgoing_transfer()) {
- if (!outgoing.is_message_port()) {
- callback(fpromise::error(fuchsia::web::FrameError::INTERNAL_ERROR));
- return;
- }
- }
- for (fuchsia::web::OutgoingTransferable& outgoing :
- *message.mutable_outgoing_transfer()) {
- blink::WebMessagePort blink_port =
- BlinkMessagePortFromFidl(std::move(outgoing.message_port()));
- if (!blink_port.IsValid()) {
- callback(fpromise::error(fuchsia::web::FrameError::INTERNAL_ERROR));
- return;
- }
- message_ports.push_back(std::move(blink_port));
- }
- }
- content::MessagePortProvider::PostMessageToFrame(
- web_contents_->GetPrimaryPage(), std::u16string(), origin_utf16,
- std::move(*data_utf16), std::move(message_ports));
- callback(fpromise::ok());
- }
- void FrameImpl::SetNavigationEventListener(
- fidl::InterfaceHandle<fuchsia::web::NavigationEventListener> listener) {
- SetNavigationEventListener2(std::move(listener), /*flags=*/{});
- }
- void FrameImpl::SetNavigationEventListener2(
- fidl::InterfaceHandle<fuchsia::web::NavigationEventListener> listener,
- fuchsia::web::NavigationEventListenerFlags flags) {
- navigation_controller_.SetEventListener(std::move(listener), flags);
- }
- void FrameImpl::SetJavaScriptLogLevel(fuchsia::web::ConsoleLogLevel level) {
- log_level_ = FuchsiaWebConsoleLogLevelToFxLogSeverity(level);
- }
- void FrameImpl::SetConsoleLogSink(fuchsia::logger::LogSinkHandle sink) {
- if (sink) {
- console_logger_ = base::ScopedFxLogger::CreateFromLogSink(
- std::move(sink), {console_log_tag_});
- } else {
- console_logger_ = {};
- }
- }
- void FrameImpl::ConfigureInputTypes(fuchsia::web::InputTypes types,
- fuchsia::web::AllowInputState allow) {
- event_filter_.ConfigureInputTypes(types, allow);
- }
- void FrameImpl::SetPopupFrameCreationListener(
- fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener) {
- popup_listener_ = listener.Bind();
- popup_listener_.set_error_handler(
- fit::bind_member(this, &FrameImpl::OnPopupListenerDisconnected));
- }
- void FrameImpl::SetUrlRequestRewriteRules(
- std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
- SetUrlRequestRewriteRulesCallback callback) {
- auto mojom_rules =
- mojo::ConvertTo<url_rewrite::mojom::UrlRequestRewriteRulesPtr>(
- std::move(rules));
- if (url_request_rewrite_rules_manager_.OnRulesUpdated(
- std::move(mojom_rules))) {
- std::move(callback)();
- } else {
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- }
- }
- void FrameImpl::EnableHeadlessRendering() {
- if (!IsHeadless()) {
- LOG(ERROR) << "EnableHeadlessRendering() on non-HEADLESS Context.";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
- SetupWindowTreeHost(fuchsia::ui::views::ViewToken(),
- std::move(view_ref_pair));
- gfx::Rect bounds(kHeadlessWindowSize);
- if (window_size_for_test_) {
- ConnectToAccessibilityBridge();
- bounds.set_size(*window_size_for_test_);
- }
- window_tree_host_->SetBoundsInPixels(bounds);
- // FrameWindowTreeHost will Show() itself when the View is attached, but
- // in headless mode there is no View, so Show() it explicitly.
- window_tree_host_->Show();
- }
- void FrameImpl::DisableHeadlessRendering() {
- if (!IsHeadless()) {
- LOG(ERROR)
- << "Attempted to disable headless rendering on non-HEADLESS Context.";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- DestroyWindowTreeHost();
- }
- void FrameImpl::SetupWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
- scenic::ViewRefPair view_ref_pair) {
- DCHECK(!window_tree_host_);
- window_tree_host_ = std::make_unique<FrameWindowTreeHost>(
- std::move(view_token), std::move(view_ref_pair), web_contents_.get(),
- base::BindRepeating(&FrameImpl::OnPixelScaleUpdate,
- base::Unretained(this)));
- InitWindowTreeHost();
- }
- void FrameImpl::SetupWindowTreeHost(
- fuchsia::ui::views::ViewCreationToken view_creation_token,
- scenic::ViewRefPair view_ref_pair) {
- DCHECK(!window_tree_host_);
- window_tree_host_ = std::make_unique<FrameWindowTreeHost>(
- std::move(view_creation_token), std::move(view_ref_pair),
- web_contents_.get(),
- base::BindRepeating(&FrameImpl::OnPixelScaleUpdate,
- base::Unretained(this)));
- InitWindowTreeHost();
- }
- void FrameImpl::InitWindowTreeHost() {
- DCHECK(window_tree_host_);
- window_tree_host_->InitHost();
- root_window()->AddPreTargetHandler(&event_filter_);
- // Add hooks which automatically set the focus state when input events are
- // received.
- focus_controller_ =
- std::make_unique<wm::FocusController>(new FrameFocusRules);
- root_window()->AddPreTargetHandler(focus_controller_.get());
- aura::client::SetFocusClient(root_window(), focus_controller_.get());
- wm::SetActivationClient(root_window(), focus_controller_.get());
- layout_manager_ = new FrameLayoutManager;
- root_window()->SetLayoutManager(layout_manager_); // Transfers ownership.
- if (!render_size_override_.IsEmpty())
- layout_manager_->ForceContentDimensions(render_size_override_);
- root_window()->AddChild(web_contents_->GetNativeView());
- web_contents_->GetNativeView()->Show();
- // FrameWindowTreeHost will Show() itself when the View is actually attached
- // to the view-tree to be displayed. See https://crbug.com/1109270
- }
- void FrameImpl::SetMediaSettings(
- fuchsia::web::FrameMediaSettings media_settings) {
- media_settings_ = std::move(media_settings);
- }
- void FrameImpl::MediaStartedPlaying(const MediaPlayerInfo& video_type,
- const content::MediaPlayerId& id) {
- base::RecordComputedAction("MediaPlay");
- }
- void FrameImpl::MediaStoppedPlaying(
- const MediaPlayerInfo& video_type,
- const content::MediaPlayerId& id,
- WebContentsObserver::MediaStoppedReason reason) {
- base::RecordComputedAction("MediaPause");
- }
- void FrameImpl::GetPrivateMemorySize(GetPrivateMemorySizeCallback callback) {
- if (!web_contents_->GetPrimaryMainFrame()->GetProcess()->IsReady()) {
- // Renderer process is not yet started.
- callback(0);
- return;
- }
- zx_info_task_stats_t task_stats;
- zx_status_t status = zx_object_get_info(
- web_contents_->GetPrimaryMainFrame()->GetProcess()->GetProcess().Handle(),
- ZX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), nullptr, nullptr);
- if (status != ZX_OK) {
- // Fail gracefully by returning zero.
- ZX_LOG(WARNING, status) << "zx_object_get_info(ZX_INFO_TASK_STATS)";
- callback(0);
- return;
- }
- callback(task_stats.mem_private_bytes);
- }
- void FrameImpl::SetNavigationPolicyProvider(
- fuchsia::web::NavigationPolicyProviderParams params,
- fidl::InterfaceHandle<fuchsia::web::NavigationPolicyProvider> provider) {
- navigation_policy_handler_ = std::make_unique<NavigationPolicyHandler>(
- std::move(params), std::move(provider));
- }
- void FrameImpl::OnThemeManagerError() {
- // TODO(crbug.com/1148454): Destroy the frame once a fake Display service is
- // implemented.
- // this->CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- }
- void FrameImpl::SetPreferredTheme(fuchsia::settings::ThemeType theme) {
- fuchsia::web::ContentAreaSettings settings;
- settings.set_theme(theme);
- SetContentAreaSettings(std::move(settings));
- }
- void FrameImpl::SetPageScale(float scale) {
- fuchsia::web::ContentAreaSettings settings;
- settings.set_page_scale(scale);
- SetContentAreaSettings(std::move(settings));
- }
- void FrameImpl::SetContentAreaSettings(
- fuchsia::web::ContentAreaSettings settings) {
- if (settings.has_hide_scrollbars())
- content_area_settings_.set_hide_scrollbars(settings.hide_scrollbars());
- if (settings.has_autoplay_policy())
- content_area_settings_.set_autoplay_policy(settings.autoplay_policy());
- if (settings.has_theme()) {
- content_area_settings_.set_theme(settings.theme());
- theme_manager_.SetTheme(settings.theme());
- }
- if (settings.has_page_scale()) {
- if (settings.page_scale() <= 0.0) {
- LOG(ERROR) << "SetPageScale() called with nonpositive scale.";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- if (!(content_area_settings_.has_page_scale() &&
- (settings.page_scale() == content_area_settings_.page_scale()))) {
- content_area_settings_.set_page_scale(settings.page_scale());
- UpdateRenderViewZoomLevel(web_contents_->GetRenderViewHost());
- }
- }
- web_contents_->OnWebPreferencesChanged();
- }
- void FrameImpl::ResetContentAreaSettings() {
- content_area_settings_ = fuchsia::web::ContentAreaSettings();
- web_contents_->OnWebPreferencesChanged();
- UpdateRenderViewZoomLevel(web_contents_->GetRenderViewHost());
- }
- void FrameImpl::OverrideWebPreferences(
- blink::web_pref::WebPreferences* web_prefs) {
- if (content_area_settings_.has_hide_scrollbars()) {
- web_prefs->hide_scrollbars = content_area_settings_.hide_scrollbars();
- } else {
- // Verify that hide_scrollbars defaults to false, per FIDL API.
- DCHECK(!web_prefs->hide_scrollbars);
- }
- if (content_area_settings_.has_autoplay_policy()) {
- switch (content_area_settings_.autoplay_policy()) {
- case fuchsia::web::AutoplayPolicy::ALLOW:
- web_prefs->autoplay_policy =
- blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
- break;
- case fuchsia::web::AutoplayPolicy::REQUIRE_USER_ACTIVATION:
- web_prefs->autoplay_policy =
- blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired;
- break;
- }
- } else {
- // REQUIRE_USER_ACTIVATION is the default per the FIDL API.
- web_prefs->autoplay_policy =
- blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired;
- }
- theme_manager_.ApplyThemeToWebPreferences(web_prefs);
- }
- void FrameImpl::ForceContentDimensions(
- std::unique_ptr<fuchsia::ui::gfx::vec2> web_dips) {
- if (!web_dips) {
- render_size_override_ = {};
- if (layout_manager_)
- layout_manager_->ForceContentDimensions({});
- return;
- }
- gfx::Size web_dips_converted(web_dips->x, web_dips->y);
- if (web_dips_converted.IsEmpty()) {
- LOG(ERROR) << "Rejecting zero-area size for ForceContentDimensions().";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- render_size_override_ = web_dips_converted;
- if (layout_manager_)
- layout_manager_->ForceContentDimensions(web_dips_converted);
- }
- void FrameImpl::SetPermissionState(
- fuchsia::web::PermissionDescriptor fidl_permission,
- std::string web_origin_string,
- fuchsia::web::PermissionState fidl_state) {
- if (!fidl_permission.has_type()) {
- LOG(ERROR) << "PermissionDescriptor.type is not specified in "
- "SetPermissionState().";
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- blink::PermissionType type =
- FidlPermissionTypeToContentPermissionType(fidl_permission.type());
- blink::mojom::PermissionStatus state =
- (fidl_state == fuchsia::web::PermissionState::GRANTED)
- ? blink::mojom::PermissionStatus::GRANTED
- : blink::mojom::PermissionStatus::DENIED;
- // TODO(crbug.com/1136994): Remove this once the PermissionManager API is
- // available.
- if (web_origin_string == "*" &&
- type == blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
- permission_controller_.SetDefaultPermissionState(type, state);
- return;
- }
- // Handle per-origin permissions specifications.
- auto web_origin = ParseAndValidateWebOrigin(web_origin_string);
- if (!web_origin) {
- LOG(ERROR) << "SetPermissionState() called with invalid web_origin: "
- << web_origin_string;
- CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
- return;
- }
- permission_controller_.SetPermissionState(type, web_origin.value(), state);
- }
- void FrameImpl::CloseContents(content::WebContents* source) {
- DCHECK_EQ(source, web_contents_.get());
- CloseAndDestroyFrame(ZX_OK);
- }
- void FrameImpl::SetBlockMediaLoading(bool blocked) {
- media_blocker_.BlockMediaLoading(blocked);
- }
- bool FrameImpl::DidAddMessageToConsole(
- content::WebContents* source,
- blink::mojom::ConsoleMessageLevel log_level,
- const std::u16string& message,
- int32_t line_no,
- const std::u16string& source_id) {
- // Prevent logging when log_level_ is 0. See crbug.com/1292187.
- // TODO(crbug.com/1292208): Convert to DCHECK when FUCHSIA_LOG_NONE
- // is defined to be greater than other log levels.
- if (log_level_ == 0) {
- // Prevent the default logging mechanism from logging the message.
- return true;
- }
- FuchsiaLogSeverity severity =
- BlinkConsoleMessageLevelToFxLogSeverity(log_level);
- if (severity < log_level_) {
- // Prevent the default logging mechanism from logging the message.
- return true;
- }
- if (!console_logger_.is_valid()) {
- // Log via the process' LogSink service if none was set on the Frame.
- // Connect on-demand, so that embedders need not provide a LogSink in the
- // CreateContextParams services, unless they actually enable logging.
- console_logger_ = base::ScopedFxLogger::CreateFromLogSink(
- base::ComponentContextForProcess()
- ->svc()
- ->Connect<fuchsia::logger::LogSink>(),
- {console_log_tag_});
- if (!console_logger_.is_valid())
- return false;
- }
- std::string source_id_utf8 = base::UTF16ToUTF8(source_id);
- std::string message_utf8 = base::UTF16ToUTF8(message);
- console_logger_.LogMessage(source_id_utf8, line_no, message_utf8, severity);
- return true;
- }
- void FrameImpl::RequestMediaAccessPermission(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- content::MediaResponseCallback callback) {
- DCHECK_EQ(web_contents_.get(), web_contents);
- std::vector<blink::PermissionType> permissions;
- if (request.audio_type ==
- blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
- permissions.push_back(blink::PermissionType::AUDIO_CAPTURE);
- } else if (request.audio_type != blink::mojom::MediaStreamType::NO_SERVICE) {
- std::move(callback).Run(
- blink::mojom::StreamDevicesSet(),
- blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
- return;
- }
- if (request.video_type ==
- blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
- permissions.push_back(blink::PermissionType::VIDEO_CAPTURE);
- } else if (request.video_type != blink::mojom::MediaStreamType::NO_SERVICE) {
- std::move(callback).Run(
- blink::mojom::StreamDevicesSet(),
- blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
- return;
- }
- auto* render_frame_host = content::RenderFrameHost::FromID(
- request.render_process_id, request.render_frame_id);
- if (!render_frame_host) {
- std::move(callback).Run(
- blink::mojom::StreamDevicesSet(),
- blink::mojom::MediaStreamRequestResult::INVALID_STATE, nullptr);
- return;
- }
- if (url::Origin::Create(request.security_origin) !=
- render_frame_host->GetLastCommittedOrigin()) {
- std::move(callback).Run(
- blink::mojom::StreamDevicesSet(),
- blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN,
- nullptr);
- return;
- }
- content::PermissionController* permission_controller =
- web_contents_->GetBrowserContext()->GetPermissionController();
- DCHECK(permission_controller);
- permission_controller->RequestPermissionsFromCurrentDocument(
- permissions, render_frame_host, request.user_gesture,
- base::BindOnce(&HandleMediaPermissionsRequestResult, request,
- std::move(callback)));
- }
- bool FrameImpl::CheckMediaAccessPermission(
- content::RenderFrameHost* render_frame_host,
- const GURL& security_origin,
- blink::mojom::MediaStreamType type) {
- blink::PermissionType permission;
- switch (type) {
- case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE:
- permission = blink::PermissionType::AUDIO_CAPTURE;
- break;
- case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE:
- permission = blink::PermissionType::VIDEO_CAPTURE;
- break;
- default:
- NOTREACHED();
- return false;
- }
- // TODO(crbug.com/1321100): Remove `security_origin`.
- if (url::Origin::Create(security_origin) !=
- render_frame_host->GetLastCommittedOrigin()) {
- return false;
- }
- content::PermissionController* permission_controller =
- web_contents_->GetBrowserContext()->GetPermissionController();
- DCHECK(permission_controller);
- return permission_controller->GetPermissionStatusForCurrentDocument(
- permission, render_frame_host) ==
- blink::mojom::PermissionStatus::GRANTED;
- }
- bool FrameImpl::CanOverscrollContent() {
- // Don't process "overscroll" events (e.g. pull-to-refresh, swipe back,
- // swipe forward).
- // TODO(crbug/1177399): Add overscroll toggle to Frame API.
- return false;
- }
- void FrameImpl::ReadyToCommitNavigation(
- content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInPrimaryMainFrame() ||
- navigation_handle->IsSameDocument() || navigation_handle->IsErrorPage()) {
- return;
- }
- script_injector_.InjectScriptsForURL(navigation_handle->GetURL(),
- navigation_handle->GetRenderFrameHost());
- MaybeStartCastStreaming(navigation_handle);
- }
- void FrameImpl::DidFinishLoad(content::RenderFrameHost* render_frame_host,
- const GURL& validated_url) {
- context_->devtools_controller()->OnFrameLoaded(web_contents_.get());
- }
- void FrameImpl::RenderFrameCreated(content::RenderFrameHost* frame_host) {
- // The top-level frame is given a transparent background color.
- // GetView() is guaranteed to be non-null until |frame_host| teardown.
- if (!frame_host->GetParentOrOuterDocument()) {
- frame_host->GetView()->SetBackgroundColor(SK_AlphaTRANSPARENT);
- }
- }
- void FrameImpl::RenderViewHostChanged(content::RenderViewHost* old_host,
- content::RenderViewHost* new_host) {
- // UpdateRenderViewZoomLevel() sets temporary zoom level for the current
- // RenderView. It needs to be called again whenever main RenderView is
- // changed.
- UpdateRenderViewZoomLevel(new_host);
- }
- void FrameImpl::DidFirstVisuallyNonEmptyPaint() {
- base::RecordComputedAction("AppFirstPaint");
- }
- void FrameImpl::ResourceLoadComplete(
- content::RenderFrameHost* render_frame_host,
- const content::GlobalRequestID& request_id,
- const blink::mojom::ResourceLoadInfo& resource_load_info) {
- int net_error = resource_load_info.net_error;
- if (net_error != net::OK) {
- base::RecordComputedAction(
- base::StringPrintf("WebEngine.ResourceRequestError:%d", net_error));
- }
- }
- // TODO(crbug.com/1136681#c6): Move below GetBindingChannelForTest when fixed.
- void FrameImpl::EnableExplicitSitesFilter(std::string error_page) {
- explicit_sites_filter_error_page_ = std::move(error_page);
- }
- void FrameImpl::SetAccessibilityEnabled(bool enabled) {
- auto* browser_accessibility_state =
- content::BrowserAccessibilityState::GetInstance();
- if (enabled) {
- browser_accessibility_state->AddAccessibilityModeFlags(ui::kAXModeComplete);
- } else {
- browser_accessibility_state->RemoveAccessibilityModeFlags(
- ui::kAXModeComplete);
- }
- }
- void FrameImpl::OnPixelScaleUpdate(float pixel_scale) {
- if (v2_accessibility_bridge_) {
- v2_accessibility_bridge_->SetPixelScale(pixel_scale);
- }
- }
|