1 // Copyright 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 
5 #include "android_webview/browser/aw_contents.h"
6 
7 #include <limits>
8 #include <memory>
9 #include <utility>
10 
11 #include "android_webview/browser/aw_autofill_client.h"
12 #include "android_webview/browser/aw_browser_context.h"
13 #include "android_webview/browser/aw_browser_main_parts.h"
14 #include "android_webview/browser/aw_contents_client_bridge.h"
15 #include "android_webview/browser/aw_contents_io_thread_client.h"
16 #include "android_webview/browser/aw_pdf_exporter.h"
17 #include "android_webview/browser/aw_render_process.h"
18 #include "android_webview/browser/aw_renderer_priority.h"
19 #include "android_webview/browser/aw_resource_context.h"
20 #include "android_webview/browser/aw_settings.h"
21 #include "android_webview/browser/aw_web_contents_delegate.h"
22 #include "android_webview/browser/gfx/aw_gl_functor.h"
23 #include "android_webview/browser/gfx/aw_picture.h"
24 #include "android_webview/browser/gfx/browser_view_renderer.h"
25 #include "android_webview/browser/gfx/child_frame.h"
26 #include "android_webview/browser/gfx/gpu_service_web_view.h"
27 #include "android_webview/browser/gfx/java_browser_view_renderer_helper.h"
28 #include "android_webview/browser/gfx/render_thread_manager.h"
29 #include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
30 #include "android_webview/browser/js_java_interaction/aw_web_message_host_factory.h"
31 #include "android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h"
32 #include "android_webview/browser/page_load_metrics/page_load_metrics_initialize.h"
33 #include "android_webview/browser/permission/aw_permission_request.h"
34 #include "android_webview/browser/permission/permission_request_handler.h"
35 #include "android_webview/browser/permission/simple_permission_request.h"
36 #include "android_webview/browser/state_serializer.h"
37 #include "android_webview/browser_jni_headers/AwContents_jni.h"
38 #include "android_webview/common/aw_hit_test_data.h"
39 #include "android_webview/common/aw_switches.h"
40 #include "android_webview/common/devtools_instrumentation.h"
41 #include "base/android/jni_android.h"
42 #include "base/android/jni_array.h"
43 #include "base/android/jni_string.h"
44 #include "base/android/locale_utils.h"
45 #include "base/android/scoped_java_ref.h"
46 #include "base/atomicops.h"
47 #include "base/bind.h"
48 #include "base/callback.h"
49 #include "base/callback_helpers.h"
50 #include "base/command_line.h"
51 #include "base/feature_list.h"
52 #include "base/i18n/rtl.h"
53 #include "base/json/json_writer.h"
54 #include "base/location.h"
55 #include "base/macros.h"
56 #include "base/memory/memory_pressure_listener.h"
57 #include "base/no_destructor.h"
58 #include "base/pickle.h"
59 #include "base/single_thread_task_runner.h"
60 #include "base/strings/string16.h"
61 #include "base/supports_user_data.h"
62 #include "base/threading/thread_restrictions.h"
63 #include "base/threading/thread_task_runner_handle.h"
64 #include "components/autofill/android/provider/autofill_provider_android.h"
65 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
66 #include "components/autofill/core/browser/autofill_manager.h"
67 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
68 #include "components/navigation_interception/intercept_navigation_delegate.h"
69 #include "components/safe_browsing/core/features.h"
70 #include "components/security_interstitials/content/security_interstitial_tab_helper.h"
71 #include "components/viz/common/surfaces/frame_sink_id.h"
72 #include "content/public/browser/android/child_process_importance.h"
73 #include "content/public/browser/android/synchronous_compositor.h"
74 #include "content/public/browser/browser_task_traits.h"
75 #include "content/public/browser/browser_thread.h"
76 #include "content/public/browser/browsing_data_remover.h"
77 #include "content/public/browser/child_process_security_policy.h"
78 #include "content/public/browser/favicon_status.h"
79 #include "content/public/browser/navigation_entry.h"
80 #include "content/public/browser/navigation_handle.h"
81 #include "content/public/browser/render_frame_host.h"
82 #include "content/public/browser/render_process_host.h"
83 #include "content/public/browser/render_view_host.h"
84 #include "content/public/browser/render_widget_host.h"
85 #include "content/public/browser/render_widget_host_iterator.h"
86 #include "content/public/browser/ssl_status.h"
87 #include "content/public/browser/web_contents.h"
88 #include "content/public/common/mhtml_generation_params.h"
89 #include "content/public/common/use_zoom_for_dsf_policy.h"
90 #include "net/base/auth.h"
91 #include "net/cert/x509_certificate.h"
92 #include "net/cert/x509_util.h"
93 #include "third_party/skia/include/core/SkPicture.h"
94 #include "ui/gfx/android/java_bitmap.h"
95 #include "ui/gfx/geometry/rect_f.h"
96 #include "ui/gfx/geometry/size.h"
97 #include "ui/gfx/image/image.h"
98 struct AwDrawSWFunctionTable;
99 
100 using autofill::AutofillManager;
101 using autofill::ContentAutofillDriverFactory;
102 using base::android::AttachCurrentThread;
103 using base::android::ConvertJavaStringToUTF16;
104 using base::android::ConvertJavaStringToUTF8;
105 using base::android::ConvertUTF16ToJavaString;
106 using base::android::ConvertUTF8ToJavaString;
107 using base::android::HasException;
108 using base::android::JavaParamRef;
109 using base::android::JavaRef;
110 using base::android::ScopedJavaGlobalRef;
111 using base::android::ScopedJavaLocalRef;
112 using content::BrowserThread;
113 using content::RenderFrameHost;
114 using content::WebContents;
115 using js_injection::JsCommunicationHost;
116 using navigation_interception::InterceptNavigationDelegate;
117 
118 namespace android_webview {
119 
120 class CompositorFrameConsumer;
121 
122 namespace {
123 
124 bool g_should_download_favicons = false;
125 
g_locale()126 std::string* g_locale() {
127   static base::NoDestructor<std::string> locale;
128   return locale.get();
129 }
130 
g_locale_list()131 std::string* g_locale_list() {
132   static base::NoDestructor<std::string> locale_list;
133   return locale_list.get();
134 }
135 
136 const void* const kAwContentsUserDataKey = &kAwContentsUserDataKey;
137 const void* const kComputedRendererPriorityUserDataKey =
138     &kComputedRendererPriorityUserDataKey;
139 
140 class AwContentsUserData : public base::SupportsUserData::Data {
141  public:
AwContentsUserData(AwContents * ptr)142   explicit AwContentsUserData(AwContents* ptr) : contents_(ptr) {}
143 
GetContents(WebContents * web_contents)144   static AwContents* GetContents(WebContents* web_contents) {
145     if (!web_contents)
146       return NULL;
147     AwContentsUserData* data = static_cast<AwContentsUserData*>(
148         web_contents->GetUserData(kAwContentsUserDataKey));
149     return data ? data->contents_ : NULL;
150   }
151 
152  private:
153   AwContents* contents_;
154 };
155 
156 base::subtle::Atomic32 g_instance_count = 0;
157 
158 }  // namespace
159 
160 class ScopedAllowInitGLBindings {
161  public:
ScopedAllowInitGLBindings()162   ScopedAllowInitGLBindings() {}
163 
~ScopedAllowInitGLBindings()164   ~ScopedAllowInitGLBindings() {}
165 
166  private:
167   base::ScopedAllowBlocking allow_blocking_;
168 };
169 
170 // static
FromWebContents(WebContents * web_contents)171 AwContents* AwContents::FromWebContents(WebContents* web_contents) {
172   DCHECK_CURRENTLY_ON(BrowserThread::UI);
173   return AwContentsUserData::GetContents(web_contents);
174 }
175 
176 // static
JNI_AwContents_UpdateDefaultLocale(JNIEnv * env,const JavaParamRef<jstring> & locale,const JavaParamRef<jstring> & locale_list)177 void JNI_AwContents_UpdateDefaultLocale(
178     JNIEnv* env,
179     const JavaParamRef<jstring>& locale,
180     const JavaParamRef<jstring>& locale_list) {
181   *g_locale() = ConvertJavaStringToUTF8(env, locale);
182   *g_locale_list() = ConvertJavaStringToUTF8(env, locale_list);
183 }
184 
185 // static
GetLocale()186 std::string AwContents::GetLocale() {
187   return *g_locale();
188 }
189 
190 // static
GetLocaleList()191 std::string AwContents::GetLocaleList() {
192   return *g_locale_list();
193 }
194 
195 // static
FromID(int render_process_id,int render_frame_id)196 AwBrowserPermissionRequestDelegate* AwBrowserPermissionRequestDelegate::FromID(
197     int render_process_id,
198     int render_frame_id) {
199   AwContents* aw_contents =
200       AwContents::FromWebContents(content::WebContents::FromRenderFrameHost(
201           content::RenderFrameHost::FromID(render_process_id,
202                                            render_frame_id)));
203   return aw_contents;
204 }
205 
206 // static
207 AwSafeBrowsingUIManager::UIManagerClient*
FromWebContents(WebContents * web_contents)208 AwSafeBrowsingUIManager::UIManagerClient::FromWebContents(
209     WebContents* web_contents) {
210   return AwContents::FromWebContents(web_contents);
211 }
212 
213 // static
FromWebContents(content::WebContents * web_contents)214 AwRenderProcessGoneDelegate* AwRenderProcessGoneDelegate::FromWebContents(
215     content::WebContents* web_contents) {
216   return AwContents::FromWebContents(web_contents);
217 }
218 
AwContents(std::unique_ptr<WebContents> web_contents)219 AwContents::AwContents(std::unique_ptr<WebContents> web_contents)
220     : content::WebContentsObserver(web_contents.get()),
221       browser_view_renderer_(this, content::GetUIThreadTaskRunner({})),
222       web_contents_(std::move(web_contents)) {
223   base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1);
224   icon_helper_.reset(new IconHelper(web_contents_.get()));
225   icon_helper_->SetListener(this);
226   web_contents_->SetUserData(android_webview::kAwContentsUserDataKey,
227                              std::make_unique<AwContentsUserData>(this));
228   browser_view_renderer_.RegisterWithWebContents(web_contents_.get());
229 
230   viz::FrameSinkId frame_sink_id;
231   if (web_contents_->GetRenderViewHost()) {
232     frame_sink_id =
233         web_contents_->GetRenderViewHost()->GetWidget()->GetFrameSinkId();
234   }
235 
236   browser_view_renderer_.SetActiveFrameSinkId(frame_sink_id);
237   render_view_host_ext_.reset(
238       new AwRenderViewHostExt(this, web_contents_.get()));
239 
240   InitializePageLoadMetricsForWebContents(web_contents_.get());
241 
242   permission_request_handler_.reset(
243       new PermissionRequestHandler(this, web_contents_.get()));
244 
245   AwAutofillClient* autofill_manager_delegate =
246       AwAutofillClient::FromWebContents(web_contents_.get());
247   if (autofill_manager_delegate)
248     InitAutofillIfNecessary(autofill_manager_delegate->GetSaveFormData());
249   content::SynchronousCompositor::SetClientForWebContents(
250       web_contents_.get(), &browser_view_renderer_);
251   AwContentsLifecycleNotifier::GetInstance().OnWebViewCreated(this);
252   AwBrowserProcess::GetInstance()->visibility_metrics_logger()->AddClient(this);
253 }
254 
SetJavaPeers(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jobject> & aw_contents,const JavaParamRef<jobject> & web_contents_delegate,const JavaParamRef<jobject> & contents_client_bridge,const JavaParamRef<jobject> & io_thread_client,const JavaParamRef<jobject> & intercept_navigation_delegate,const JavaParamRef<jobject> & autofill_provider)255 void AwContents::SetJavaPeers(
256     JNIEnv* env,
257     const JavaParamRef<jobject>& obj,
258     const JavaParamRef<jobject>& aw_contents,
259     const JavaParamRef<jobject>& web_contents_delegate,
260     const JavaParamRef<jobject>& contents_client_bridge,
261     const JavaParamRef<jobject>& io_thread_client,
262     const JavaParamRef<jobject>& intercept_navigation_delegate,
263     const JavaParamRef<jobject>& autofill_provider) {
264   DCHECK_CURRENTLY_ON(BrowserThread::UI);
265   // The |aw_content| param is technically spurious as it duplicates |obj| but
266   // is passed over anyway to make the binding more explicit.
267   java_ref_ = JavaObjectWeakGlobalRef(env, aw_contents);
268 
269   web_contents_delegate_.reset(
270       new AwWebContentsDelegate(env, web_contents_delegate));
271   web_contents_->SetDelegate(web_contents_delegate_.get());
272 
273   contents_client_bridge_.reset(
274       new AwContentsClientBridge(env, contents_client_bridge));
275   AwContentsClientBridge::Associate(web_contents_.get(),
276                                     contents_client_bridge_.get());
277 
278   AwContentsIoThreadClient::Associate(web_contents_.get(), io_thread_client);
279 
280   InterceptNavigationDelegate::Associate(
281       web_contents_.get(), std::make_unique<InterceptNavigationDelegate>(
282                                env, intercept_navigation_delegate));
283 
284   if (autofill_provider) {
285     autofill_provider_ = std::make_unique<autofill::AutofillProviderAndroid>(
286         autofill_provider, web_contents_.get());
287   }
288 }
289 
SetSaveFormData(bool enabled)290 void AwContents::SetSaveFormData(bool enabled) {
291   DCHECK_CURRENTLY_ON(BrowserThread::UI);
292   InitAutofillIfNecessary(enabled);
293   // We need to check for the existence, since autofill_manager_delegate
294   // may not be created when the setting is false.
295   if (AwAutofillClient::FromWebContents(web_contents_.get())) {
296     AwAutofillClient::FromWebContents(web_contents_.get())
297         ->SetSaveFormData(enabled);
298   }
299 }
300 
InitAutofillIfNecessary(bool autocomplete_enabled)301 void AwContents::InitAutofillIfNecessary(bool autocomplete_enabled) {
302   // Check if the autofill driver factory already exists.
303   content::WebContents* web_contents = web_contents_.get();
304   if (ContentAutofillDriverFactory::FromWebContents(web_contents))
305     return;
306 
307   // Check if AutofillProvider is available.
308   DCHECK_CURRENTLY_ON(BrowserThread::UI);
309   JNIEnv* env = AttachCurrentThread();
310   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
311   if (!obj)
312     return;
313 
314   // Just return, if the app neither runs on O sdk nor enables autocomplete.
315   if (!autofill_provider_ && !autocomplete_enabled)
316     return;
317 
318   AwAutofillClient::CreateForWebContents(web_contents);
319   ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
320       web_contents, AwAutofillClient::FromWebContents(web_contents),
321       base::android::GetDefaultLocaleString(),
322       AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER,
323       autofill_provider_.get());
324 }
325 
SetAwAutofillClient(const JavaRef<jobject> & client)326 void AwContents::SetAwAutofillClient(const JavaRef<jobject>& client) {
327   DCHECK_CURRENTLY_ON(BrowserThread::UI);
328   JNIEnv* env = AttachCurrentThread();
329   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
330   if (!obj)
331     return;
332   Java_AwContents_setAwAutofillClient(env, obj, client);
333 }
334 
~AwContents()335 AwContents::~AwContents() {
336   DCHECK_EQ(this, AwContents::FromWebContents(web_contents_.get()));
337   web_contents_->RemoveUserData(kAwContentsUserDataKey);
338   AwContentsClientBridge::Dissociate(web_contents_.get());
339   if (find_helper_.get())
340     find_helper_->SetListener(NULL);
341   if (icon_helper_.get())
342     icon_helper_->SetListener(NULL);
343   base::subtle::Atomic32 instance_count =
344       base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, -1);
345   // When the last WebView is destroyed free all discardable memory allocated by
346   // Chromium, because the app process may continue to run for a long time
347   // without ever using another WebView.
348   if (instance_count == 0) {
349     // TODO(timvolodine): consider moving NotifyMemoryPressure to
350     // AwContentsLifecycleNotifier (crbug.com/522988).
351     base::MemoryPressureListener::NotifyMemoryPressure(
352         base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
353   }
354   browser_view_renderer_.SetCurrentCompositorFrameConsumer(nullptr);
355   AwContentsLifecycleNotifier::GetInstance().OnWebViewDestroyed(this);
356   WebContentsObserver::Observe(nullptr);
357   AwBrowserProcess::GetInstance()->visibility_metrics_logger()->RemoveClient(
358       this);
359 }
360 
GetWebContents(JNIEnv * env,const JavaParamRef<jobject> & obj)361 base::android::ScopedJavaLocalRef<jobject> AwContents::GetWebContents(
362     JNIEnv* env,
363     const JavaParamRef<jobject>& obj) {
364   DCHECK_CURRENTLY_ON(BrowserThread::UI);
365   DCHECK(web_contents_);
366   if (!web_contents_)
367     return base::android::ScopedJavaLocalRef<jobject>();
368 
369   return web_contents_->GetJavaWebContents();
370 }
371 
GetBrowserContext(JNIEnv * env,const JavaParamRef<jobject> & obj)372 base::android::ScopedJavaLocalRef<jobject> AwContents::GetBrowserContext(
373     JNIEnv* env,
374     const JavaParamRef<jobject>& obj) {
375   if (!web_contents_)
376     return base::android::ScopedJavaLocalRef<jobject>();
377   return AwBrowserContext::FromWebContents(web_contents_.get())
378       ->GetJavaBrowserContext();
379 }
380 
SetCompositorFrameConsumer(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj,jlong compositor_frame_consumer)381 void AwContents::SetCompositorFrameConsumer(
382     JNIEnv* env,
383     const base::android::JavaParamRef<jobject>& obj,
384     jlong compositor_frame_consumer) {
385   browser_view_renderer_.SetCurrentCompositorFrameConsumer(
386       reinterpret_cast<CompositorFrameConsumer*>(compositor_frame_consumer));
387 }
388 
GetRenderProcess(JNIEnv * env,const JavaParamRef<jobject> & obj)389 ScopedJavaLocalRef<jobject> AwContents::GetRenderProcess(
390     JNIEnv* env,
391     const JavaParamRef<jobject>& obj) {
392   DCHECK_CURRENTLY_ON(BrowserThread::UI);
393   content::RenderProcessHost* host =
394       web_contents_->GetMainFrame()->GetProcess();
395   if (host->run_renderer_in_process()) {
396     return ScopedJavaLocalRef<jobject>();
397   }
398   AwRenderProcess* render_process =
399       AwRenderProcess::GetInstanceForRenderProcessHost(host);
400   return render_process->GetJavaObject();
401 }
402 
Destroy(JNIEnv * env)403 void AwContents::Destroy(JNIEnv* env) {
404   java_ref_.reset();
405   delete this;
406 }
407 
JNI_AwContents_Init(JNIEnv * env,jlong browser_context_pointer)408 static jlong JNI_AwContents_Init(JNIEnv* env, jlong browser_context_pointer) {
409   AwBrowserContext* browser_context =
410       reinterpret_cast<AwBrowserContext*>(browser_context_pointer);
411   std::unique_ptr<WebContents> web_contents(content::WebContents::Create(
412       content::WebContents::CreateParams(browser_context)));
413   // Return an 'uninitialized' instance; most work is deferred until the
414   // subsequent SetJavaPeers() call.
415   return reinterpret_cast<intptr_t>(new AwContents(std::move(web_contents)));
416 }
417 
JNI_AwContents_HasRequiredHardwareExtensions(JNIEnv * env)418 static jboolean JNI_AwContents_HasRequiredHardwareExtensions(JNIEnv* env) {
419   ScopedAllowInitGLBindings scoped_allow_init_gl_bindings;
420   // Make sure GPUInfo is collected. This will initialize GL bindings,
421   // collect GPUInfo, and compute GpuFeatureInfo if they have not been
422   // already done.
423   return GpuServiceWebView::GetInstance()
424       ->gpu_info()
425       .can_support_threaded_texture_mailbox;
426 }
427 
JNI_AwContents_SetAwDrawSWFunctionTable(JNIEnv * env,jlong function_table)428 static void JNI_AwContents_SetAwDrawSWFunctionTable(JNIEnv* env,
429                                                     jlong function_table) {
430   RasterHelperSetAwDrawSWFunctionTable(
431       reinterpret_cast<AwDrawSWFunctionTable*>(function_table));
432 }
433 
JNI_AwContents_SetAwDrawGLFunctionTable(JNIEnv * env,jlong function_table)434 static void JNI_AwContents_SetAwDrawGLFunctionTable(JNIEnv* env,
435                                                     jlong function_table) {}
436 
JNI_AwContents_UpdateOpenWebScreenArea(JNIEnv * env,jint pixels,jint percentage)437 static void JNI_AwContents_UpdateOpenWebScreenArea(JNIEnv* env,
438                                                    jint pixels,
439                                                    jint percentage) {
440   AwBrowserProcess::GetInstance()
441       ->visibility_metrics_logger()
442       ->UpdateOpenWebScreenArea(pixels, percentage);
443 }
444 
445 // static
JNI_AwContents_GetNativeInstanceCount(JNIEnv * env)446 jint JNI_AwContents_GetNativeInstanceCount(JNIEnv* env) {
447   return base::subtle::NoBarrier_Load(&g_instance_count);
448 }
449 
450 // static
JNI_AwContents_GetSafeBrowsingLocaleForTesting(JNIEnv * env)451 ScopedJavaLocalRef<jstring> JNI_AwContents_GetSafeBrowsingLocaleForTesting(
452     JNIEnv* env) {
453   ScopedJavaLocalRef<jstring> locale =
454       ConvertUTF8ToJavaString(env, base::i18n::GetConfiguredLocale());
455   return locale;
456 }
457 
458 namespace {
DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject> & message,bool has_images)459 void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message,
460                                bool has_images) {
461   Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(), has_images,
462                                               message);
463 }
464 }  // namespace
465 
DocumentHasImages(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jobject> & message)466 void AwContents::DocumentHasImages(JNIEnv* env,
467                                    const JavaParamRef<jobject>& obj,
468                                    const JavaParamRef<jobject>& message) {
469   DCHECK_CURRENTLY_ON(BrowserThread::UI);
470   ScopedJavaGlobalRef<jobject> j_message;
471   j_message.Reset(env, message);
472   render_view_host_ext_->DocumentHasImages(
473       base::BindOnce(&DocumentHasImagesCallback, j_message));
474 }
475 
476 namespace {
GenerateMHTMLCallback(const JavaRef<jobject> & callback,const base::FilePath & path,int64_t size)477 void GenerateMHTMLCallback(const JavaRef<jobject>& callback,
478                            const base::FilePath& path,
479                            int64_t size) {
480   JNIEnv* env = AttachCurrentThread();
481   // Android files are UTF8, so the path conversion below is safe.
482   Java_AwContents_generateMHTMLCallback(
483       env, ConvertUTF8ToJavaString(env, path.AsUTF8Unsafe()), size, callback);
484 }
485 }  // namespace
486 
GenerateMHTML(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jstring> & jpath,const JavaParamRef<jobject> & callback)487 void AwContents::GenerateMHTML(JNIEnv* env,
488                                const JavaParamRef<jobject>& obj,
489                                const JavaParamRef<jstring>& jpath,
490                                const JavaParamRef<jobject>& callback) {
491   DCHECK_CURRENTLY_ON(BrowserThread::UI);
492   base::FilePath target_path(ConvertJavaStringToUTF8(env, jpath));
493   web_contents_->GenerateMHTML(
494       content::MHTMLGenerationParams(target_path),
495       base::BindOnce(&GenerateMHTMLCallback,
496                      ScopedJavaGlobalRef<jobject>(env, callback), target_path));
497 }
498 
CreatePdfExporter(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jobject> & pdfExporter)499 void AwContents::CreatePdfExporter(JNIEnv* env,
500                                    const JavaParamRef<jobject>& obj,
501                                    const JavaParamRef<jobject>& pdfExporter) {
502   pdf_exporter_.reset(new AwPdfExporter(env, pdfExporter, web_contents_.get()));
503 }
504 
OnReceivedHttpAuthRequest(const JavaRef<jobject> & handler,const std::string & host,const std::string & realm)505 bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler,
506                                            const std::string& host,
507                                            const std::string& realm) {
508   DCHECK_CURRENTLY_ON(BrowserThread::UI);
509   JNIEnv* env = AttachCurrentThread();
510   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
511   if (!obj)
512     return false;
513 
514   ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host);
515   ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm);
516   devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
517       "onReceivedHttpAuthRequest");
518   Java_AwContents_onReceivedHttpAuthRequest(env, obj, handler, jhost, jrealm);
519   return true;
520 }
521 
SetOffscreenPreRaster(bool enabled)522 void AwContents::SetOffscreenPreRaster(bool enabled) {
523   DCHECK_CURRENTLY_ON(BrowserThread::UI);
524   browser_view_renderer_.SetOffscreenPreRaster(enabled);
525 }
526 
AddVisitedLinks(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jobjectArray> & jvisited_links)527 void AwContents::AddVisitedLinks(
528     JNIEnv* env,
529     const JavaParamRef<jobject>& obj,
530     const JavaParamRef<jobjectArray>& jvisited_links) {
531   DCHECK_CURRENTLY_ON(BrowserThread::UI);
532   std::vector<base::string16> visited_link_strings;
533   base::android::AppendJavaStringArrayToStringVector(env, jvisited_links,
534                                                      &visited_link_strings);
535 
536   std::vector<GURL> visited_link_gurls;
537   std::vector<base::string16>::const_iterator itr;
538   for (itr = visited_link_strings.begin(); itr != visited_link_strings.end();
539        ++itr) {
540     visited_link_gurls.push_back(GURL(*itr));
541   }
542 
543   AwBrowserContext::FromWebContents(web_contents_.get())
544       ->AddVisitedURLs(visited_link_gurls);
545 }
546 
547 namespace {
548 
ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef & java_ref,const GURL & origin)549 void ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef& java_ref,
550                                      const GURL& origin) {
551   JNIEnv* env = AttachCurrentThread();
552   ScopedJavaLocalRef<jobject> j_ref = java_ref.get(env);
553   if (j_ref.obj()) {
554     ScopedJavaLocalRef<jstring> j_origin(
555         ConvertUTF8ToJavaString(env, origin.spec()));
556     devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
557         "onGeolocationPermissionsShowPrompt");
558     Java_AwContents_onGeolocationPermissionsShowPrompt(env, j_ref, j_origin);
559   }
560 }
561 
ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef & java_ref,const GURL & origin)562 void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref,
563                                  const GURL& origin) {
564   JNIEnv* env = AttachCurrentThread();
565   if (java_ref.get(env).obj()) {
566     content::GetUIThreadTaskRunner({})->PostTask(
567         FROM_HERE,
568         base::BindOnce(&ShowGeolocationPromptHelperTask, java_ref, origin));
569   }
570 }
571 
572 }  // anonymous namespace
573 
ShowGeolocationPrompt(const GURL & requesting_frame,base::OnceCallback<void (bool)> callback)574 void AwContents::ShowGeolocationPrompt(
575     const GURL& requesting_frame,
576     base::OnceCallback<void(bool)> callback) {
577   DCHECK_CURRENTLY_ON(BrowserThread::UI);
578 
579   GURL origin = requesting_frame.GetOrigin();
580   bool show_prompt = pending_geolocation_prompts_.empty();
581   pending_geolocation_prompts_.emplace_back(origin, std::move(callback));
582   if (show_prompt) {
583     ShowGeolocationPromptHelper(java_ref_, origin);
584   }
585 }
586 
587 // Invoked from Java
InvokeGeolocationCallback(JNIEnv * env,const JavaParamRef<jobject> & obj,jboolean value,const JavaParamRef<jstring> & origin)588 void AwContents::InvokeGeolocationCallback(
589     JNIEnv* env,
590     const JavaParamRef<jobject>& obj,
591     jboolean value,
592     const JavaParamRef<jstring>& origin) {
593   DCHECK_CURRENTLY_ON(BrowserThread::UI);
594   if (pending_geolocation_prompts_.empty())
595     return;
596 
597   GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin));
598   if (callback_origin.GetOrigin() ==
599       pending_geolocation_prompts_.front().first) {
600     std::move(pending_geolocation_prompts_.front().second).Run(value);
601     pending_geolocation_prompts_.pop_front();
602     if (!pending_geolocation_prompts_.empty()) {
603       ShowGeolocationPromptHelper(java_ref_,
604                                   pending_geolocation_prompts_.front().first);
605     }
606   }
607 }
608 
HideGeolocationPrompt(const GURL & origin)609 void AwContents::HideGeolocationPrompt(const GURL& origin) {
610   DCHECK_CURRENTLY_ON(BrowserThread::UI);
611   bool removed_current_outstanding_callback = false;
612   std::list<OriginCallback>::iterator it = pending_geolocation_prompts_.begin();
613   while (it != pending_geolocation_prompts_.end()) {
614     if ((*it).first == origin.GetOrigin()) {
615       if (it == pending_geolocation_prompts_.begin()) {
616         removed_current_outstanding_callback = true;
617       }
618       it = pending_geolocation_prompts_.erase(it);
619     } else {
620       ++it;
621     }
622   }
623 
624   if (removed_current_outstanding_callback) {
625     JNIEnv* env = AttachCurrentThread();
626     ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
627     if (j_ref.obj()) {
628       devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
629           "onGeolocationPermissionsHidePrompt");
630       Java_AwContents_onGeolocationPermissionsHidePrompt(env, j_ref);
631     }
632     if (!pending_geolocation_prompts_.empty()) {
633       ShowGeolocationPromptHelper(java_ref_,
634                                   pending_geolocation_prompts_.front().first);
635     }
636   }
637 }
638 
OnPermissionRequest(base::android::ScopedJavaLocalRef<jobject> j_request,AwPermissionRequest * request)639 void AwContents::OnPermissionRequest(
640     base::android::ScopedJavaLocalRef<jobject> j_request,
641     AwPermissionRequest* request) {
642   DCHECK(j_request);
643   DCHECK(request);
644 
645   JNIEnv* env = AttachCurrentThread();
646   ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
647   if (!j_ref) {
648     permission_request_handler_->CancelRequest(request->GetOrigin(),
649                                                request->GetResources());
650     return;
651   }
652 
653   Java_AwContents_onPermissionRequest(env, j_ref, j_request);
654 }
655 
OnPermissionRequestCanceled(AwPermissionRequest * request)656 void AwContents::OnPermissionRequestCanceled(AwPermissionRequest* request) {
657   JNIEnv* env = AttachCurrentThread();
658   ScopedJavaLocalRef<jobject> j_request = request->GetJavaObject();
659   ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
660   if (!j_request || !j_ref)
661     return;
662 
663   Java_AwContents_onPermissionRequestCanceled(env, j_ref, j_request);
664 }
665 
PreauthorizePermission(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jstring> & origin,jlong resources)666 void AwContents::PreauthorizePermission(JNIEnv* env,
667                                         const JavaParamRef<jobject>& obj,
668                                         const JavaParamRef<jstring>& origin,
669                                         jlong resources) {
670   permission_request_handler_->PreauthorizePermission(
671       GURL(base::android::ConvertJavaStringToUTF8(env, origin)), resources);
672 }
673 
RequestProtectedMediaIdentifierPermission(const GURL & origin,base::OnceCallback<void (bool)> callback)674 void AwContents::RequestProtectedMediaIdentifierPermission(
675     const GURL& origin,
676     base::OnceCallback<void(bool)> callback) {
677   permission_request_handler_->SendRequest(
678       std::make_unique<SimplePermissionRequest>(
679           origin, AwPermissionRequest::ProtectedMediaId, std::move(callback)));
680 }
681 
CancelProtectedMediaIdentifierPermissionRequests(const GURL & origin)682 void AwContents::CancelProtectedMediaIdentifierPermissionRequests(
683     const GURL& origin) {
684   permission_request_handler_->CancelRequest(
685       origin, AwPermissionRequest::ProtectedMediaId);
686 }
687 
RequestGeolocationPermission(const GURL & origin,base::OnceCallback<void (bool)> callback)688 void AwContents::RequestGeolocationPermission(
689     const GURL& origin,
690     base::OnceCallback<void(bool)> callback) {
691   JNIEnv* env = AttachCurrentThread();
692   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
693   if (!obj)
694     return;
695 
696   if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj)) {
697     ShowGeolocationPrompt(origin, std::move(callback));
698     return;
699   }
700   permission_request_handler_->SendRequest(
701       std::make_unique<SimplePermissionRequest>(
702           origin, AwPermissionRequest::Geolocation, std::move(callback)));
703 }
704 
CancelGeolocationPermissionRequests(const GURL & origin)705 void AwContents::CancelGeolocationPermissionRequests(const GURL& origin) {
706   JNIEnv* env = AttachCurrentThread();
707   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
708   if (!obj)
709     return;
710 
711   if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj)) {
712     HideGeolocationPrompt(origin);
713     return;
714   }
715   permission_request_handler_->CancelRequest(origin,
716                                              AwPermissionRequest::Geolocation);
717 }
718 
RequestMIDISysexPermission(const GURL & origin,base::OnceCallback<void (bool)> callback)719 void AwContents::RequestMIDISysexPermission(
720     const GURL& origin,
721     base::OnceCallback<void(bool)> callback) {
722   permission_request_handler_->SendRequest(
723       std::make_unique<SimplePermissionRequest>(
724           origin, AwPermissionRequest::MIDISysex, std::move(callback)));
725 }
726 
CancelMIDISysexPermissionRequests(const GURL & origin)727 void AwContents::CancelMIDISysexPermissionRequests(const GURL& origin) {
728   permission_request_handler_->CancelRequest(
729       origin, AwPermissionRequest::AwPermissionRequest::MIDISysex);
730 }
731 
FindAllAsync(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jstring> & search_string)732 void AwContents::FindAllAsync(JNIEnv* env,
733                               const JavaParamRef<jobject>& obj,
734                               const JavaParamRef<jstring>& search_string) {
735   DCHECK_CURRENTLY_ON(BrowserThread::UI);
736   GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string));
737 }
738 
FindNext(JNIEnv * env,const JavaParamRef<jobject> & obj,jboolean forward)739 void AwContents::FindNext(JNIEnv* env,
740                           const JavaParamRef<jobject>& obj,
741                           jboolean forward) {
742   DCHECK_CURRENTLY_ON(BrowserThread::UI);
743   GetFindHelper()->FindNext(forward);
744 }
745 
ClearMatches(JNIEnv * env,const JavaParamRef<jobject> & obj)746 void AwContents::ClearMatches(JNIEnv* env, const JavaParamRef<jobject>& obj) {
747   DCHECK_CURRENTLY_ON(BrowserThread::UI);
748   GetFindHelper()->ClearMatches();
749 }
750 
ClearCache(JNIEnv * env,const JavaParamRef<jobject> & obj,jboolean include_disk_files)751 void AwContents::ClearCache(JNIEnv* env,
752                             const JavaParamRef<jobject>& obj,
753                             jboolean include_disk_files) {
754   DCHECK_CURRENTLY_ON(BrowserThread::UI);
755   AwRenderProcess* aw_render_process =
756       AwRenderProcess::GetInstanceForRenderProcessHost(
757           web_contents_->GetMainFrame()->GetProcess());
758 
759   aw_render_process->ClearCache();
760 
761   if (include_disk_files) {
762     content::BrowsingDataRemover* remover =
763         content::BrowserContext::GetBrowsingDataRemover(
764             web_contents_->GetBrowserContext());
765     remover->Remove(
766         base::Time(), base::Time::Max(),
767         content::BrowsingDataRemover::DATA_TYPE_CACHE,
768         content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
769             content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB);
770   }
771 }
772 
GetFindHelper()773 FindHelper* AwContents::GetFindHelper() {
774   DCHECK_CURRENTLY_ON(BrowserThread::UI);
775   if (!find_helper_.get()) {
776     find_helper_.reset(new FindHelper(web_contents_.get()));
777     find_helper_->SetListener(this);
778   }
779   return find_helper_.get();
780 }
781 
AllowThirdPartyCookies()782 bool AwContents::AllowThirdPartyCookies() {
783   DCHECK_CURRENTLY_ON(BrowserThread::UI);
784   AwSettings* aw_settings = AwSettings::FromWebContents(web_contents_.get());
785   return aw_settings->GetAllowThirdPartyCookies();
786 }
787 
OnFindResultReceived(int active_ordinal,int match_count,bool finished)788 void AwContents::OnFindResultReceived(int active_ordinal,
789                                       int match_count,
790                                       bool finished) {
791   DCHECK_CURRENTLY_ON(BrowserThread::UI);
792   JNIEnv* env = AttachCurrentThread();
793   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
794   if (!obj)
795     return;
796 
797   Java_AwContents_onFindResultReceived(env, obj, active_ordinal, match_count,
798                                        finished);
799 }
800 
ShouldDownloadFavicon(const GURL & icon_url)801 bool AwContents::ShouldDownloadFavicon(const GURL& icon_url) {
802   return g_should_download_favicons;
803 }
804 
OnReceivedIcon(const GURL & icon_url,const SkBitmap & bitmap)805 void AwContents::OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap) {
806   DCHECK_CURRENTLY_ON(BrowserThread::UI);
807   JNIEnv* env = AttachCurrentThread();
808   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
809   if (!obj)
810     return;
811 
812   content::NavigationEntry* entry =
813       web_contents_->GetController().GetLastCommittedEntry();
814 
815   if (entry) {
816     entry->GetFavicon().valid = true;
817     entry->GetFavicon().url = icon_url;
818     entry->GetFavicon().image = gfx::Image::CreateFrom1xBitmap(bitmap);
819   }
820 
821   ScopedJavaLocalRef<jobject> java_bitmap =
822       gfx::ConvertToJavaBitmap(bitmap, gfx::OomBehavior::kReturnNullOnOom);
823   if (!java_bitmap) {
824     LOG(WARNING) << "Skipping onReceivedIcon; Not enough memory to convert "
825                     "icon to Bitmap.";
826     return;
827   }
828   Java_AwContents_onReceivedIcon(env, obj, java_bitmap);
829 }
830 
OnReceivedTouchIconUrl(const std::string & url,bool precomposed)831 void AwContents::OnReceivedTouchIconUrl(const std::string& url,
832                                         bool precomposed) {
833   DCHECK_CURRENTLY_ON(BrowserThread::UI);
834   JNIEnv* env = AttachCurrentThread();
835   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
836   if (!obj)
837     return;
838 
839   Java_AwContents_onReceivedTouchIconUrl(
840       env, obj, ConvertUTF8ToJavaString(env, url), precomposed);
841 }
842 
PostInvalidate()843 void AwContents::PostInvalidate() {
844   DCHECK_CURRENTLY_ON(BrowserThread::UI);
845   JNIEnv* env = AttachCurrentThread();
846   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
847   if (obj)
848     Java_AwContents_postInvalidateOnAnimation(env, obj);
849 }
850 
OnNewPicture()851 void AwContents::OnNewPicture() {
852   DCHECK_CURRENTLY_ON(BrowserThread::UI);
853   JNIEnv* env = AttachCurrentThread();
854   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
855   if (obj) {
856     devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
857         "onNewPicture");
858     Java_AwContents_onNewPicture(env, obj);
859   }
860 }
861 
OnViewTreeForceDarkStateChanged(bool view_tree_force_dark_state)862 void AwContents::OnViewTreeForceDarkStateChanged(
863     bool view_tree_force_dark_state) {
864   view_tree_force_dark_state_ = view_tree_force_dark_state;
865   web_contents_->NotifyPreferencesChanged();
866 }
867 
GetCertificate(JNIEnv * env,const JavaParamRef<jobject> & obj)868 base::android::ScopedJavaLocalRef<jbyteArray> AwContents::GetCertificate(
869     JNIEnv* env,
870     const JavaParamRef<jobject>& obj) {
871   DCHECK_CURRENTLY_ON(BrowserThread::UI);
872   content::NavigationEntry* entry =
873       web_contents_->GetController().GetLastCommittedEntry();
874   if (!entry || !entry->GetSSL().certificate)
875     return ScopedJavaLocalRef<jbyteArray>();
876 
877   // Convert the certificate and return it
878   base::StringPiece der_string = net::x509_util::CryptoBufferAsStringPiece(
879       entry->GetSSL().certificate->cert_buffer());
880   return base::android::ToJavaByteArray(
881       env, reinterpret_cast<const uint8_t*>(der_string.data()),
882       der_string.length());
883 }
884 
RequestNewHitTestDataAt(JNIEnv * env,const JavaParamRef<jobject> & obj,jfloat x,jfloat y,jfloat touch_major)885 void AwContents::RequestNewHitTestDataAt(JNIEnv* env,
886                                          const JavaParamRef<jobject>& obj,
887                                          jfloat x,
888                                          jfloat y,
889                                          jfloat touch_major) {
890   DCHECK_CURRENTLY_ON(BrowserThread::UI);
891   gfx::PointF touch_center(x, y);
892   gfx::SizeF touch_area(touch_major, touch_major);
893   render_view_host_ext_->RequestNewHitTestDataAt(touch_center, touch_area);
894 }
895 
UpdateLastHitTestData(JNIEnv * env,const JavaParamRef<jobject> & obj)896 void AwContents::UpdateLastHitTestData(JNIEnv* env,
897                                        const JavaParamRef<jobject>& obj) {
898   DCHECK_CURRENTLY_ON(BrowserThread::UI);
899   if (!render_view_host_ext_->HasNewHitTestData())
900     return;
901 
902   const AwHitTestData& data = render_view_host_ext_->GetLastHitTestData();
903   render_view_host_ext_->MarkHitTestDataRead();
904 
905   // Make sure to null the Java object if data is empty/invalid.
906   ScopedJavaLocalRef<jstring> extra_data_for_type;
907   if (data.extra_data_for_type.length())
908     extra_data_for_type =
909         ConvertUTF8ToJavaString(env, data.extra_data_for_type);
910 
911   ScopedJavaLocalRef<jstring> href;
912   if (data.href.length())
913     href = ConvertUTF16ToJavaString(env, data.href);
914 
915   ScopedJavaLocalRef<jstring> anchor_text;
916   if (data.anchor_text.length())
917     anchor_text = ConvertUTF16ToJavaString(env, data.anchor_text);
918 
919   ScopedJavaLocalRef<jstring> img_src;
920   if (data.img_src.is_valid())
921     img_src = ConvertUTF8ToJavaString(env, data.img_src.spec());
922 
923   Java_AwContents_updateHitTestData(env, obj, data.type, extra_data_for_type,
924                                     href, anchor_text, img_src);
925 }
926 
OnSizeChanged(JNIEnv * env,const JavaParamRef<jobject> & obj,int w,int h,int ow,int oh)927 void AwContents::OnSizeChanged(JNIEnv* env,
928                                const JavaParamRef<jobject>& obj,
929                                int w,
930                                int h,
931                                int ow,
932                                int oh) {
933   DCHECK_CURRENTLY_ON(BrowserThread::UI);
934   gfx::Size size(w, h);
935   web_contents_->GetNativeView()->OnPhysicalBackingSizeChanged(size);
936   web_contents_->GetNativeView()->OnSizeChanged(w, h);
937   browser_view_renderer_.OnSizeChanged(w, h);
938   AwBrowserProcess::GetInstance()
939       ->visibility_metrics_logger()
940       ->ClientVisibilityChanged(this);
941 }
942 
SetViewVisibility(JNIEnv * env,const JavaParamRef<jobject> & obj,bool visible)943 void AwContents::SetViewVisibility(JNIEnv* env,
944                                    const JavaParamRef<jobject>& obj,
945                                    bool visible) {
946   DCHECK_CURRENTLY_ON(BrowserThread::UI);
947   browser_view_renderer_.SetViewVisibility(visible);
948   AwBrowserProcess::GetInstance()
949       ->visibility_metrics_logger()
950       ->ClientVisibilityChanged(this);
951 }
952 
SetWindowVisibility(JNIEnv * env,const JavaParamRef<jobject> & obj,bool visible)953 void AwContents::SetWindowVisibility(JNIEnv* env,
954                                      const JavaParamRef<jobject>& obj,
955                                      bool visible) {
956   DCHECK_CURRENTLY_ON(BrowserThread::UI);
957   browser_view_renderer_.SetWindowVisibility(visible);
958   if (visible)
959     AwContentsLifecycleNotifier::GetInstance().OnWebViewWindowBeVisible(this);
960   else
961     AwContentsLifecycleNotifier::GetInstance().OnWebViewWindowBeInvisible(this);
962   AwBrowserProcess::GetInstance()
963       ->visibility_metrics_logger()
964       ->ClientVisibilityChanged(this);
965 }
966 
SetIsPaused(JNIEnv * env,const JavaParamRef<jobject> & obj,bool paused)967 void AwContents::SetIsPaused(JNIEnv* env,
968                              const JavaParamRef<jobject>& obj,
969                              bool paused) {
970   DCHECK_CURRENTLY_ON(BrowserThread::UI);
971   browser_view_renderer_.SetIsPaused(paused);
972 }
973 
OnAttachedToWindow(JNIEnv * env,const JavaParamRef<jobject> & obj,int w,int h)974 void AwContents::OnAttachedToWindow(JNIEnv* env,
975                                     const JavaParamRef<jobject>& obj,
976                                     int w,
977                                     int h) {
978   DCHECK_CURRENTLY_ON(BrowserThread::UI);
979   browser_view_renderer_.OnAttachedToWindow(w, h);
980   AwContentsLifecycleNotifier::GetInstance().OnWebViewAttachedToWindow(this);
981   AwBrowserProcess::GetInstance()
982       ->visibility_metrics_logger()
983       ->ClientVisibilityChanged(this);
984 }
985 
OnDetachedFromWindow(JNIEnv * env,const JavaParamRef<jobject> & obj)986 void AwContents::OnDetachedFromWindow(JNIEnv* env,
987                                       const JavaParamRef<jobject>& obj) {
988   DCHECK_CURRENTLY_ON(BrowserThread::UI);
989   browser_view_renderer_.OnDetachedFromWindow();
990   AwContentsLifecycleNotifier::GetInstance().OnWebViewDetachedFromWindow(this);
991   AwBrowserProcess::GetInstance()
992       ->visibility_metrics_logger()
993       ->ClientVisibilityChanged(this);
994 }
995 
IsVisible(JNIEnv * env,const JavaParamRef<jobject> & obj)996 bool AwContents::IsVisible(JNIEnv* env, const JavaParamRef<jobject>& obj) {
997   return browser_view_renderer_.IsClientVisible();
998 }
999 
IsDisplayingInterstitialForTesting(JNIEnv * env,const JavaParamRef<jobject> & obj)1000 bool AwContents::IsDisplayingInterstitialForTesting(
1001     JNIEnv* env,
1002     const JavaParamRef<jobject>& obj) {
1003   security_interstitials::SecurityInterstitialTabHelper*
1004       security_interstitial_tab_helper = security_interstitials::
1005           SecurityInterstitialTabHelper::FromWebContents(web_contents_.get());
1006   return security_interstitial_tab_helper &&
1007          security_interstitial_tab_helper->IsDisplayingInterstitial();
1008 }
1009 
GetOpaqueState(JNIEnv * env,const JavaParamRef<jobject> & obj)1010 base::android::ScopedJavaLocalRef<jbyteArray> AwContents::GetOpaqueState(
1011     JNIEnv* env,
1012     const JavaParamRef<jobject>& obj) {
1013   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1014   // Required optimization in WebViewClassic to not save any state if
1015   // there has been no navigations.
1016   if (!web_contents_->GetController().GetEntryCount())
1017     return ScopedJavaLocalRef<jbyteArray>();
1018 
1019   base::Pickle pickle;
1020   WriteToPickle(*web_contents_, &pickle);
1021   return base::android::ToJavaByteArray(
1022       env, reinterpret_cast<const uint8_t*>(pickle.data()), pickle.size());
1023 }
1024 
RestoreFromOpaqueState(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jbyteArray> & state)1025 jboolean AwContents::RestoreFromOpaqueState(
1026     JNIEnv* env,
1027     const JavaParamRef<jobject>& obj,
1028     const JavaParamRef<jbyteArray>& state) {
1029   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1030   // TODO(boliu): This copy can be optimized out if this is a performance
1031   // problem.
1032   std::vector<uint8_t> state_vector;
1033   base::android::JavaByteArrayToByteVector(env, state, &state_vector);
1034 
1035   base::Pickle pickle(reinterpret_cast<const char*>(state_vector.data()),
1036                       state_vector.size());
1037   base::PickleIterator iterator(pickle);
1038 
1039   return RestoreFromPickle(&iterator, web_contents_.get());
1040 }
1041 
OnDraw(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jobject> & canvas,jboolean is_hardware_accelerated,jint scroll_x,jint scroll_y,jint visible_left,jint visible_top,jint visible_right,jint visible_bottom,jboolean force_auxiliary_bitmap_rendering)1042 bool AwContents::OnDraw(JNIEnv* env,
1043                         const JavaParamRef<jobject>& obj,
1044                         const JavaParamRef<jobject>& canvas,
1045                         jboolean is_hardware_accelerated,
1046                         jint scroll_x,
1047                         jint scroll_y,
1048                         jint visible_left,
1049                         jint visible_top,
1050                         jint visible_right,
1051                         jint visible_bottom,
1052                         jboolean force_auxiliary_bitmap_rendering) {
1053   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1054   gfx::Vector2d scroll(scroll_x, scroll_y);
1055   browser_view_renderer_.PrepareToDraw(
1056       scroll, gfx::Rect(visible_left, visible_top, visible_right - visible_left,
1057                         visible_bottom - visible_top));
1058   if (is_hardware_accelerated && browser_view_renderer_.attached_to_window() &&
1059       !force_auxiliary_bitmap_rendering) {
1060     return browser_view_renderer_.OnDrawHardware();
1061   }
1062 
1063   gfx::Size view_size = browser_view_renderer_.size();
1064   if (view_size.IsEmpty()) {
1065     TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_EmptySize",
1066                          TRACE_EVENT_SCOPE_THREAD);
1067     return false;
1068   }
1069 
1070   // TODO(hush): Right now webview size is passed in as the auxiliary bitmap
1071   // size, which might hurt performance (only for software draws with auxiliary
1072   // bitmap). For better performance, get global visible rect, transform it
1073   // from screen space to view space, then intersect with the webview in
1074   // viewspace.  Use the resulting rect as the auxiliary bitmap.
1075   std::unique_ptr<SoftwareCanvasHolder> canvas_holder =
1076       SoftwareCanvasHolder::Create(canvas, scroll, view_size,
1077                                    force_auxiliary_bitmap_rendering);
1078   if (!canvas_holder || !canvas_holder->GetCanvas()) {
1079     TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_NoSoftwareCanvas",
1080                          TRACE_EVENT_SCOPE_THREAD);
1081     return false;
1082   }
1083   return browser_view_renderer_.OnDrawSoftware(canvas_holder->GetCanvas());
1084 }
1085 
NeedToDrawBackgroundColor(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj)1086 bool AwContents::NeedToDrawBackgroundColor(
1087     JNIEnv* env,
1088     const base::android::JavaParamRef<jobject>& obj) {
1089   return browser_view_renderer_.NeedToDrawBackgroundColor();
1090 }
1091 
SetPendingWebContentsForPopup(std::unique_ptr<content::WebContents> pending)1092 void AwContents::SetPendingWebContentsForPopup(
1093     std::unique_ptr<content::WebContents> pending) {
1094   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1095   if (pending_contents_.get()) {
1096     // TODO(benm): Support holding multiple pop up window requests.
1097     LOG(WARNING) << "Blocking popup window creation as an outstanding "
1098                  << "popup window is still pending.";
1099     base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
1100                                                     pending.release());
1101     return;
1102   }
1103   pending_contents_.reset(new AwContents(std::move(pending)));
1104   // Set dip_scale for pending contents, which is necessary for the later
1105   // SynchronousCompositor and InputHandler setup.
1106   pending_contents_->SetDipScaleInternal(browser_view_renderer_.dip_scale());
1107 }
1108 
FocusFirstNode(JNIEnv * env,const JavaParamRef<jobject> & obj)1109 void AwContents::FocusFirstNode(JNIEnv* env, const JavaParamRef<jobject>& obj) {
1110   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1111   web_contents_->FocusThroughTabTraversal(false);
1112 }
1113 
SetBackgroundColor(JNIEnv * env,const JavaParamRef<jobject> & obj,jint color)1114 void AwContents::SetBackgroundColor(JNIEnv* env,
1115                                     const JavaParamRef<jobject>& obj,
1116                                     jint color) {
1117   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1118   render_view_host_ext_->SetBackgroundColor(color);
1119 }
1120 
ZoomBy(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj,jfloat delta)1121 void AwContents::ZoomBy(JNIEnv* env,
1122                         const base::android::JavaParamRef<jobject>& obj,
1123                         jfloat delta) {
1124   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1125   browser_view_renderer_.ZoomBy(delta);
1126 }
1127 
OnComputeScroll(JNIEnv * env,const JavaParamRef<jobject> & obj,jlong animation_time_millis)1128 void AwContents::OnComputeScroll(JNIEnv* env,
1129                                  const JavaParamRef<jobject>& obj,
1130                                  jlong animation_time_millis) {
1131   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1132   browser_view_renderer_.OnComputeScroll(
1133       base::TimeTicks() +
1134       base::TimeDelta::FromMilliseconds(animation_time_millis));
1135 }
1136 
ReleasePopupAwContents(JNIEnv * env,const JavaParamRef<jobject> & obj)1137 jlong AwContents::ReleasePopupAwContents(JNIEnv* env,
1138                                          const JavaParamRef<jobject>& obj) {
1139   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1140   return reinterpret_cast<intptr_t>(pending_contents_.release());
1141 }
1142 
GetLocationOnScreen()1143 gfx::Point AwContents::GetLocationOnScreen() {
1144   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1145   JNIEnv* env = AttachCurrentThread();
1146   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1147   if (!obj)
1148     return gfx::Point();
1149   std::vector<int> location;
1150   base::android::JavaIntArrayToIntVector(
1151       env, Java_AwContents_getLocationOnScreen(env, obj), &location);
1152   return gfx::Point(location[0], location[1]);
1153 }
1154 
ScrollContainerViewTo(const gfx::Vector2d & new_value)1155 void AwContents::ScrollContainerViewTo(const gfx::Vector2d& new_value) {
1156   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1157   JNIEnv* env = AttachCurrentThread();
1158   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1159   if (!obj)
1160     return;
1161   Java_AwContents_scrollContainerViewTo(env, obj, new_value.x(), new_value.y());
1162 }
1163 
UpdateScrollState(const gfx::Vector2d & max_scroll_offset,const gfx::SizeF & contents_size_dip,float page_scale_factor,float min_page_scale_factor,float max_page_scale_factor)1164 void AwContents::UpdateScrollState(const gfx::Vector2d& max_scroll_offset,
1165                                    const gfx::SizeF& contents_size_dip,
1166                                    float page_scale_factor,
1167                                    float min_page_scale_factor,
1168                                    float max_page_scale_factor) {
1169   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1170   JNIEnv* env = AttachCurrentThread();
1171   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1172   if (!obj)
1173     return;
1174   Java_AwContents_updateScrollState(
1175       env, obj, max_scroll_offset.x(), max_scroll_offset.y(),
1176       contents_size_dip.width(), contents_size_dip.height(), page_scale_factor,
1177       min_page_scale_factor, max_page_scale_factor);
1178 }
1179 
DidOverscroll(const gfx::Vector2d & overscroll_delta,const gfx::Vector2dF & overscroll_velocity)1180 void AwContents::DidOverscroll(const gfx::Vector2d& overscroll_delta,
1181                                const gfx::Vector2dF& overscroll_velocity) {
1182   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1183   JNIEnv* env = AttachCurrentThread();
1184   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1185   if (!obj)
1186     return;
1187   Java_AwContents_didOverscroll(env, obj, overscroll_delta.x(),
1188                                 overscroll_delta.y(), overscroll_velocity.x(),
1189                                 overscroll_velocity.y());
1190 }
1191 
CreateDrawable()1192 ui::TouchHandleDrawable* AwContents::CreateDrawable() {
1193   JNIEnv* env = AttachCurrentThread();
1194   const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1195   if (!obj)
1196     return nullptr;
1197   return reinterpret_cast<ui::TouchHandleDrawable*>(
1198       Java_AwContents_onCreateTouchHandle(env, obj));
1199 }
1200 
SetDipScale(JNIEnv * env,const JavaParamRef<jobject> & obj,jfloat dip_scale)1201 void AwContents::SetDipScale(JNIEnv* env,
1202                              const JavaParamRef<jobject>& obj,
1203                              jfloat dip_scale) {
1204   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1205   SetDipScaleInternal(dip_scale);
1206 }
1207 
IsDisplayingOpenWebContent(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj)1208 jboolean AwContents::IsDisplayingOpenWebContent(
1209     JNIEnv* env,
1210     const base::android::JavaParamRef<jobject>& obj) {
1211   return GetVisibilityInfo().IsDisplayingOpenWebContent();
1212 }
1213 
OnInputEvent(JNIEnv * env,const JavaParamRef<jobject> & obj)1214 void AwContents::OnInputEvent(JNIEnv* env, const JavaParamRef<jobject>& obj) {
1215   browser_view_renderer_.OnInputEvent();
1216 }
1217 
SetDipScaleInternal(float dip_scale)1218 void AwContents::SetDipScaleInternal(float dip_scale) {
1219   browser_view_renderer_.SetDipScale(dip_scale);
1220 }
1221 
ScrollTo(JNIEnv * env,const JavaParamRef<jobject> & obj,jint x,jint y)1222 void AwContents::ScrollTo(JNIEnv* env,
1223                           const JavaParamRef<jobject>& obj,
1224                           jint x,
1225                           jint y) {
1226   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1227   browser_view_renderer_.ScrollTo(gfx::Vector2d(x, y));
1228 }
1229 
RestoreScrollAfterTransition(JNIEnv * env,const JavaParamRef<jobject> & obj,jint x,jint y)1230 void AwContents::RestoreScrollAfterTransition(JNIEnv* env,
1231                                               const JavaParamRef<jobject>& obj,
1232                                               jint x,
1233                                               jint y) {
1234   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1235   browser_view_renderer_.RestoreScrollAfterTransition(gfx::Vector2d(x, y));
1236 }
1237 
SmoothScroll(JNIEnv * env,const JavaParamRef<jobject> & obj,jint target_x,jint target_y,jlong duration_ms)1238 void AwContents::SmoothScroll(JNIEnv* env,
1239                               const JavaParamRef<jobject>& obj,
1240                               jint target_x,
1241                               jint target_y,
1242                               jlong duration_ms) {
1243   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1244 
1245   float scale = browser_view_renderer_.page_scale_factor();
1246   if (!content::IsUseZoomForDSFEnabled())
1247     scale *= browser_view_renderer_.dip_scale();
1248 
1249   DCHECK_GE(duration_ms, 0);
1250   render_view_host_ext_->SmoothScroll(
1251       target_x / scale, target_y / scale,
1252       base::TimeDelta::FromMilliseconds(duration_ms));
1253 }
1254 
OnWebLayoutPageScaleFactorChanged(float page_scale_factor)1255 void AwContents::OnWebLayoutPageScaleFactorChanged(float page_scale_factor) {
1256   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1257   JNIEnv* env = AttachCurrentThread();
1258   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1259   if (!obj)
1260     return;
1261   Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj,
1262                                                     page_scale_factor);
1263 }
1264 
OnWebLayoutContentsSizeChanged(const gfx::Size & contents_size)1265 void AwContents::OnWebLayoutContentsSizeChanged(
1266     const gfx::Size& contents_size) {
1267   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1268   JNIEnv* env = AttachCurrentThread();
1269   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1270   if (!obj)
1271     return;
1272   gfx::Size contents_size_css =
1273       content::IsUseZoomForDSFEnabled()
1274           ? ScaleToRoundedSize(contents_size,
1275                                1 / browser_view_renderer_.dip_scale())
1276           : contents_size;
1277   Java_AwContents_onWebLayoutContentsSizeChanged(
1278       env, obj, contents_size_css.width(), contents_size_css.height());
1279 }
1280 
CapturePicture(JNIEnv * env,const JavaParamRef<jobject> & obj,int width,int height)1281 jlong AwContents::CapturePicture(JNIEnv* env,
1282                                  const JavaParamRef<jobject>& obj,
1283                                  int width,
1284                                  int height) {
1285   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1286   return reinterpret_cast<intptr_t>(
1287       new AwPicture(browser_view_renderer_.CapturePicture(width, height)));
1288 }
1289 
EnableOnNewPicture(JNIEnv * env,const JavaParamRef<jobject> & obj,jboolean enabled)1290 void AwContents::EnableOnNewPicture(JNIEnv* env,
1291                                     const JavaParamRef<jobject>& obj,
1292                                     jboolean enabled) {
1293   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1294   browser_view_renderer_.EnableOnNewPicture(enabled);
1295 }
1296 
1297 namespace {
InvokeVisualStateCallback(const JavaObjectWeakGlobalRef & java_ref,jlong request_id,const JavaRef<jobject> & callback,bool result)1298 void InvokeVisualStateCallback(const JavaObjectWeakGlobalRef& java_ref,
1299                                jlong request_id,
1300                                const JavaRef<jobject>& callback,
1301                                bool result) {
1302   JNIEnv* env = AttachCurrentThread();
1303   ScopedJavaLocalRef<jobject> obj = java_ref.get(env);
1304   if (!obj)
1305     return;
1306   Java_AwContents_invokeVisualStateCallback(env, obj, callback, request_id);
1307 }
1308 }  // namespace
1309 
InsertVisualStateCallback(JNIEnv * env,const JavaParamRef<jobject> & obj,jlong request_id,const JavaParamRef<jobject> & callback)1310 void AwContents::InsertVisualStateCallback(
1311     JNIEnv* env,
1312     const JavaParamRef<jobject>& obj,
1313     jlong request_id,
1314     const JavaParamRef<jobject>& callback) {
1315   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1316   web_contents_->GetMainFrame()->InsertVisualStateCallback(
1317       base::BindOnce(&InvokeVisualStateCallback, java_ref_, request_id,
1318                      ScopedJavaGlobalRef<jobject>(env, callback)));
1319 }
1320 
GetEffectivePriority(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj)1321 jint AwContents::GetEffectivePriority(
1322     JNIEnv* env,
1323     const base::android::JavaParamRef<jobject>& obj) {
1324   switch (
1325       web_contents_->GetMainFrame()->GetProcess()->GetEffectiveImportance()) {
1326     case content::ChildProcessImportance::NORMAL:
1327       return static_cast<jint>(RendererPriority::WAIVED);
1328     case content::ChildProcessImportance::MODERATE:
1329       return static_cast<jint>(RendererPriority::LOW);
1330     case content::ChildProcessImportance::IMPORTANT:
1331       return static_cast<jint>(RendererPriority::HIGH);
1332   }
1333   NOTREACHED();
1334   return 0;
1335 }
1336 
GetJsCommunicationHost()1337 JsCommunicationHost* AwContents::GetJsCommunicationHost() {
1338   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1339   if (!js_communication_host_.get()) {
1340     js_communication_host_ =
1341         std::make_unique<JsCommunicationHost>(web_contents_.get());
1342   }
1343   return js_communication_host_.get();
1344 }
1345 
AddDocumentStartJavaScript(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj,const base::android::JavaParamRef<jstring> & script,const base::android::JavaParamRef<jobjectArray> & allowed_origin_rules)1346 jint AwContents::AddDocumentStartJavaScript(
1347     JNIEnv* env,
1348     const base::android::JavaParamRef<jobject>& obj,
1349     const base::android::JavaParamRef<jstring>& script,
1350     const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules) {
1351   std::vector<std::string> native_allowed_origin_rule_strings;
1352   AppendJavaStringArrayToStringVector(env, allowed_origin_rules,
1353                                       &native_allowed_origin_rule_strings);
1354   auto result = GetJsCommunicationHost()->AddDocumentStartJavaScript(
1355       base::android::ConvertJavaStringToUTF16(env, script),
1356       native_allowed_origin_rule_strings);
1357   if (result.error_message) {
1358     env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
1359                   result.error_message->data());
1360     return -1;
1361   }
1362   DCHECK(result.script_id);
1363   return result.script_id.value();
1364 }
1365 
RemoveDocumentStartJavaScript(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj,jint script_id)1366 void AwContents::RemoveDocumentStartJavaScript(
1367     JNIEnv* env,
1368     const base::android::JavaParamRef<jobject>& obj,
1369     jint script_id) {
1370   GetJsCommunicationHost()->RemoveDocumentStartJavaScript(script_id);
1371 }
1372 
AddWebMessageListener(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj,const base::android::JavaParamRef<jobject> & listener,const base::android::JavaParamRef<jstring> & js_object_name,const base::android::JavaParamRef<jobjectArray> & allowed_origin_rules)1373 base::android::ScopedJavaLocalRef<jstring> AwContents::AddWebMessageListener(
1374     JNIEnv* env,
1375     const base::android::JavaParamRef<jobject>& obj,
1376     const base::android::JavaParamRef<jobject>& listener,
1377     const base::android::JavaParamRef<jstring>& js_object_name,
1378     const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules) {
1379   base::string16 native_js_object_name =
1380       base::android::ConvertJavaStringToUTF16(env, js_object_name);
1381   std::vector<std::string> native_allowed_origin_rule_strings;
1382   AppendJavaStringArrayToStringVector(env, allowed_origin_rules,
1383                                       &native_allowed_origin_rule_strings);
1384   const base::string16 error_message =
1385       GetJsCommunicationHost()->AddWebMessageHostFactory(
1386           std::make_unique<AwWebMessageHostFactory>(listener),
1387           native_js_object_name, native_allowed_origin_rule_strings);
1388   if (error_message.empty())
1389     return nullptr;
1390   return base::android::ConvertUTF16ToJavaString(env, error_message);
1391 }
1392 
RemoveWebMessageListener(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj,const base::android::JavaParamRef<jstring> & js_object_name)1393 void AwContents::RemoveWebMessageListener(
1394     JNIEnv* env,
1395     const base::android::JavaParamRef<jobject>& obj,
1396     const base::android::JavaParamRef<jstring>& js_object_name) {
1397   GetJsCommunicationHost()->RemoveWebMessageHostFactory(
1398       ConvertJavaStringToUTF16(env, js_object_name));
1399 }
1400 
GetJsObjectsInfo(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj,const base::android::JavaParamRef<jclass> & clazz)1401 base::android::ScopedJavaLocalRef<jobjectArray> AwContents::GetJsObjectsInfo(
1402     JNIEnv* env,
1403     const base::android::JavaParamRef<jobject>& obj,
1404     const base::android::JavaParamRef<jclass>& clazz) {
1405   if (js_communication_host_.get()) {
1406     return AwWebMessageHostFactory::GetWebMessageListenerInfo(
1407         GetJsCommunicationHost(), env, clazz);
1408   }
1409   return nullptr;
1410 }
1411 
ClearView(JNIEnv * env,const JavaParamRef<jobject> & obj)1412 void AwContents::ClearView(JNIEnv* env, const JavaParamRef<jobject>& obj) {
1413   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1414   browser_view_renderer_.ClearView();
1415 }
1416 
SetExtraHeadersForUrl(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jstring> & url,const JavaParamRef<jstring> & jextra_headers)1417 void AwContents::SetExtraHeadersForUrl(
1418     JNIEnv* env,
1419     const JavaParamRef<jobject>& obj,
1420     const JavaParamRef<jstring>& url,
1421     const JavaParamRef<jstring>& jextra_headers) {
1422   std::string extra_headers;
1423   if (jextra_headers)
1424     extra_headers = ConvertJavaStringToUTF8(env, jextra_headers);
1425   AwResourceContext* resource_context = static_cast<AwResourceContext*>(
1426       AwBrowserContext::FromWebContents(web_contents_.get())
1427           ->GetResourceContext());
1428   resource_context->SetExtraHeaders(GURL(ConvertJavaStringToUTF8(env, url)),
1429                                     extra_headers);
1430 }
1431 
SetJsOnlineProperty(JNIEnv * env,const JavaParamRef<jobject> & obj,jboolean network_up)1432 void AwContents::SetJsOnlineProperty(JNIEnv* env,
1433                                      const JavaParamRef<jobject>& obj,
1434                                      jboolean network_up) {
1435   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1436   AwRenderProcess* aw_render_process =
1437       AwRenderProcess::GetInstanceForRenderProcessHost(
1438           web_contents_->GetMainFrame()->GetProcess());
1439 
1440   aw_render_process->SetJsOnlineProperty(network_up);
1441 }
1442 
TrimMemory(JNIEnv * env,const JavaParamRef<jobject> & obj,jint level,jboolean visible)1443 void AwContents::TrimMemory(JNIEnv* env,
1444                             const JavaParamRef<jobject>& obj,
1445                             jint level,
1446                             jboolean visible) {
1447   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1448   // Constants from Android ComponentCallbacks2.
1449   enum {
1450     TRIM_MEMORY_RUNNING_LOW = 10,
1451     TRIM_MEMORY_UI_HIDDEN = 20,
1452     TRIM_MEMORY_BACKGROUND = 40,
1453     TRIM_MEMORY_MODERATE = 60,
1454   };
1455 
1456   // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
1457   // it does not indicate memory pressure, but merely that the app is
1458   // backgrounded.
1459   if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
1460     return;
1461 
1462   // Do not release resources on view we expect to get DrawGL soon.
1463   if (level < TRIM_MEMORY_BACKGROUND && visible)
1464     return;
1465 
1466   browser_view_renderer_.TrimMemory();
1467 }
1468 
GrantFileSchemeAccesstoChildProcess(JNIEnv * env,const JavaParamRef<jobject> & obj)1469 void AwContents::GrantFileSchemeAccesstoChildProcess(
1470     JNIEnv* env,
1471     const JavaParamRef<jobject>& obj) {
1472   content::ChildProcessSecurityPolicy::GetInstance()->GrantRequestScheme(
1473       web_contents_->GetMainFrame()->GetProcess()->GetID(), url::kFileScheme);
1474 }
1475 
ResumeLoadingCreatedPopupWebContents(JNIEnv * env,const JavaParamRef<jobject> & obj)1476 void AwContents::ResumeLoadingCreatedPopupWebContents(
1477     JNIEnv* env,
1478     const JavaParamRef<jobject>& obj) {
1479   web_contents_->ResumeLoadingCreatedWebContents();
1480 }
1481 
GetAutofillProvider(JNIEnv * env,const base::android::JavaParamRef<jobject> & obj)1482 jlong AwContents::GetAutofillProvider(
1483     JNIEnv* env,
1484     const base::android::JavaParamRef<jobject>& obj) {
1485   return reinterpret_cast<jlong>(autofill_provider_.get());
1486 }
1487 
JNI_AwContents_SetShouldDownloadFavicons(JNIEnv * env)1488 void JNI_AwContents_SetShouldDownloadFavicons(JNIEnv* env) {
1489   g_should_download_favicons = true;
1490 }
1491 
RenderViewHostChanged(content::RenderViewHost * old_host,content::RenderViewHost * new_host)1492 void AwContents::RenderViewHostChanged(content::RenderViewHost* old_host,
1493                                        content::RenderViewHost* new_host) {
1494   DCHECK(new_host);
1495 
1496   // At this point, the current RVH may or may not contain a compositor. So
1497   // compositor_ may be nullptr, in which case
1498   // BrowserViewRenderer::DidInitializeCompositor() callback is time when the
1499   // new compositor is constructed.
1500   browser_view_renderer_.SetActiveFrameSinkId(
1501       new_host->GetWidget()->GetFrameSinkId());
1502 }
1503 
DidFinishNavigation(content::NavigationHandle * navigation_handle)1504 void AwContents::DidFinishNavigation(
1505     content::NavigationHandle* navigation_handle) {
1506   // If this request was blocked in any way, broadcast an error.
1507   net::Error error_code = navigation_handle->GetNetErrorCode();
1508 
1509   bool navigation_successful_and_scheme_http_or_https =
1510       ((error_code == net::OK) &&
1511        navigation_handle->GetURL().SchemeIsHTTPOrHTTPS());
1512   if (navigation_successful_and_scheme_http_or_https != scheme_http_or_https_) {
1513     scheme_http_or_https_ = navigation_successful_and_scheme_http_or_https;
1514     AwBrowserProcess::GetInstance()
1515         ->visibility_metrics_logger()
1516         ->ClientVisibilityChanged(this);
1517   }
1518 
1519   if (!net::IsRequestBlockedError(error_code) &&
1520       error_code != net::ERR_ABORTED) {
1521     return;
1522   }
1523 
1524   // We do not call OnReceivedError for requests that were blocked due to an
1525   // interstitial showing. OnReceivedError is handled directly by the blocking
1526   // page for interstitials.
1527   if (web_contents_) {
1528     // We can't be showing an interstitial if there is no web_contents.
1529     security_interstitials::SecurityInterstitialTabHelper*
1530         security_interstitial_tab_helper = security_interstitials::
1531             SecurityInterstitialTabHelper::FromWebContents(web_contents_.get());
1532     if (security_interstitial_tab_helper &&
1533         (security_interstitial_tab_helper->IsInterstitialPendingForNavigation(
1534              navigation_handle->GetNavigationId()) ||
1535          security_interstitial_tab_helper->IsDisplayingInterstitial())) {
1536       return;
1537     }
1538   }
1539 
1540   AwContentsClientBridge* client =
1541       AwContentsClientBridge::FromWebContents(web_contents_.get());
1542   if (!client)
1543     return;
1544 
1545   AwWebResourceRequest request(navigation_handle->GetURL().spec(),
1546                                navigation_handle->IsPost() ? "POST" : "GET",
1547                                navigation_handle->IsInMainFrame(),
1548                                navigation_handle->HasUserGesture(),
1549                                net::HttpRequestHeaders());
1550   request.is_renderer_initiated = navigation_handle->IsRendererInitiated();
1551   client->OnReceivedError(request, error_code, false, false);
1552 }
1553 
CanShowInterstitial()1554 bool AwContents::CanShowInterstitial() {
1555   JNIEnv* env = AttachCurrentThread();
1556   const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1557   if (!obj)
1558     return false;
1559   return Java_AwContents_canShowInterstitial(env, obj);
1560 }
1561 
GetErrorUiType()1562 int AwContents::GetErrorUiType() {
1563   JNIEnv* env = AttachCurrentThread();
1564   const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1565   if (!obj)
1566     return false;
1567   return Java_AwContents_getErrorUiType(env, obj);
1568 }
1569 
GetVisibilityInfo()1570 VisibilityMetricsLogger::VisibilityInfo AwContents::GetVisibilityInfo() {
1571   return VisibilityMetricsLogger::VisibilityInfo{
1572       browser_view_renderer_.attached_to_window(),
1573       browser_view_renderer_.view_visible(),
1574       browser_view_renderer_.window_visible(), scheme_http_or_https_};
1575 }
1576 
RendererUnresponsive(content::RenderProcessHost * render_process_host)1577 void AwContents::RendererUnresponsive(
1578     content::RenderProcessHost* render_process_host) {
1579   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1580   JNIEnv* env = AttachCurrentThread();
1581   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1582   if (!obj)
1583     return;
1584 
1585   AwRenderProcess* aw_render_process =
1586       AwRenderProcess::GetInstanceForRenderProcessHost(render_process_host);
1587   Java_AwContents_onRendererUnresponsive(env, obj,
1588                                          aw_render_process->GetJavaObject());
1589 }
1590 
RendererResponsive(content::RenderProcessHost * render_process_host)1591 void AwContents::RendererResponsive(
1592     content::RenderProcessHost* render_process_host) {
1593   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1594   JNIEnv* env = AttachCurrentThread();
1595   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1596   if (!obj)
1597     return;
1598 
1599   AwRenderProcess* aw_render_process =
1600       AwRenderProcess::GetInstanceForRenderProcessHost(render_process_host);
1601   Java_AwContents_onRendererResponsive(env, obj,
1602                                        aw_render_process->GetJavaObject());
1603 }
1604 
OnRenderProcessGone(int child_process_id,bool crashed)1605 AwContents::RenderProcessGoneResult AwContents::OnRenderProcessGone(
1606     int child_process_id,
1607     bool crashed) {
1608   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1609   JNIEnv* env = AttachCurrentThread();
1610   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1611   if (!obj)
1612     return RenderProcessGoneResult::kHandled;
1613 
1614   bool result =
1615       Java_AwContents_onRenderProcessGone(env, obj, child_process_id, crashed);
1616 
1617   if (HasException(env))
1618     return RenderProcessGoneResult::kException;
1619 
1620   return result ? RenderProcessGoneResult::kHandled
1621                 : RenderProcessGoneResult::kUnhandled;
1622 }
1623 
1624 }  // namespace android_webview
1625