123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- // Copyright (c) 2012 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 "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
- #include "android_webview/browser/aw_browser_context.h"
- #include "android_webview/browser/aw_contents.h"
- #include "android_webview/browser/aw_contents_client_bridge.h"
- #include "android_webview/common/aw_features.h"
- #include "base/android/scoped_java_ref.h"
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/command_line.h"
- #include "base/logging.h"
- #include "content/public/browser/browser_task_traits.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/navigation_handle.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/web_contents.h"
- #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
- namespace android_webview {
- // static
- void AwRenderViewHostExt::BindFrameHost(
- mojo::PendingAssociatedReceiver<mojom::FrameHost> receiver,
- content::RenderFrameHost* rfh) {
- auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
- if (!web_contents)
- return;
- auto* aw_contents = AwContents::FromWebContents(web_contents);
- if (!aw_contents)
- return;
- auto* aw_rvh_ext = aw_contents->render_view_host_ext();
- if (!aw_rvh_ext)
- return;
- aw_rvh_ext->frame_host_receivers_.Bind(rfh, std::move(receiver));
- }
- AwRenderViewHostExt::AwRenderViewHostExt(AwRenderViewHostExtClient* client,
- content::WebContents* contents)
- : content::WebContentsObserver(contents),
- client_(client),
- frame_host_receivers_(contents, this) {
- DCHECK(client_);
- }
- AwRenderViewHostExt::~AwRenderViewHostExt() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- }
- void AwRenderViewHostExt::DocumentHasImages(DocumentHasImagesResult result) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!web_contents()->GetRenderViewHost()) {
- std::move(result).Run(false);
- return;
- }
- if (auto* local_main_frame_remote = GetLocalMainFrameRemote()) {
- local_main_frame_remote->DocumentHasImage(std::move(result));
- } else {
- // Still have to respond to the API call WebView#docuemntHasImages.
- // Otherwise the listener of the response may be starved.
- std::move(result).Run(false);
- }
- }
- void AwRenderViewHostExt::RequestNewHitTestDataAt(
- const gfx::PointF& touch_center,
- const gfx::SizeF& touch_area) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- // If the new hit testing approach for touch start is enabled we just early
- // return.
- if (base::FeatureList::IsEnabled(
- features::kWebViewHitTestInBlinkOnTouchStart)) {
- return;
- }
- // The following code is broken for OOPIF and fenced frames. The hit testing
- // feature for touch start replaces this code and works correctly in those
- // scenarios. For mitigating risk we've put the old code behind a feature
- // flag.
- //
- // We only need to get blink::WebView on the renderer side to invoke the
- // blink hit test Mojo method, so sending this message via LocalMainFrame
- // interface is enough.
- if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
- local_main_frame_remote->HitTest(touch_center, touch_area);
- }
- mojom::HitTestDataPtr AwRenderViewHostExt::TakeLastHitTestData() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- return std::move(last_hit_test_data_);
- }
- void AwRenderViewHostExt::SetTextZoomFactor(float factor) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
- local_main_frame_remote->SetTextZoomFactor(factor);
- }
- void AwRenderViewHostExt::ResetScrollAndScaleState() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
- local_main_frame_remote->ResetScrollAndScaleState();
- }
- void AwRenderViewHostExt::SetInitialPageScale(double page_scale_factor) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
- local_main_frame_remote->SetInitialPageScale(page_scale_factor);
- }
- void AwRenderViewHostExt::SetWillSuppressErrorPage(bool suppress) {
- will_suppress_error_page_ = suppress;
- }
- void AwRenderViewHostExt::SmoothScroll(int target_x,
- int target_y,
- base::TimeDelta duration) {
- if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
- local_main_frame_remote->SmoothScroll(target_x, target_y, duration);
- }
- void AwRenderViewHostExt::DidStartNavigation(
- content::NavigationHandle* navigation_handle) {
- if (will_suppress_error_page_)
- navigation_handle->SetSilentlyIgnoreErrors();
- }
- void AwRenderViewHostExt::DidFinishNavigation(
- content::NavigationHandle* navigation_handle) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!navigation_handle->HasCommitted())
- return;
- // Only record a visit if the navigation affects user-facing session history
- // (i.e. it occurs in the primary frame tree).
- if (navigation_handle->IsInPrimaryMainFrame() ||
- (navigation_handle->GetParentFrame() &&
- navigation_handle->GetParentFrame()->GetPage().IsPrimary() &&
- navigation_handle->HasSubframeNavigationEntryCommitted())) {
- AwBrowserContext::FromWebContents(web_contents())
- ->AddVisitedURLs(navigation_handle->GetRedirectChain());
- }
- }
- void AwRenderViewHostExt::OnPageScaleFactorChanged(float page_scale_factor) {
- client_->OnWebLayoutPageScaleFactorChanged(page_scale_factor);
- }
- void AwRenderViewHostExt::UpdateHitTestData(
- mojom::HitTestDataPtr hit_test_data) {
- content::RenderFrameHost* render_frame_host =
- frame_host_receivers_.GetCurrentTargetFrame();
- // Make sense from any frame of the active frame tree, because a focused
- // node could be in either the mainframe or a subframe.
- if (!render_frame_host->IsActive())
- return;
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- last_hit_test_data_ = std::move(hit_test_data);
- }
- void AwRenderViewHostExt::ContentsSizeChanged(const gfx::Size& contents_size) {
- content::RenderFrameHost* render_frame_host =
- frame_host_receivers_.GetCurrentTargetFrame();
- // Only makes sense coming from the main frame of the current frame tree.
- if (render_frame_host != web_contents()->GetPrimaryMainFrame())
- return;
- client_->OnWebLayoutContentsSizeChanged(contents_size);
- }
- void AwRenderViewHostExt::ShouldOverrideUrlLoading(
- const std::u16string& url,
- bool has_user_gesture,
- bool is_redirect,
- bool is_main_frame,
- ShouldOverrideUrlLoadingCallback callback) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- bool ignore_navigation = false;
- AwContentsClientBridge* client =
- AwContentsClientBridge::FromWebContents(web_contents());
- if (client) {
- if (!client->ShouldOverrideUrlLoading(url, has_user_gesture, is_redirect,
- is_main_frame, &ignore_navigation)) {
- // If the shouldOverrideUrlLoading call caused a java exception we should
- // always return immediately here!
- return;
- }
- } else {
- LOG(WARNING) << "Failed to find the associated render view host for url: "
- << url;
- }
- std::move(callback).Run(ignore_navigation);
- }
- mojom::LocalMainFrame* AwRenderViewHostExt::GetLocalMainFrameRemote() {
- // Validate the local main frame matches what we have stored for the current
- // main frame. Previously `local_main_frame_remote_` was adjusted in
- // RenderFrameCreated/RenderFrameHostChanged events but the timings of when
- // this class gets called vs others using this class might cause a TOU
- // problem, so we validate it each time before use.
- content::RenderFrameHost* main_frame = web_contents()->GetPrimaryMainFrame();
- content::GlobalRenderFrameHostId main_frame_id = main_frame->GetGlobalId();
- if (main_frame_global_id_ == main_frame_id) {
- return local_main_frame_remote_.get();
- }
- local_main_frame_remote_.reset();
- // Avoid accessing GetRemoteAssociatedInterfaces until the renderer is
- // created.
- if (!main_frame->IsRenderFrameLive()) {
- main_frame_global_id_ = content::GlobalRenderFrameHostId();
- return nullptr;
- }
- main_frame_global_id_ = main_frame_id;
- main_frame->GetRemoteAssociatedInterfaces()->GetInterface(
- local_main_frame_remote_.BindNewEndpointAndPassReceiver());
- return local_main_frame_remote_.get();
- }
- } // namespace android_webview
|