aw_render_view_host_ext.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
  5. #include "android_webview/browser/aw_browser_context.h"
  6. #include "android_webview/browser/aw_contents.h"
  7. #include "android_webview/browser/aw_contents_client_bridge.h"
  8. #include "android_webview/common/aw_features.h"
  9. #include "base/android/scoped_java_ref.h"
  10. #include "base/bind.h"
  11. #include "base/callback.h"
  12. #include "base/command_line.h"
  13. #include "base/logging.h"
  14. #include "content/public/browser/browser_task_traits.h"
  15. #include "content/public/browser/browser_thread.h"
  16. #include "content/public/browser/navigation_handle.h"
  17. #include "content/public/browser/render_frame_host.h"
  18. #include "content/public/browser/render_process_host.h"
  19. #include "content/public/browser/render_view_host.h"
  20. #include "content/public/browser/web_contents.h"
  21. #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
  22. namespace android_webview {
  23. // static
  24. void AwRenderViewHostExt::BindFrameHost(
  25. mojo::PendingAssociatedReceiver<mojom::FrameHost> receiver,
  26. content::RenderFrameHost* rfh) {
  27. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  28. if (!web_contents)
  29. return;
  30. auto* aw_contents = AwContents::FromWebContents(web_contents);
  31. if (!aw_contents)
  32. return;
  33. auto* aw_rvh_ext = aw_contents->render_view_host_ext();
  34. if (!aw_rvh_ext)
  35. return;
  36. aw_rvh_ext->frame_host_receivers_.Bind(rfh, std::move(receiver));
  37. }
  38. AwRenderViewHostExt::AwRenderViewHostExt(AwRenderViewHostExtClient* client,
  39. content::WebContents* contents)
  40. : content::WebContentsObserver(contents),
  41. client_(client),
  42. frame_host_receivers_(contents, this) {
  43. DCHECK(client_);
  44. }
  45. AwRenderViewHostExt::~AwRenderViewHostExt() {
  46. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  47. }
  48. void AwRenderViewHostExt::DocumentHasImages(DocumentHasImagesResult result) {
  49. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  50. if (!web_contents()->GetRenderViewHost()) {
  51. std::move(result).Run(false);
  52. return;
  53. }
  54. if (auto* local_main_frame_remote = GetLocalMainFrameRemote()) {
  55. local_main_frame_remote->DocumentHasImage(std::move(result));
  56. } else {
  57. // Still have to respond to the API call WebView#docuemntHasImages.
  58. // Otherwise the listener of the response may be starved.
  59. std::move(result).Run(false);
  60. }
  61. }
  62. void AwRenderViewHostExt::RequestNewHitTestDataAt(
  63. const gfx::PointF& touch_center,
  64. const gfx::SizeF& touch_area) {
  65. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  66. // If the new hit testing approach for touch start is enabled we just early
  67. // return.
  68. if (base::FeatureList::IsEnabled(
  69. features::kWebViewHitTestInBlinkOnTouchStart)) {
  70. return;
  71. }
  72. // The following code is broken for OOPIF and fenced frames. The hit testing
  73. // feature for touch start replaces this code and works correctly in those
  74. // scenarios. For mitigating risk we've put the old code behind a feature
  75. // flag.
  76. //
  77. // We only need to get blink::WebView on the renderer side to invoke the
  78. // blink hit test Mojo method, so sending this message via LocalMainFrame
  79. // interface is enough.
  80. if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
  81. local_main_frame_remote->HitTest(touch_center, touch_area);
  82. }
  83. mojom::HitTestDataPtr AwRenderViewHostExt::TakeLastHitTestData() {
  84. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  85. return std::move(last_hit_test_data_);
  86. }
  87. void AwRenderViewHostExt::SetTextZoomFactor(float factor) {
  88. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  89. if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
  90. local_main_frame_remote->SetTextZoomFactor(factor);
  91. }
  92. void AwRenderViewHostExt::ResetScrollAndScaleState() {
  93. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  94. if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
  95. local_main_frame_remote->ResetScrollAndScaleState();
  96. }
  97. void AwRenderViewHostExt::SetInitialPageScale(double page_scale_factor) {
  98. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  99. if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
  100. local_main_frame_remote->SetInitialPageScale(page_scale_factor);
  101. }
  102. void AwRenderViewHostExt::SetWillSuppressErrorPage(bool suppress) {
  103. will_suppress_error_page_ = suppress;
  104. }
  105. void AwRenderViewHostExt::SmoothScroll(int target_x,
  106. int target_y,
  107. base::TimeDelta duration) {
  108. if (auto* local_main_frame_remote = GetLocalMainFrameRemote())
  109. local_main_frame_remote->SmoothScroll(target_x, target_y, duration);
  110. }
  111. void AwRenderViewHostExt::DidStartNavigation(
  112. content::NavigationHandle* navigation_handle) {
  113. if (will_suppress_error_page_)
  114. navigation_handle->SetSilentlyIgnoreErrors();
  115. }
  116. void AwRenderViewHostExt::DidFinishNavigation(
  117. content::NavigationHandle* navigation_handle) {
  118. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  119. if (!navigation_handle->HasCommitted())
  120. return;
  121. // Only record a visit if the navigation affects user-facing session history
  122. // (i.e. it occurs in the primary frame tree).
  123. if (navigation_handle->IsInPrimaryMainFrame() ||
  124. (navigation_handle->GetParentFrame() &&
  125. navigation_handle->GetParentFrame()->GetPage().IsPrimary() &&
  126. navigation_handle->HasSubframeNavigationEntryCommitted())) {
  127. AwBrowserContext::FromWebContents(web_contents())
  128. ->AddVisitedURLs(navigation_handle->GetRedirectChain());
  129. }
  130. }
  131. void AwRenderViewHostExt::OnPageScaleFactorChanged(float page_scale_factor) {
  132. client_->OnWebLayoutPageScaleFactorChanged(page_scale_factor);
  133. }
  134. void AwRenderViewHostExt::UpdateHitTestData(
  135. mojom::HitTestDataPtr hit_test_data) {
  136. content::RenderFrameHost* render_frame_host =
  137. frame_host_receivers_.GetCurrentTargetFrame();
  138. // Make sense from any frame of the active frame tree, because a focused
  139. // node could be in either the mainframe or a subframe.
  140. if (!render_frame_host->IsActive())
  141. return;
  142. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  143. last_hit_test_data_ = std::move(hit_test_data);
  144. }
  145. void AwRenderViewHostExt::ContentsSizeChanged(const gfx::Size& contents_size) {
  146. content::RenderFrameHost* render_frame_host =
  147. frame_host_receivers_.GetCurrentTargetFrame();
  148. // Only makes sense coming from the main frame of the current frame tree.
  149. if (render_frame_host != web_contents()->GetPrimaryMainFrame())
  150. return;
  151. client_->OnWebLayoutContentsSizeChanged(contents_size);
  152. }
  153. void AwRenderViewHostExt::ShouldOverrideUrlLoading(
  154. const std::u16string& url,
  155. bool has_user_gesture,
  156. bool is_redirect,
  157. bool is_main_frame,
  158. ShouldOverrideUrlLoadingCallback callback) {
  159. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  160. bool ignore_navigation = false;
  161. AwContentsClientBridge* client =
  162. AwContentsClientBridge::FromWebContents(web_contents());
  163. if (client) {
  164. if (!client->ShouldOverrideUrlLoading(url, has_user_gesture, is_redirect,
  165. is_main_frame, &ignore_navigation)) {
  166. // If the shouldOverrideUrlLoading call caused a java exception we should
  167. // always return immediately here!
  168. return;
  169. }
  170. } else {
  171. LOG(WARNING) << "Failed to find the associated render view host for url: "
  172. << url;
  173. }
  174. std::move(callback).Run(ignore_navigation);
  175. }
  176. mojom::LocalMainFrame* AwRenderViewHostExt::GetLocalMainFrameRemote() {
  177. // Validate the local main frame matches what we have stored for the current
  178. // main frame. Previously `local_main_frame_remote_` was adjusted in
  179. // RenderFrameCreated/RenderFrameHostChanged events but the timings of when
  180. // this class gets called vs others using this class might cause a TOU
  181. // problem, so we validate it each time before use.
  182. content::RenderFrameHost* main_frame = web_contents()->GetPrimaryMainFrame();
  183. content::GlobalRenderFrameHostId main_frame_id = main_frame->GetGlobalId();
  184. if (main_frame_global_id_ == main_frame_id) {
  185. return local_main_frame_remote_.get();
  186. }
  187. local_main_frame_remote_.reset();
  188. // Avoid accessing GetRemoteAssociatedInterfaces until the renderer is
  189. // created.
  190. if (!main_frame->IsRenderFrameLive()) {
  191. main_frame_global_id_ = content::GlobalRenderFrameHostId();
  192. return nullptr;
  193. }
  194. main_frame_global_id_ = main_frame_id;
  195. main_frame->GetRemoteAssociatedInterfaces()->GetInterface(
  196. local_main_frame_remote_.BindNewEndpointAndPassReceiver());
  197. return local_main_frame_remote_.get();
  198. }
  199. } // namespace android_webview