OLD | NEW |
| (Empty) |
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/native/aw_contents.h" | |
6 | |
7 #include <limits> | |
8 #include <utility> | |
9 | |
10 #include "android_webview/browser/aw_browser_context.h" | |
11 #include "android_webview/browser/aw_browser_main_parts.h" | |
12 #include "android_webview/browser/aw_resource_context.h" | |
13 #include "android_webview/browser/browser_view_renderer.h" | |
14 #include "android_webview/browser/child_frame.h" | |
15 #include "android_webview/browser/deferred_gpu_command_service.h" | |
16 #include "android_webview/browser/net_disk_cache_remover.h" | |
17 #include "android_webview/browser/render_thread_manager.h" | |
18 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_dele
gate.h" | |
19 #include "android_webview/browser/scoped_app_gl_state_restore.h" | |
20 #include "android_webview/common/aw_hit_test_data.h" | |
21 #include "android_webview/common/aw_switches.h" | |
22 #include "android_webview/common/devtools_instrumentation.h" | |
23 #include "android_webview/native/aw_autofill_client.h" | |
24 #include "android_webview/native/aw_contents_client_bridge.h" | |
25 #include "android_webview/native/aw_contents_io_thread_client_impl.h" | |
26 #include "android_webview/native/aw_contents_lifecycle_notifier.h" | |
27 #include "android_webview/native/aw_gl_functor.h" | |
28 #include "android_webview/native/aw_pdf_exporter.h" | |
29 #include "android_webview/native/aw_picture.h" | |
30 #include "android_webview/native/aw_renderer_priority_manager.h" | |
31 #include "android_webview/native/aw_web_contents_delegate.h" | |
32 #include "android_webview/native/java_browser_view_renderer_helper.h" | |
33 #include "android_webview/native/permission/aw_permission_request.h" | |
34 #include "android_webview/native/permission/permission_request_handler.h" | |
35 #include "android_webview/native/permission/simple_permission_request.h" | |
36 #include "android_webview/native/state_serializer.h" | |
37 #include "android_webview/public/browser/draw_gl.h" | |
38 #include "base/android/jni_android.h" | |
39 #include "base/android/jni_array.h" | |
40 #include "base/android/jni_string.h" | |
41 #include "base/android/locale_utils.h" | |
42 #include "base/android/scoped_java_ref.h" | |
43 #include "base/atomicops.h" | |
44 #include "base/bind.h" | |
45 #include "base/callback.h" | |
46 #include "base/command_line.h" | |
47 #include "base/location.h" | |
48 #include "base/memory/memory_pressure_listener.h" | |
49 #include "base/memory/ptr_util.h" | |
50 #include "base/pickle.h" | |
51 #include "base/single_thread_task_runner.h" | |
52 #include "base/strings/string16.h" | |
53 #include "base/supports_user_data.h" | |
54 #include "base/threading/thread_task_runner_handle.h" | |
55 #include "components/autofill/content/browser/content_autofill_driver_factory.h" | |
56 #include "components/autofill/core/browser/autofill_manager.h" | |
57 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" | |
58 #include "components/navigation_interception/intercept_navigation_delegate.h" | |
59 #include "content/public/browser/android/content_view_core.h" | |
60 #include "content/public/browser/android/synchronous_compositor.h" | |
61 #include "content/public/browser/browser_thread.h" | |
62 #include "content/public/browser/child_process_security_policy.h" | |
63 #include "content/public/browser/favicon_status.h" | |
64 #include "content/public/browser/interstitial_page.h" | |
65 #include "content/public/browser/message_port_provider.h" | |
66 #include "content/public/browser/navigation_entry.h" | |
67 #include "content/public/browser/render_frame_host.h" | |
68 #include "content/public/browser/render_process_host.h" | |
69 #include "content/public/browser/render_view_host.h" | |
70 #include "content/public/browser/render_widget_host.h" | |
71 #include "content/public/browser/render_widget_host_iterator.h" | |
72 #include "content/public/browser/ssl_status.h" | |
73 #include "content/public/browser/web_contents.h" | |
74 #include "content/public/common/mhtml_generation_params.h" | |
75 #include "content/public/common/renderer_preferences.h" | |
76 #include "jni/AwContents_jni.h" | |
77 #include "net/base/auth.h" | |
78 #include "net/cert/x509_certificate.h" | |
79 #include "third_party/skia/include/core/SkPicture.h" | |
80 #include "ui/gfx/android/java_bitmap.h" | |
81 #include "ui/gfx/geometry/rect_f.h" | |
82 #include "ui/gfx/geometry/size.h" | |
83 #include "ui/gfx/image/image.h" | |
84 struct AwDrawSWFunctionTable; | |
85 | |
86 using autofill::ContentAutofillDriverFactory; | |
87 using autofill::AutofillManager; | |
88 using base::android::AttachCurrentThread; | |
89 using base::android::ConvertJavaStringToUTF16; | |
90 using base::android::ConvertJavaStringToUTF8; | |
91 using base::android::ConvertUTF16ToJavaString; | |
92 using base::android::ConvertUTF8ToJavaString; | |
93 using base::android::JavaParamRef; | |
94 using base::android::JavaRef; | |
95 using base::android::ScopedJavaGlobalRef; | |
96 using base::android::ScopedJavaLocalRef; | |
97 using navigation_interception::InterceptNavigationDelegate; | |
98 using content::BrowserThread; | |
99 using content::ContentViewCore; | |
100 using content::RenderFrameHost; | |
101 using content::WebContents; | |
102 | |
103 namespace android_webview { | |
104 | |
105 namespace { | |
106 | |
107 bool g_should_download_favicons = false; | |
108 | |
109 bool g_force_auxiliary_bitmap_rendering = false; | |
110 | |
111 std::string g_locale; | |
112 | |
113 std::string g_locale_list; | |
114 | |
115 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey; | |
116 const void* kComputedRendererPriorityUserDataKey = | |
117 &kComputedRendererPriorityUserDataKey; | |
118 | |
119 class AwContentsUserData : public base::SupportsUserData::Data { | |
120 public: | |
121 explicit AwContentsUserData(AwContents* ptr) : contents_(ptr) {} | |
122 | |
123 static AwContents* GetContents(WebContents* web_contents) { | |
124 if (!web_contents) | |
125 return NULL; | |
126 AwContentsUserData* data = static_cast<AwContentsUserData*>( | |
127 web_contents->GetUserData(kAwContentsUserDataKey)); | |
128 return data ? data->contents_ : NULL; | |
129 } | |
130 | |
131 private: | |
132 AwContents* contents_; | |
133 }; | |
134 | |
135 base::subtle::Atomic32 g_instance_count = 0; | |
136 | |
137 } // namespace | |
138 | |
139 // static | |
140 AwContents* AwContents::FromWebContents(WebContents* web_contents) { | |
141 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
142 return AwContentsUserData::GetContents(web_contents); | |
143 } | |
144 | |
145 // static | |
146 AwContents* AwContents::FromID(int render_process_id, int render_view_id) { | |
147 content::RenderViewHost* rvh = | |
148 content::RenderViewHost::FromID(render_process_id, render_view_id); | |
149 if (!rvh) return NULL; | |
150 content::WebContents* web_contents = | |
151 content::WebContents::FromRenderViewHost(rvh); | |
152 if (!web_contents) return NULL; | |
153 return FromWebContents(web_contents); | |
154 } | |
155 | |
156 // static | |
157 void UpdateDefaultLocale(JNIEnv* env, | |
158 const JavaParamRef<jclass>&, | |
159 const JavaParamRef<jstring>& locale, | |
160 const JavaParamRef<jstring>& locale_list) { | |
161 g_locale = ConvertJavaStringToUTF8(env, locale); | |
162 g_locale_list = ConvertJavaStringToUTF8(env, locale_list); | |
163 } | |
164 | |
165 // static | |
166 std::string AwContents::GetLocale() { | |
167 return g_locale; | |
168 } | |
169 | |
170 // static | |
171 std::string AwContents::GetLocaleList() { | |
172 return g_locale_list; | |
173 } | |
174 | |
175 // static | |
176 AwBrowserPermissionRequestDelegate* AwBrowserPermissionRequestDelegate::FromID( | |
177 int render_process_id, int render_frame_id) { | |
178 AwContents* aw_contents = AwContents::FromWebContents( | |
179 content::WebContents::FromRenderFrameHost( | |
180 content::RenderFrameHost::FromID(render_process_id, | |
181 render_frame_id))); | |
182 return aw_contents; | |
183 } | |
184 | |
185 // static | |
186 AwSafeBrowsingUIManager::UIManagerClient* | |
187 AwSafeBrowsingUIManager::UIManagerClient::FromWebContents( | |
188 WebContents* web_contents) { | |
189 return AwContents::FromWebContents(web_contents); | |
190 } | |
191 | |
192 // static | |
193 AwRenderProcessGoneDelegate* AwRenderProcessGoneDelegate::FromWebContents( | |
194 content::WebContents* web_contents) { | |
195 return AwContents::FromWebContents(web_contents); | |
196 } | |
197 | |
198 AwContents::AwContents(std::unique_ptr<WebContents> web_contents) | |
199 : content::WebContentsObserver(web_contents.get()), | |
200 functor_(nullptr), | |
201 browser_view_renderer_( | |
202 this, | |
203 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)), | |
204 web_contents_(std::move(web_contents)), | |
205 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()), | |
206 renderer_requested_priority_( | |
207 AwRendererPriorityManager::RENDERER_PRIORITY_HIGH), | |
208 renderer_priority_waived_when_not_visible_(false) { | |
209 base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1); | |
210 icon_helper_.reset(new IconHelper(web_contents_.get())); | |
211 icon_helper_->SetListener(this); | |
212 web_contents_->SetUserData(android_webview::kAwContentsUserDataKey, | |
213 base::MakeUnique<AwContentsUserData>(this)); | |
214 browser_view_renderer_.RegisterWithWebContents(web_contents_.get()); | |
215 | |
216 CompositorID compositor_id; | |
217 if (web_contents_->GetRenderProcessHost() && | |
218 web_contents_->GetRenderViewHost()) { | |
219 compositor_id.process_id = web_contents_->GetRenderProcessHost()->GetID(); | |
220 compositor_id.routing_id = | |
221 web_contents_->GetRenderViewHost()->GetRoutingID(); | |
222 } | |
223 | |
224 browser_view_renderer_.SetActiveCompositorID(compositor_id); | |
225 render_view_host_ext_.reset( | |
226 new AwRenderViewHostExt(this, web_contents_.get())); | |
227 | |
228 permission_request_handler_.reset( | |
229 new PermissionRequestHandler(this, web_contents_.get())); | |
230 | |
231 AwAutofillClient* autofill_manager_delegate = | |
232 AwAutofillClient::FromWebContents(web_contents_.get()); | |
233 if (autofill_manager_delegate) | |
234 InitAutofillIfNecessary(autofill_manager_delegate->GetSaveFormData()); | |
235 content::SynchronousCompositor::SetClientForWebContents( | |
236 web_contents_.get(), &browser_view_renderer_); | |
237 UpdateRendererPriority(); | |
238 web_contents_->GetRenderProcessHost()->AddObserver(this); | |
239 AwContentsLifecycleNotifier::OnWebViewCreated(); | |
240 } | |
241 | |
242 void AwContents::SetJavaPeers( | |
243 JNIEnv* env, | |
244 const JavaParamRef<jobject>& obj, | |
245 const JavaParamRef<jobject>& aw_contents, | |
246 const JavaParamRef<jobject>& web_contents_delegate, | |
247 const JavaParamRef<jobject>& contents_client_bridge, | |
248 const JavaParamRef<jobject>& io_thread_client, | |
249 const JavaParamRef<jobject>& intercept_navigation_delegate) { | |
250 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
251 // The |aw_content| param is technically spurious as it duplicates |obj| but | |
252 // is passed over anyway to make the binding more explicit. | |
253 java_ref_ = JavaObjectWeakGlobalRef(env, aw_contents); | |
254 | |
255 web_contents_delegate_.reset( | |
256 new AwWebContentsDelegate(env, web_contents_delegate)); | |
257 web_contents_->SetDelegate(web_contents_delegate_.get()); | |
258 | |
259 contents_client_bridge_.reset( | |
260 new AwContentsClientBridge(env, contents_client_bridge)); | |
261 AwContentsClientBridgeBase::Associate(web_contents_.get(), | |
262 contents_client_bridge_.get()); | |
263 | |
264 AwContentsIoThreadClientImpl::Associate(web_contents_.get(), | |
265 io_thread_client); | |
266 | |
267 InterceptNavigationDelegate::Associate( | |
268 web_contents_.get(), base::MakeUnique<InterceptNavigationDelegate>( | |
269 env, intercept_navigation_delegate)); | |
270 | |
271 // Finally, having setup the associations, release any deferred requests | |
272 for (content::RenderFrameHost* rfh : web_contents_->GetAllFrames()) { | |
273 int render_process_id = rfh->GetProcess()->GetID(); | |
274 int render_frame_id = rfh->GetRoutingID(); | |
275 AwResourceDispatcherHostDelegate::OnIoThreadClientReady(render_process_id, | |
276 render_frame_id); | |
277 } | |
278 } | |
279 | |
280 void AwContents::SetSaveFormData(bool enabled) { | |
281 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
282 InitAutofillIfNecessary(enabled); | |
283 // We need to check for the existence, since autofill_manager_delegate | |
284 // may not be created when the setting is false. | |
285 if (AwAutofillClient::FromWebContents(web_contents_.get())) { | |
286 AwAutofillClient::FromWebContents(web_contents_.get())-> | |
287 SetSaveFormData(enabled); | |
288 } | |
289 } | |
290 | |
291 void AwContents::InitAutofillIfNecessary(bool enabled) { | |
292 // Do not initialize if the feature is not enabled. | |
293 if (!enabled) | |
294 return; | |
295 // Check if the autofill driver factory already exists. | |
296 content::WebContents* web_contents = web_contents_.get(); | |
297 if (ContentAutofillDriverFactory::FromWebContents(web_contents)) | |
298 return; | |
299 | |
300 AwAutofillClient::CreateForWebContents(web_contents); | |
301 ContentAutofillDriverFactory::CreateForWebContentsAndDelegate( | |
302 web_contents, AwAutofillClient::FromWebContents(web_contents), | |
303 base::android::GetDefaultLocaleString(), | |
304 AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER); | |
305 } | |
306 | |
307 void AwContents::SetAwAutofillClient(const JavaRef<jobject>& client) { | |
308 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
309 JNIEnv* env = AttachCurrentThread(); | |
310 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
311 if (obj.is_null()) | |
312 return; | |
313 Java_AwContents_setAwAutofillClient(env, obj, client); | |
314 } | |
315 | |
316 AwContents::~AwContents() { | |
317 DCHECK_EQ(this, AwContents::FromWebContents(web_contents_.get())); | |
318 web_contents_->GetRenderProcessHost()->RemoveObserver(this); | |
319 UpdateRendererPriority(AwRendererPriorityManager::RENDERER_PRIORITY_WAIVED); | |
320 web_contents_->RemoveUserData(kAwContentsUserDataKey); | |
321 if (find_helper_.get()) | |
322 find_helper_->SetListener(NULL); | |
323 if (icon_helper_.get()) | |
324 icon_helper_->SetListener(NULL); | |
325 base::subtle::Atomic32 instance_count = | |
326 base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, -1); | |
327 // When the last WebView is destroyed free all discardable memory allocated by | |
328 // Chromium, because the app process may continue to run for a long time | |
329 // without ever using another WebView. | |
330 if (instance_count == 0) { | |
331 // TODO(timvolodine): consider moving NotifyMemoryPressure to | |
332 // AwContentsLifecycleNotifier (crbug.com/522988). | |
333 base::MemoryPressureListener::NotifyMemoryPressure( | |
334 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); | |
335 } | |
336 SetAwGLFunctor(nullptr); | |
337 AwContentsLifecycleNotifier::OnWebViewDestroyed(); | |
338 } | |
339 | |
340 base::android::ScopedJavaLocalRef<jobject> AwContents::GetWebContents( | |
341 JNIEnv* env, | |
342 const JavaParamRef<jobject>& obj) { | |
343 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
344 DCHECK(web_contents_); | |
345 if (!web_contents_) | |
346 return base::android::ScopedJavaLocalRef<jobject>(); | |
347 | |
348 return web_contents_->GetJavaWebContents(); | |
349 } | |
350 | |
351 void AwContents::SetAwGLFunctor(AwGLFunctor* functor) { | |
352 if (functor == functor_) { | |
353 return; | |
354 } | |
355 functor_ = functor; | |
356 if (functor_) { | |
357 browser_view_renderer_.SetCurrentCompositorFrameConsumer( | |
358 functor_->GetCompositorFrameConsumer()); | |
359 } else { | |
360 browser_view_renderer_.SetCurrentCompositorFrameConsumer(nullptr); | |
361 } | |
362 } | |
363 | |
364 void AwContents::SetAwGLFunctor(JNIEnv* env, | |
365 const base::android::JavaParamRef<jobject>& obj, | |
366 jlong gl_functor) { | |
367 SetAwGLFunctor(reinterpret_cast<AwGLFunctor*>(gl_functor)); | |
368 } | |
369 | |
370 void AwContents::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { | |
371 java_ref_.reset(); | |
372 delete this; | |
373 } | |
374 | |
375 static jlong Init(JNIEnv* env, | |
376 const JavaParamRef<jclass>&, | |
377 const JavaParamRef<jobject>& browser_context) { | |
378 // TODO(joth): Use |browser_context| to get the native BrowserContext, rather | |
379 // than hard-code the default instance lookup here. | |
380 std::unique_ptr<WebContents> web_contents(content::WebContents::Create( | |
381 content::WebContents::CreateParams(AwBrowserContext::GetDefault()))); | |
382 // Return an 'uninitialized' instance; most work is deferred until the | |
383 // subsequent SetJavaPeers() call. | |
384 return reinterpret_cast<intptr_t>(new AwContents(std::move(web_contents))); | |
385 } | |
386 | |
387 static void SetForceAuxiliaryBitmapRendering( | |
388 JNIEnv* env, | |
389 const JavaParamRef<jclass>&, | |
390 jboolean force_auxiliary_bitmap_rendering) { | |
391 g_force_auxiliary_bitmap_rendering = force_auxiliary_bitmap_rendering; | |
392 } | |
393 | |
394 static void SetAwDrawSWFunctionTable(JNIEnv* env, | |
395 const JavaParamRef<jclass>&, | |
396 jlong function_table) { | |
397 RasterHelperSetAwDrawSWFunctionTable( | |
398 reinterpret_cast<AwDrawSWFunctionTable*>(function_table)); | |
399 } | |
400 | |
401 static void SetAwDrawGLFunctionTable(JNIEnv* env, | |
402 const JavaParamRef<jclass>&, | |
403 jlong function_table) {} | |
404 | |
405 // static | |
406 jint GetNativeInstanceCount(JNIEnv* env, const JavaParamRef<jclass>&) { | |
407 return base::subtle::NoBarrier_Load(&g_instance_count); | |
408 } | |
409 | |
410 namespace { | |
411 void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message, | |
412 bool has_images) { | |
413 Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(), has_images, | |
414 message); | |
415 } | |
416 } // namespace | |
417 | |
418 void AwContents::DocumentHasImages(JNIEnv* env, | |
419 const JavaParamRef<jobject>& obj, | |
420 const JavaParamRef<jobject>& message) { | |
421 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
422 ScopedJavaGlobalRef<jobject> j_message; | |
423 j_message.Reset(env, message); | |
424 render_view_host_ext_->DocumentHasImages( | |
425 base::Bind(&DocumentHasImagesCallback, j_message)); | |
426 } | |
427 | |
428 namespace { | |
429 void GenerateMHTMLCallback(const JavaRef<jobject>& callback, | |
430 const base::FilePath& path, | |
431 int64_t size) { | |
432 JNIEnv* env = AttachCurrentThread(); | |
433 // Android files are UTF8, so the path conversion below is safe. | |
434 Java_AwContents_generateMHTMLCallback( | |
435 env, ConvertUTF8ToJavaString(env, path.AsUTF8Unsafe()), size, callback); | |
436 } | |
437 } // namespace | |
438 | |
439 void AwContents::GenerateMHTML(JNIEnv* env, | |
440 const JavaParamRef<jobject>& obj, | |
441 const JavaParamRef<jstring>& jpath, | |
442 const JavaParamRef<jobject>& callback) { | |
443 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
444 base::FilePath target_path(ConvertJavaStringToUTF8(env, jpath)); | |
445 web_contents_->GenerateMHTML( | |
446 content::MHTMLGenerationParams(target_path), | |
447 base::Bind(&GenerateMHTMLCallback, | |
448 ScopedJavaGlobalRef<jobject>(env, callback), target_path)); | |
449 } | |
450 | |
451 void AwContents::CreatePdfExporter(JNIEnv* env, | |
452 const JavaParamRef<jobject>& obj, | |
453 const JavaParamRef<jobject>& pdfExporter) { | |
454 pdf_exporter_.reset( | |
455 new AwPdfExporter(env, | |
456 pdfExporter, | |
457 web_contents_.get())); | |
458 } | |
459 | |
460 bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler, | |
461 const std::string& host, | |
462 const std::string& realm) { | |
463 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
464 JNIEnv* env = AttachCurrentThread(); | |
465 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
466 if (obj.is_null()) | |
467 return false; | |
468 | |
469 ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host); | |
470 ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm); | |
471 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( | |
472 "onReceivedHttpAuthRequest"); | |
473 Java_AwContents_onReceivedHttpAuthRequest(env, obj, handler, jhost, jrealm); | |
474 return true; | |
475 } | |
476 | |
477 void AwContents::SetOffscreenPreRaster(bool enabled) { | |
478 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
479 browser_view_renderer_.SetOffscreenPreRaster(enabled); | |
480 } | |
481 | |
482 void AwContents::AddVisitedLinks( | |
483 JNIEnv* env, | |
484 const JavaParamRef<jobject>& obj, | |
485 const JavaParamRef<jobjectArray>& jvisited_links) { | |
486 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
487 std::vector<base::string16> visited_link_strings; | |
488 base::android::AppendJavaStringArrayToStringVector( | |
489 env, jvisited_links, &visited_link_strings); | |
490 | |
491 std::vector<GURL> visited_link_gurls; | |
492 std::vector<base::string16>::const_iterator itr; | |
493 for (itr = visited_link_strings.begin(); itr != visited_link_strings.end(); | |
494 ++itr) { | |
495 visited_link_gurls.push_back(GURL(*itr)); | |
496 } | |
497 | |
498 AwBrowserContext::FromWebContents(web_contents_.get()) | |
499 ->AddVisitedURLs(visited_link_gurls); | |
500 } | |
501 | |
502 bool RegisterAwContents(JNIEnv* env) { | |
503 return RegisterNativesImpl(env); | |
504 } | |
505 | |
506 namespace { | |
507 | |
508 void ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef& java_ref, | |
509 const GURL& origin) { | |
510 JNIEnv* env = AttachCurrentThread(); | |
511 ScopedJavaLocalRef<jobject> j_ref = java_ref.get(env); | |
512 if (j_ref.obj()) { | |
513 ScopedJavaLocalRef<jstring> j_origin( | |
514 ConvertUTF8ToJavaString(env, origin.spec())); | |
515 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( | |
516 "onGeolocationPermissionsShowPrompt"); | |
517 Java_AwContents_onGeolocationPermissionsShowPrompt(env, j_ref, j_origin); | |
518 } | |
519 } | |
520 | |
521 void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref, | |
522 const GURL& origin) { | |
523 JNIEnv* env = AttachCurrentThread(); | |
524 if (java_ref.get(env).obj()) { | |
525 content::BrowserThread::PostTask( | |
526 content::BrowserThread::UI, | |
527 FROM_HERE, | |
528 base::Bind(&ShowGeolocationPromptHelperTask, | |
529 java_ref, | |
530 origin)); | |
531 } | |
532 } | |
533 | |
534 } // anonymous namespace | |
535 | |
536 void AwContents::ShowGeolocationPrompt(const GURL& requesting_frame, | |
537 base::Callback<void(bool)> callback) { | |
538 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
539 | |
540 GURL origin = requesting_frame.GetOrigin(); | |
541 bool show_prompt = pending_geolocation_prompts_.empty(); | |
542 pending_geolocation_prompts_.push_back(OriginCallback(origin, callback)); | |
543 if (show_prompt) { | |
544 ShowGeolocationPromptHelper(java_ref_, origin); | |
545 } | |
546 } | |
547 | |
548 // Invoked from Java | |
549 void AwContents::InvokeGeolocationCallback( | |
550 JNIEnv* env, | |
551 const JavaParamRef<jobject>& obj, | |
552 jboolean value, | |
553 const JavaParamRef<jstring>& origin) { | |
554 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
555 if (pending_geolocation_prompts_.empty()) | |
556 return; | |
557 | |
558 GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin)); | |
559 if (callback_origin.GetOrigin() == | |
560 pending_geolocation_prompts_.front().first) { | |
561 pending_geolocation_prompts_.front().second.Run(value); | |
562 pending_geolocation_prompts_.pop_front(); | |
563 if (!pending_geolocation_prompts_.empty()) { | |
564 ShowGeolocationPromptHelper(java_ref_, | |
565 pending_geolocation_prompts_.front().first); | |
566 } | |
567 } | |
568 } | |
569 | |
570 void AwContents::HideGeolocationPrompt(const GURL& origin) { | |
571 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
572 bool removed_current_outstanding_callback = false; | |
573 std::list<OriginCallback>::iterator it = pending_geolocation_prompts_.begin(); | |
574 while (it != pending_geolocation_prompts_.end()) { | |
575 if ((*it).first == origin.GetOrigin()) { | |
576 if (it == pending_geolocation_prompts_.begin()) { | |
577 removed_current_outstanding_callback = true; | |
578 } | |
579 it = pending_geolocation_prompts_.erase(it); | |
580 } else { | |
581 ++it; | |
582 } | |
583 } | |
584 | |
585 if (removed_current_outstanding_callback) { | |
586 JNIEnv* env = AttachCurrentThread(); | |
587 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); | |
588 if (j_ref.obj()) { | |
589 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( | |
590 "onGeolocationPermissionsHidePrompt"); | |
591 Java_AwContents_onGeolocationPermissionsHidePrompt(env, j_ref); | |
592 } | |
593 if (!pending_geolocation_prompts_.empty()) { | |
594 ShowGeolocationPromptHelper(java_ref_, | |
595 pending_geolocation_prompts_.front().first); | |
596 } | |
597 } | |
598 } | |
599 | |
600 void AwContents::OnPermissionRequest( | |
601 base::android::ScopedJavaLocalRef<jobject> j_request, | |
602 AwPermissionRequest* request) { | |
603 DCHECK(!j_request.is_null()); | |
604 DCHECK(request); | |
605 | |
606 JNIEnv* env = AttachCurrentThread(); | |
607 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); | |
608 if (j_ref.is_null()) { | |
609 permission_request_handler_->CancelRequest(request->GetOrigin(), | |
610 request->GetResources()); | |
611 return; | |
612 } | |
613 | |
614 Java_AwContents_onPermissionRequest(env, j_ref, j_request); | |
615 } | |
616 | |
617 void AwContents::OnPermissionRequestCanceled(AwPermissionRequest* request) { | |
618 JNIEnv* env = AttachCurrentThread(); | |
619 ScopedJavaLocalRef<jobject> j_request = request->GetJavaObject(); | |
620 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); | |
621 if (j_request.is_null() || j_ref.is_null()) | |
622 return; | |
623 | |
624 Java_AwContents_onPermissionRequestCanceled(env, j_ref, j_request); | |
625 } | |
626 | |
627 void AwContents::PreauthorizePermission(JNIEnv* env, | |
628 const JavaParamRef<jobject>& obj, | |
629 const JavaParamRef<jstring>& origin, | |
630 jlong resources) { | |
631 permission_request_handler_->PreauthorizePermission( | |
632 GURL(base::android::ConvertJavaStringToUTF8(env, origin)), resources); | |
633 } | |
634 | |
635 void AwContents::RequestProtectedMediaIdentifierPermission( | |
636 const GURL& origin, | |
637 const base::Callback<void(bool)>& callback) { | |
638 permission_request_handler_->SendRequest( | |
639 std::unique_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest( | |
640 origin, AwPermissionRequest::ProtectedMediaId, callback))); | |
641 } | |
642 | |
643 void AwContents::CancelProtectedMediaIdentifierPermissionRequests( | |
644 const GURL& origin) { | |
645 permission_request_handler_->CancelRequest( | |
646 origin, AwPermissionRequest::ProtectedMediaId); | |
647 } | |
648 | |
649 void AwContents::RequestGeolocationPermission( | |
650 const GURL& origin, | |
651 const base::Callback<void(bool)>& callback) { | |
652 JNIEnv* env = AttachCurrentThread(); | |
653 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
654 if (obj.is_null()) | |
655 return; | |
656 | |
657 if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj)) { | |
658 ShowGeolocationPrompt(origin, callback); | |
659 return; | |
660 } | |
661 permission_request_handler_->SendRequest( | |
662 std::unique_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest( | |
663 origin, AwPermissionRequest::Geolocation, callback))); | |
664 } | |
665 | |
666 void AwContents::CancelGeolocationPermissionRequests(const GURL& origin) { | |
667 JNIEnv* env = AttachCurrentThread(); | |
668 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
669 if (obj.is_null()) | |
670 return; | |
671 | |
672 if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj)) { | |
673 HideGeolocationPrompt(origin); | |
674 return; | |
675 } | |
676 permission_request_handler_->CancelRequest( | |
677 origin, AwPermissionRequest::Geolocation); | |
678 } | |
679 | |
680 void AwContents::RequestMIDISysexPermission( | |
681 const GURL& origin, | |
682 const base::Callback<void(bool)>& callback) { | |
683 permission_request_handler_->SendRequest( | |
684 std::unique_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest( | |
685 origin, AwPermissionRequest::MIDISysex, callback))); | |
686 } | |
687 | |
688 void AwContents::CancelMIDISysexPermissionRequests(const GURL& origin) { | |
689 permission_request_handler_->CancelRequest( | |
690 origin, AwPermissionRequest::AwPermissionRequest::MIDISysex); | |
691 } | |
692 | |
693 void AwContents::FindAllAsync(JNIEnv* env, | |
694 const JavaParamRef<jobject>& obj, | |
695 const JavaParamRef<jstring>& search_string) { | |
696 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
697 GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string)); | |
698 } | |
699 | |
700 void AwContents::FindNext(JNIEnv* env, | |
701 const JavaParamRef<jobject>& obj, | |
702 jboolean forward) { | |
703 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
704 GetFindHelper()->FindNext(forward); | |
705 } | |
706 | |
707 void AwContents::ClearMatches(JNIEnv* env, const JavaParamRef<jobject>& obj) { | |
708 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
709 GetFindHelper()->ClearMatches(); | |
710 } | |
711 | |
712 void AwContents::ClearCache(JNIEnv* env, | |
713 const JavaParamRef<jobject>& obj, | |
714 jboolean include_disk_files) { | |
715 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
716 render_view_host_ext_->ClearCache(); | |
717 | |
718 if (include_disk_files) | |
719 RemoveHttpDiskCache(web_contents_->GetRenderProcessHost()); | |
720 } | |
721 | |
722 void AwContents::KillRenderProcess(JNIEnv* env, | |
723 const JavaParamRef<jobject>& obj) { | |
724 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
725 render_view_host_ext_->KillRenderProcess(); | |
726 } | |
727 | |
728 FindHelper* AwContents::GetFindHelper() { | |
729 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
730 if (!find_helper_.get()) { | |
731 find_helper_.reset(new FindHelper(web_contents_.get())); | |
732 find_helper_->SetListener(this); | |
733 } | |
734 return find_helper_.get(); | |
735 } | |
736 | |
737 void AwContents::OnFindResultReceived(int active_ordinal, | |
738 int match_count, | |
739 bool finished) { | |
740 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
741 JNIEnv* env = AttachCurrentThread(); | |
742 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
743 if (obj.is_null()) | |
744 return; | |
745 | |
746 Java_AwContents_onFindResultReceived(env, obj, active_ordinal, match_count, | |
747 finished); | |
748 } | |
749 | |
750 bool AwContents::ShouldDownloadFavicon(const GURL& icon_url) { | |
751 return g_should_download_favicons; | |
752 } | |
753 | |
754 void AwContents::OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap) { | |
755 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
756 JNIEnv* env = AttachCurrentThread(); | |
757 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
758 if (obj.is_null()) | |
759 return; | |
760 | |
761 content::NavigationEntry* entry = | |
762 web_contents_->GetController().GetLastCommittedEntry(); | |
763 | |
764 if (entry) { | |
765 entry->GetFavicon().valid = true; | |
766 entry->GetFavicon().url = icon_url; | |
767 entry->GetFavicon().image = gfx::Image::CreateFrom1xBitmap(bitmap); | |
768 } | |
769 | |
770 Java_AwContents_onReceivedIcon(env, obj, gfx::ConvertToJavaBitmap(&bitmap)); | |
771 } | |
772 | |
773 void AwContents::OnReceivedTouchIconUrl(const std::string& url, | |
774 bool precomposed) { | |
775 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
776 JNIEnv* env = AttachCurrentThread(); | |
777 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
778 if (obj.is_null()) | |
779 return; | |
780 | |
781 Java_AwContents_onReceivedTouchIconUrl( | |
782 env, obj, ConvertUTF8ToJavaString(env, url), precomposed); | |
783 } | |
784 | |
785 void AwContents::PostInvalidate() { | |
786 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
787 JNIEnv* env = AttachCurrentThread(); | |
788 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
789 if (!obj.is_null()) | |
790 Java_AwContents_postInvalidateOnAnimation(env, obj); | |
791 } | |
792 | |
793 void AwContents::OnNewPicture() { | |
794 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
795 JNIEnv* env = AttachCurrentThread(); | |
796 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
797 if (!obj.is_null()) { | |
798 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( | |
799 "onNewPicture"); | |
800 Java_AwContents_onNewPicture(env, obj); | |
801 } | |
802 } | |
803 | |
804 base::android::ScopedJavaLocalRef<jbyteArray> AwContents::GetCertificate( | |
805 JNIEnv* env, | |
806 const JavaParamRef<jobject>& obj) { | |
807 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
808 content::NavigationEntry* entry = | |
809 web_contents_->GetController().GetLastCommittedEntry(); | |
810 if (!entry || !entry->GetSSL().certificate) | |
811 return ScopedJavaLocalRef<jbyteArray>(); | |
812 | |
813 // Convert the certificate and return it | |
814 std::string der_string; | |
815 net::X509Certificate::GetDEREncoded( | |
816 entry->GetSSL().certificate->os_cert_handle(), &der_string); | |
817 return base::android::ToJavaByteArray( | |
818 env, reinterpret_cast<const uint8_t*>(der_string.data()), | |
819 der_string.length()); | |
820 } | |
821 | |
822 void AwContents::RequestNewHitTestDataAt(JNIEnv* env, | |
823 const JavaParamRef<jobject>& obj, | |
824 jfloat x, | |
825 jfloat y, | |
826 jfloat touch_major) { | |
827 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
828 gfx::PointF touch_center(x, y); | |
829 gfx::SizeF touch_area(touch_major, touch_major); | |
830 render_view_host_ext_->RequestNewHitTestDataAt(touch_center, touch_area); | |
831 } | |
832 | |
833 void AwContents::UpdateLastHitTestData(JNIEnv* env, | |
834 const JavaParamRef<jobject>& obj) { | |
835 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
836 if (!render_view_host_ext_->HasNewHitTestData()) return; | |
837 | |
838 const AwHitTestData& data = render_view_host_ext_->GetLastHitTestData(); | |
839 render_view_host_ext_->MarkHitTestDataRead(); | |
840 | |
841 // Make sure to null the Java object if data is empty/invalid. | |
842 ScopedJavaLocalRef<jstring> extra_data_for_type; | |
843 if (data.extra_data_for_type.length()) | |
844 extra_data_for_type = ConvertUTF8ToJavaString( | |
845 env, data.extra_data_for_type); | |
846 | |
847 ScopedJavaLocalRef<jstring> href; | |
848 if (data.href.length()) | |
849 href = ConvertUTF16ToJavaString(env, data.href); | |
850 | |
851 ScopedJavaLocalRef<jstring> anchor_text; | |
852 if (data.anchor_text.length()) | |
853 anchor_text = ConvertUTF16ToJavaString(env, data.anchor_text); | |
854 | |
855 ScopedJavaLocalRef<jstring> img_src; | |
856 if (data.img_src.is_valid()) | |
857 img_src = ConvertUTF8ToJavaString(env, data.img_src.spec()); | |
858 | |
859 Java_AwContents_updateHitTestData(env, obj, data.type, extra_data_for_type, | |
860 href, anchor_text, img_src); | |
861 } | |
862 | |
863 void AwContents::OnSizeChanged(JNIEnv* env, | |
864 const JavaParamRef<jobject>& obj, | |
865 int w, | |
866 int h, | |
867 int ow, | |
868 int oh) { | |
869 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
870 browser_view_renderer_.OnSizeChanged(w, h); | |
871 } | |
872 | |
873 void AwContents::SetViewVisibility(JNIEnv* env, | |
874 const JavaParamRef<jobject>& obj, | |
875 bool visible) { | |
876 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
877 browser_view_renderer_.SetViewVisibility(visible); | |
878 UpdateRendererPriority(); | |
879 } | |
880 | |
881 void AwContents::SetWindowVisibility(JNIEnv* env, | |
882 const JavaParamRef<jobject>& obj, | |
883 bool visible) { | |
884 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
885 browser_view_renderer_.SetWindowVisibility(visible); | |
886 UpdateRendererPriority(); | |
887 } | |
888 | |
889 void AwContents::SetIsPaused(JNIEnv* env, | |
890 const JavaParamRef<jobject>& obj, | |
891 bool paused) { | |
892 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
893 browser_view_renderer_.SetIsPaused(paused); | |
894 UpdateRendererPriority(); | |
895 } | |
896 | |
897 void AwContents::OnAttachedToWindow(JNIEnv* env, | |
898 const JavaParamRef<jobject>& obj, | |
899 int w, | |
900 int h) { | |
901 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
902 browser_view_renderer_.OnAttachedToWindow(w, h); | |
903 UpdateRendererPriority(); | |
904 } | |
905 | |
906 void AwContents::OnDetachedFromWindow(JNIEnv* env, | |
907 const JavaParamRef<jobject>& obj) { | |
908 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
909 browser_view_renderer_.OnDetachedFromWindow(); | |
910 UpdateRendererPriority(); | |
911 } | |
912 | |
913 bool AwContents::IsVisible(JNIEnv* env, const JavaParamRef<jobject>& obj) { | |
914 return browser_view_renderer_.IsClientVisible(); | |
915 } | |
916 | |
917 base::android::ScopedJavaLocalRef<jbyteArray> AwContents::GetOpaqueState( | |
918 JNIEnv* env, | |
919 const JavaParamRef<jobject>& obj) { | |
920 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
921 // Required optimization in WebViewClassic to not save any state if | |
922 // there has been no navigations. | |
923 if (!web_contents_->GetController().GetEntryCount()) | |
924 return ScopedJavaLocalRef<jbyteArray>(); | |
925 | |
926 base::Pickle pickle; | |
927 if (!WriteToPickle(*web_contents_, &pickle)) { | |
928 return ScopedJavaLocalRef<jbyteArray>(); | |
929 } else { | |
930 return base::android::ToJavaByteArray( | |
931 env, reinterpret_cast<const uint8_t*>(pickle.data()), pickle.size()); | |
932 } | |
933 } | |
934 | |
935 jboolean AwContents::RestoreFromOpaqueState( | |
936 JNIEnv* env, | |
937 const JavaParamRef<jobject>& obj, | |
938 const JavaParamRef<jbyteArray>& state) { | |
939 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
940 // TODO(boliu): This copy can be optimized out if this is a performance | |
941 // problem. | |
942 std::vector<uint8_t> state_vector; | |
943 base::android::JavaByteArrayToByteVector(env, state, &state_vector); | |
944 | |
945 base::Pickle pickle(reinterpret_cast<const char*>(state_vector.data()), | |
946 state_vector.size()); | |
947 base::PickleIterator iterator(pickle); | |
948 | |
949 return RestoreFromPickle(&iterator, web_contents_.get()); | |
950 } | |
951 | |
952 bool AwContents::OnDraw(JNIEnv* env, | |
953 const JavaParamRef<jobject>& obj, | |
954 const JavaParamRef<jobject>& canvas, | |
955 jboolean is_hardware_accelerated, | |
956 jint scroll_x, | |
957 jint scroll_y, | |
958 jint visible_left, | |
959 jint visible_top, | |
960 jint visible_right, | |
961 jint visible_bottom) { | |
962 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
963 gfx::Vector2d scroll(scroll_x, scroll_y); | |
964 browser_view_renderer_.PrepareToDraw( | |
965 scroll, gfx::Rect(visible_left, visible_top, visible_right - visible_left, | |
966 visible_bottom - visible_top)); | |
967 if (is_hardware_accelerated && browser_view_renderer_.attached_to_window() && | |
968 !g_force_auxiliary_bitmap_rendering) { | |
969 return browser_view_renderer_.OnDrawHardware(); | |
970 } | |
971 | |
972 gfx::Size view_size = browser_view_renderer_.size(); | |
973 if (view_size.IsEmpty()) { | |
974 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_EmptySize", | |
975 TRACE_EVENT_SCOPE_THREAD); | |
976 return false; | |
977 } | |
978 | |
979 // TODO(hush): Right now webview size is passed in as the auxiliary bitmap | |
980 // size, which might hurt performace (only for software draws with auxiliary | |
981 // bitmap). For better performance, get global visible rect, transform it | |
982 // from screen space to view space, then intersect with the webview in | |
983 // viewspace. Use the resulting rect as the auxiliary bitmap. | |
984 std::unique_ptr<SoftwareCanvasHolder> canvas_holder = | |
985 SoftwareCanvasHolder::Create(canvas, scroll, view_size, | |
986 g_force_auxiliary_bitmap_rendering); | |
987 if (!canvas_holder || !canvas_holder->GetCanvas()) { | |
988 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_NoSoftwareCanvas", | |
989 TRACE_EVENT_SCOPE_THREAD); | |
990 return false; | |
991 } | |
992 return browser_view_renderer_.OnDrawSoftware(canvas_holder->GetCanvas()); | |
993 } | |
994 | |
995 void AwContents::SetPendingWebContentsForPopup( | |
996 std::unique_ptr<content::WebContents> pending) { | |
997 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
998 if (pending_contents_.get()) { | |
999 // TODO(benm): Support holding multiple pop up window requests. | |
1000 LOG(WARNING) << "Blocking popup window creation as an outstanding " | |
1001 << "popup window is still pending."; | |
1002 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, | |
1003 pending.release()); | |
1004 return; | |
1005 } | |
1006 pending_contents_.reset(new AwContents(std::move(pending))); | |
1007 // Set dip_scale for pending contents, which is necessary for the later | |
1008 // SynchronousCompositor and InputHandler setup. | |
1009 pending_contents_->SetDipScaleInternal(browser_view_renderer_.dip_scale()); | |
1010 } | |
1011 | |
1012 void AwContents::FocusFirstNode(JNIEnv* env, const JavaParamRef<jobject>& obj) { | |
1013 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1014 web_contents_->FocusThroughTabTraversal(false); | |
1015 } | |
1016 | |
1017 void AwContents::SetBackgroundColor(JNIEnv* env, | |
1018 const JavaParamRef<jobject>& obj, | |
1019 jint color) { | |
1020 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1021 render_view_host_ext_->SetBackgroundColor(color); | |
1022 } | |
1023 | |
1024 void AwContents::ZoomBy(JNIEnv* env, | |
1025 const base::android::JavaParamRef<jobject>& obj, | |
1026 jfloat delta) { | |
1027 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1028 browser_view_renderer_.ZoomBy(delta); | |
1029 } | |
1030 | |
1031 void AwContents::OnComputeScroll(JNIEnv* env, | |
1032 const JavaParamRef<jobject>& obj, | |
1033 jlong animation_time_millis) { | |
1034 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1035 browser_view_renderer_.OnComputeScroll( | |
1036 base::TimeTicks() + | |
1037 base::TimeDelta::FromMilliseconds(animation_time_millis)); | |
1038 } | |
1039 | |
1040 jlong AwContents::ReleasePopupAwContents(JNIEnv* env, | |
1041 const JavaParamRef<jobject>& obj) { | |
1042 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1043 return reinterpret_cast<intptr_t>(pending_contents_.release()); | |
1044 } | |
1045 | |
1046 gfx::Point AwContents::GetLocationOnScreen() { | |
1047 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1048 JNIEnv* env = AttachCurrentThread(); | |
1049 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1050 if (obj.is_null()) | |
1051 return gfx::Point(); | |
1052 std::vector<int> location; | |
1053 base::android::JavaIntArrayToIntVector( | |
1054 env, Java_AwContents_getLocationOnScreen(env, obj).obj(), &location); | |
1055 return gfx::Point(location[0], location[1]); | |
1056 } | |
1057 | |
1058 void AwContents::ScrollContainerViewTo(const gfx::Vector2d& new_value) { | |
1059 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1060 JNIEnv* env = AttachCurrentThread(); | |
1061 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1062 if (obj.is_null()) | |
1063 return; | |
1064 Java_AwContents_scrollContainerViewTo(env, obj, new_value.x(), new_value.y()); | |
1065 } | |
1066 | |
1067 void AwContents::UpdateScrollState(const gfx::Vector2d& max_scroll_offset, | |
1068 const gfx::SizeF& contents_size_dip, | |
1069 float page_scale_factor, | |
1070 float min_page_scale_factor, | |
1071 float max_page_scale_factor) { | |
1072 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1073 JNIEnv* env = AttachCurrentThread(); | |
1074 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1075 if (obj.is_null()) | |
1076 return; | |
1077 Java_AwContents_updateScrollState( | |
1078 env, obj, max_scroll_offset.x(), max_scroll_offset.y(), | |
1079 contents_size_dip.width(), contents_size_dip.height(), page_scale_factor, | |
1080 min_page_scale_factor, max_page_scale_factor); | |
1081 } | |
1082 | |
1083 void AwContents::DidOverscroll(const gfx::Vector2d& overscroll_delta, | |
1084 const gfx::Vector2dF& overscroll_velocity) { | |
1085 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1086 JNIEnv* env = AttachCurrentThread(); | |
1087 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1088 if (obj.is_null()) | |
1089 return; | |
1090 Java_AwContents_didOverscroll(env, obj, overscroll_delta.x(), | |
1091 overscroll_delta.y(), overscroll_velocity.x(), | |
1092 overscroll_velocity.y()); | |
1093 } | |
1094 | |
1095 ui::TouchHandleDrawable* AwContents::CreateDrawable() { | |
1096 JNIEnv* env = AttachCurrentThread(); | |
1097 const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1098 if (obj.is_null()) | |
1099 return nullptr; | |
1100 return reinterpret_cast<ui::TouchHandleDrawable*>( | |
1101 Java_AwContents_onCreateTouchHandle(env, obj)); | |
1102 } | |
1103 | |
1104 void AwContents::SetDipScale(JNIEnv* env, | |
1105 const JavaParamRef<jobject>& obj, | |
1106 jfloat dip_scale) { | |
1107 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1108 SetDipScaleInternal(dip_scale); | |
1109 } | |
1110 | |
1111 void AwContents::SetDipScaleInternal(float dip_scale) { | |
1112 browser_view_renderer_.SetDipScale(dip_scale); | |
1113 } | |
1114 | |
1115 void AwContents::ScrollTo(JNIEnv* env, | |
1116 const JavaParamRef<jobject>& obj, | |
1117 jint x, | |
1118 jint y) { | |
1119 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1120 browser_view_renderer_.ScrollTo(gfx::Vector2d(x, y)); | |
1121 } | |
1122 | |
1123 void AwContents::SmoothScroll(JNIEnv* env, | |
1124 const JavaParamRef<jobject>& obj, | |
1125 jint target_x, | |
1126 jint target_y, | |
1127 jlong duration_ms) { | |
1128 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1129 | |
1130 float scale = browser_view_renderer_.dip_scale() * | |
1131 browser_view_renderer_.page_scale_factor(); | |
1132 render_view_host_ext_->SmoothScroll(target_x / scale, target_y / scale, | |
1133 duration_ms); | |
1134 } | |
1135 | |
1136 void AwContents::OnWebLayoutPageScaleFactorChanged(float page_scale_factor) { | |
1137 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1138 JNIEnv* env = AttachCurrentThread(); | |
1139 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1140 if (obj.is_null()) | |
1141 return; | |
1142 Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj, | |
1143 page_scale_factor); | |
1144 } | |
1145 | |
1146 void AwContents::OnWebLayoutContentsSizeChanged( | |
1147 const gfx::Size& contents_size) { | |
1148 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1149 JNIEnv* env = AttachCurrentThread(); | |
1150 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1151 if (obj.is_null()) | |
1152 return; | |
1153 Java_AwContents_onWebLayoutContentsSizeChanged( | |
1154 env, obj, contents_size.width(), contents_size.height()); | |
1155 } | |
1156 | |
1157 jlong AwContents::CapturePicture(JNIEnv* env, | |
1158 const JavaParamRef<jobject>& obj, | |
1159 int width, | |
1160 int height) { | |
1161 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1162 return reinterpret_cast<intptr_t>( | |
1163 new AwPicture(browser_view_renderer_.CapturePicture(width, height))); | |
1164 } | |
1165 | |
1166 void AwContents::EnableOnNewPicture(JNIEnv* env, | |
1167 const JavaParamRef<jobject>& obj, | |
1168 jboolean enabled) { | |
1169 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1170 browser_view_renderer_.EnableOnNewPicture(enabled); | |
1171 } | |
1172 | |
1173 namespace { | |
1174 void InvokeVisualStateCallback(const JavaObjectWeakGlobalRef& java_ref, | |
1175 jlong request_id, | |
1176 const JavaRef<jobject>& callback, | |
1177 bool result) { | |
1178 JNIEnv* env = AttachCurrentThread(); | |
1179 ScopedJavaLocalRef<jobject> obj = java_ref.get(env); | |
1180 if (obj.is_null()) | |
1181 return; | |
1182 Java_AwContents_invokeVisualStateCallback(env, obj, callback, request_id); | |
1183 } | |
1184 } // namespace | |
1185 | |
1186 void AwContents::InsertVisualStateCallback( | |
1187 JNIEnv* env, | |
1188 const JavaParamRef<jobject>& obj, | |
1189 jlong request_id, | |
1190 const JavaParamRef<jobject>& callback) { | |
1191 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1192 web_contents_->GetMainFrame()->InsertVisualStateCallback( | |
1193 base::Bind(&InvokeVisualStateCallback, java_ref_, request_id, | |
1194 ScopedJavaGlobalRef<jobject>(env, callback))); | |
1195 } | |
1196 | |
1197 void AwContents::UpdateRendererPriority( | |
1198 AwRendererPriorityManager::RendererPriority base_priority) { | |
1199 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1200 content::RenderProcessHost* rph = web_contents_->GetRenderProcessHost(); | |
1201 AwRendererPriorityManager::RendererPriority computed_priority = base_priority; | |
1202 | |
1203 std::unique_ptr<content::RenderWidgetHostIterator> widgets( | |
1204 content::RenderWidgetHost::GetRenderWidgetHosts()); | |
1205 content::RenderWidgetHost* widget; | |
1206 while ((widget = widgets->GetNextHost()) != nullptr && | |
1207 computed_priority < | |
1208 AwRendererPriorityManager::RENDERER_PRIORITY_HIGH) { | |
1209 content::RenderViewHost* view = content::RenderViewHost::From(widget); | |
1210 if (view && rph == view->GetProcess()) { | |
1211 content::WebContents* wc = content::WebContents::FromRenderViewHost(view); | |
1212 if (wc && wc != web_contents_.get()) { | |
1213 AwContents* aw_contents = FromWebContents(wc); | |
1214 if (aw_contents) { | |
1215 computed_priority = std::max( | |
1216 aw_contents->GetComputedRendererPriority(), computed_priority); | |
1217 } | |
1218 } | |
1219 } | |
1220 } | |
1221 GetAwRendererPriorityManager()->SetRendererPriority(computed_priority); | |
1222 } | |
1223 | |
1224 AwRendererPriorityManager::RendererPriority | |
1225 AwContents::GetComputedRendererPriority() { | |
1226 if (renderer_priority_waived_when_not_visible_ && | |
1227 !browser_view_renderer_.IsClientVisible()) { | |
1228 return AwRendererPriorityManager::RENDERER_PRIORITY_WAIVED; | |
1229 } | |
1230 return renderer_requested_priority_; | |
1231 } | |
1232 | |
1233 void AwContents::UpdateRendererPriority() { | |
1234 UpdateRendererPriority(GetComputedRendererPriority()); | |
1235 } | |
1236 | |
1237 AwRendererPriorityManager* AwContents::GetAwRendererPriorityManager() { | |
1238 content::RenderProcessHost* rph = web_contents_->GetRenderProcessHost(); | |
1239 AwRendererPriorityManager* manager = static_cast<AwRendererPriorityManager*>( | |
1240 rph->GetUserData(kComputedRendererPriorityUserDataKey)); | |
1241 if (manager == nullptr) { | |
1242 manager = new AwRendererPriorityManager(rph); | |
1243 rph->SetUserData(kComputedRendererPriorityUserDataKey, | |
1244 base::WrapUnique(manager)); | |
1245 } | |
1246 return manager; | |
1247 } | |
1248 | |
1249 AwRendererPriorityManager::RendererPriority | |
1250 AwContents::GetCurrentRendererPriority() { | |
1251 return GetAwRendererPriorityManager()->GetRendererPriority(); | |
1252 } | |
1253 | |
1254 jint AwContents::GetRendererCurrentPriority( | |
1255 JNIEnv* env, | |
1256 const base::android::JavaParamRef<jobject>& obj) { | |
1257 return GetCurrentRendererPriority(); | |
1258 } | |
1259 | |
1260 jint AwContents::GetRendererRequestedPriority( | |
1261 JNIEnv* env, | |
1262 const base::android::JavaParamRef<jobject>& obj) { | |
1263 return renderer_requested_priority_; | |
1264 } | |
1265 | |
1266 jboolean AwContents::GetRendererPriorityWaivedWhenNotVisible( | |
1267 JNIEnv* env, | |
1268 const base::android::JavaParamRef<jobject>& obj) { | |
1269 return renderer_priority_waived_when_not_visible_; | |
1270 } | |
1271 | |
1272 void AwContents::SetRendererPriorityPolicy( | |
1273 JNIEnv* env, | |
1274 const JavaParamRef<jobject>& obj, | |
1275 jint renderer_requested_priority, | |
1276 jboolean renderer_priority_waived_when_not_visible) { | |
1277 renderer_requested_priority_ = | |
1278 static_cast<AwRendererPriorityManager::RendererPriority>( | |
1279 renderer_requested_priority); | |
1280 renderer_priority_waived_when_not_visible_ = | |
1281 renderer_priority_waived_when_not_visible; | |
1282 UpdateRendererPriority(renderer_requested_priority_); | |
1283 } | |
1284 | |
1285 void AwContents::ClearView(JNIEnv* env, const JavaParamRef<jobject>& obj) { | |
1286 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1287 browser_view_renderer_.ClearView(); | |
1288 } | |
1289 | |
1290 void AwContents::SetExtraHeadersForUrl( | |
1291 JNIEnv* env, | |
1292 const JavaParamRef<jobject>& obj, | |
1293 const JavaParamRef<jstring>& url, | |
1294 const JavaParamRef<jstring>& jextra_headers) { | |
1295 std::string extra_headers; | |
1296 if (jextra_headers) | |
1297 extra_headers = ConvertJavaStringToUTF8(env, jextra_headers); | |
1298 AwResourceContext* resource_context = static_cast<AwResourceContext*>( | |
1299 AwBrowserContext::FromWebContents(web_contents_.get())-> | |
1300 GetResourceContext()); | |
1301 resource_context->SetExtraHeaders(GURL(ConvertJavaStringToUTF8(env, url)), | |
1302 extra_headers); | |
1303 } | |
1304 | |
1305 void AwContents::SetJsOnlineProperty(JNIEnv* env, | |
1306 const JavaParamRef<jobject>& obj, | |
1307 jboolean network_up) { | |
1308 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1309 render_view_host_ext_->SetJsOnlineProperty(network_up); | |
1310 } | |
1311 | |
1312 void AwContents::TrimMemory(JNIEnv* env, | |
1313 const JavaParamRef<jobject>& obj, | |
1314 jint level, | |
1315 jboolean visible) { | |
1316 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1317 // Constants from Android ComponentCallbacks2. | |
1318 enum { | |
1319 TRIM_MEMORY_RUNNING_LOW = 10, | |
1320 TRIM_MEMORY_UI_HIDDEN = 20, | |
1321 TRIM_MEMORY_BACKGROUND = 40, | |
1322 TRIM_MEMORY_MODERATE = 60, | |
1323 }; | |
1324 | |
1325 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because | |
1326 // it does not indicate memory pressure, but merely that the app is | |
1327 // backgrounded. | |
1328 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN) | |
1329 return; | |
1330 | |
1331 // Do not release resources on view we expect to get DrawGL soon. | |
1332 if (level < TRIM_MEMORY_BACKGROUND && visible) | |
1333 return; | |
1334 | |
1335 browser_view_renderer_.TrimMemory(); | |
1336 } | |
1337 | |
1338 // TODO(sgurun) add support for posting a frame whose name is known (only | |
1339 // main frame is supported at this time, see crbug.com/389721) | |
1340 void AwContents::PostMessageToFrame(JNIEnv* env, | |
1341 const JavaParamRef<jobject>& obj, | |
1342 const JavaParamRef<jstring>& frame_name, | |
1343 const JavaParamRef<jstring>& message, | |
1344 const JavaParamRef<jstring>& target_origin, | |
1345 const JavaParamRef<jobjectArray>& ports) { | |
1346 // Use an empty source origin for android webview. | |
1347 content::MessagePortProvider::PostMessageToFrame(web_contents_.get(), | |
1348 env, | |
1349 nullptr, | |
1350 target_origin, | |
1351 message, | |
1352 ports); | |
1353 } | |
1354 | |
1355 void AwContents::GrantFileSchemeAccesstoChildProcess( | |
1356 JNIEnv* env, | |
1357 const JavaParamRef<jobject>& obj) { | |
1358 content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( | |
1359 web_contents_->GetRenderProcessHost()->GetID(), url::kFileScheme); | |
1360 } | |
1361 | |
1362 void AwContents::ResumeLoadingCreatedPopupWebContents( | |
1363 JNIEnv* env, | |
1364 const JavaParamRef<jobject>& obj) { | |
1365 web_contents_->ResumeLoadingCreatedWebContents(); | |
1366 } | |
1367 | |
1368 void SetShouldDownloadFavicons(JNIEnv* env, | |
1369 const JavaParamRef<jclass>& jclazz) { | |
1370 g_should_download_favicons = true; | |
1371 } | |
1372 | |
1373 void AwContents::RenderViewHostChanged(content::RenderViewHost* old_host, | |
1374 content::RenderViewHost* new_host) { | |
1375 DCHECK(new_host); | |
1376 | |
1377 int process_id = new_host->GetProcess()->GetID(); | |
1378 int routing_id = new_host->GetRoutingID(); | |
1379 | |
1380 // At this point, the current RVH may or may not contain a compositor. So | |
1381 // compositor_ may be nullptr, in which case | |
1382 // BrowserViewRenderer::DidInitializeCompositor() callback is time when the | |
1383 // new compositor is constructed. | |
1384 browser_view_renderer_.SetActiveCompositorID( | |
1385 CompositorID(process_id, routing_id)); | |
1386 } | |
1387 | |
1388 void AwContents::DidAttachInterstitialPage() { | |
1389 CompositorID compositor_id; | |
1390 RenderFrameHost* rfh = web_contents_->GetInterstitialPage()->GetMainFrame(); | |
1391 compositor_id.process_id = rfh->GetProcess()->GetID(); | |
1392 compositor_id.routing_id = rfh->GetRenderViewHost()->GetRoutingID(); | |
1393 browser_view_renderer_.SetActiveCompositorID(compositor_id); | |
1394 } | |
1395 | |
1396 void AwContents::DidDetachInterstitialPage() { | |
1397 CompositorID compositor_id; | |
1398 if (!web_contents_) | |
1399 return; | |
1400 if (web_contents_->GetRenderProcessHost() && | |
1401 web_contents_->GetRenderViewHost()) { | |
1402 compositor_id.process_id = web_contents_->GetRenderProcessHost()->GetID(); | |
1403 compositor_id.routing_id = | |
1404 web_contents_->GetRenderViewHost()->GetRoutingID(); | |
1405 } else { | |
1406 LOG(WARNING) << "failed setting the compositor on detaching interstitital"; | |
1407 } | |
1408 browser_view_renderer_.SetActiveCompositorID(compositor_id); | |
1409 } | |
1410 | |
1411 bool AwContents::CanShowBigInterstitial() { | |
1412 JNIEnv* env = AttachCurrentThread(); | |
1413 const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1414 if (obj.is_null()) | |
1415 return false; | |
1416 return Java_AwContents_canShowBigInterstitial(env, obj); | |
1417 } | |
1418 | |
1419 void AwContents::CallProceedOnInterstitialForTesting( | |
1420 JNIEnv* env, | |
1421 const base::android::JavaParamRef<jobject>& obj) { | |
1422 DCHECK(web_contents_->GetInterstitialPage()); | |
1423 web_contents_->GetInterstitialPage()->Proceed(); | |
1424 } | |
1425 | |
1426 void AwContents::CallDontProceedOnInterstitialForTesting( | |
1427 JNIEnv* env, | |
1428 const base::android::JavaParamRef<jobject>& obj) { | |
1429 DCHECK(web_contents_->GetInterstitialPage()); | |
1430 web_contents_->GetInterstitialPage()->DontProceed(); | |
1431 } | |
1432 | |
1433 void AwContents::OnRenderProcessGone(int child_process_id) { | |
1434 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1435 JNIEnv* env = AttachCurrentThread(); | |
1436 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1437 if (obj.is_null()) | |
1438 return; | |
1439 | |
1440 Java_AwContents_onRenderProcessGone(env, obj, child_process_id); | |
1441 } | |
1442 | |
1443 bool AwContents::OnRenderProcessGoneDetail(int child_process_id, | |
1444 bool crashed) { | |
1445 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1446 JNIEnv* env = AttachCurrentThread(); | |
1447 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1448 if (obj.is_null()) | |
1449 return false; | |
1450 | |
1451 return Java_AwContents_onRenderProcessGoneDetail(env, obj, | |
1452 child_process_id, crashed); | |
1453 } | |
1454 | |
1455 void AwContents::RenderProcessReady(content::RenderProcessHost* host) { | |
1456 UpdateRendererPriority(); | |
1457 } | |
1458 | |
1459 } // namespace android_webview | |
OLD | NEW |