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.
5 #include "android_webview/native/aw_contents.h"
9 #include "android_webview/browser/aw_browser_context.h"
10 #include "android_webview/browser/aw_browser_main_parts.h"
11 #include "android_webview/browser/aw_resource_context.h"
12 #include "android_webview/browser/gpu_memory_buffer_factory_impl.h"
13 #include "android_webview/browser/in_process_view_renderer.h"
14 #include "android_webview/browser/net_disk_cache_remover.h"
15 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h"
16 #include "android_webview/common/aw_hit_test_data.h"
17 #include "android_webview/native/aw_autofill_manager_delegate.h"
18 #include "android_webview/native/aw_browser_dependency_factory.h"
19 #include "android_webview/native/aw_contents_client_bridge.h"
20 #include "android_webview/native/aw_contents_io_thread_client_impl.h"
21 #include "android_webview/native/aw_pdf_exporter.h"
22 #include "android_webview/native/aw_picture.h"
23 #include "android_webview/native/aw_web_contents_delegate.h"
24 #include "android_webview/native/java_browser_view_renderer_helper.h"
25 #include "android_webview/native/state_serializer.h"
26 #include "android_webview/public/browser/draw_gl.h"
27 #include "base/android/jni_android.h"
28 #include "base/android/jni_array.h"
29 #include "base/android/jni_string.h"
30 #include "base/android/scoped_java_ref.h"
31 #include "base/atomicops.h"
32 #include "base/bind.h"
33 #include "base/callback.h"
34 #include "base/memory/memory_pressure_listener.h"
35 #include "base/message_loop/message_loop.h"
36 #include "base/pickle.h"
37 #include "base/strings/string16.h"
38 #include "base/supports_user_data.h"
39 #include "components/autofill/content/browser/autofill_driver_impl.h"
40 #include "components/autofill/core/browser/autofill_manager.h"
41 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
42 #include "components/navigation_interception/intercept_navigation_delegate.h"
43 #include "content/public/browser/android/content_view_core.h"
44 #include "content/public/browser/browser_thread.h"
45 #include "content/public/browser/cert_store.h"
46 #include "content/public/browser/favicon_status.h"
47 #include "content/public/browser/navigation_entry.h"
48 #include "content/public/browser/render_frame_host.h"
49 #include "content/public/browser/render_process_host.h"
50 #include "content/public/browser/render_view_host.h"
51 #include "content/public/browser/web_contents.h"
52 #include "content/public/common/renderer_preferences.h"
53 #include "content/public/common/ssl_status.h"
54 #include "jni/AwContents_jni.h"
55 #include "net/cert/x509_certificate.h"
56 #include "third_party/skia/include/core/SkPicture.h"
57 #include "ui/base/l10n/l10n_util_android.h"
58 #include "ui/gfx/android/java_bitmap.h"
59 #include "ui/gfx/font_render_params_linux.h"
60 #include "ui/gfx/image/image.h"
61 #include "ui/gfx/size.h"
63 struct AwDrawSWFunctionTable;
64 struct AwDrawGLFunctionTable;
66 using autofill::AutofillDriverImpl;
67 using autofill::AutofillManager;
68 using base::android::AttachCurrentThread;
69 using base::android::ConvertJavaStringToUTF16;
70 using base::android::ConvertJavaStringToUTF8;
71 using base::android::ConvertUTF16ToJavaString;
72 using base::android::ConvertUTF8ToJavaString;
73 using base::android::JavaRef;
74 using base::android::ScopedJavaGlobalRef;
75 using base::android::ScopedJavaLocalRef;
76 using navigation_interception::InterceptNavigationDelegate;
77 using content::BrowserThread;
78 using content::ContentViewCore;
79 using content::WebContents;
82 static AwDrawGLFunction DrawGLFunction;
83 static void DrawGLFunction(int view_context,
84 AwDrawGLInfo* draw_info,
86 // |view_context| is the value that was returned from the java
87 // AwContents.onPrepareDrawGL; this cast must match the code there.
88 reinterpret_cast<android_webview::BrowserViewRenderer*>(view_context)->DrawGL(
93 namespace android_webview {
97 bool g_should_download_favicons = false;
99 JavaBrowserViewRendererHelper* java_renderer_helper() {
100 return JavaBrowserViewRendererHelper::GetInstance();
103 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
105 class AwContentsUserData : public base::SupportsUserData::Data {
107 AwContentsUserData(AwContents* ptr) : contents_(ptr) {}
109 static AwContents* GetContents(WebContents* web_contents) {
112 AwContentsUserData* data = reinterpret_cast<AwContentsUserData*>(
113 web_contents->GetUserData(kAwContentsUserDataKey));
114 return data ? data->contents_ : NULL;
118 AwContents* contents_;
121 base::subtle::Atomic32 g_instance_count = 0;
123 // TODO(boliu): Deduplicate with chrome/ code.
124 content::RendererPreferencesHintingEnum GetRendererPreferencesHintingEnum(
125 gfx::FontRenderParams::Hinting hinting) {
127 case gfx::FontRenderParams::HINTING_NONE:
128 return content::RENDERER_PREFERENCES_HINTING_NONE;
129 case gfx::FontRenderParams::HINTING_SLIGHT:
130 return content::RENDERER_PREFERENCES_HINTING_SLIGHT;
131 case gfx::FontRenderParams::HINTING_MEDIUM:
132 return content::RENDERER_PREFERENCES_HINTING_MEDIUM;
133 case gfx::FontRenderParams::HINTING_FULL:
134 return content::RENDERER_PREFERENCES_HINTING_FULL;
136 NOTREACHED() << "Unhandled hinting style " << hinting;
137 return content::RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT;
141 // TODO(boliu): Deduplicate with chrome/ code.
142 content::RendererPreferencesSubpixelRenderingEnum
143 GetRendererPreferencesSubpixelRenderingEnum(
144 gfx::FontRenderParams::SubpixelRendering subpixel_rendering) {
145 switch (subpixel_rendering) {
146 case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE:
147 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE;
148 case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB:
149 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB;
150 case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR:
151 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR;
152 case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB:
153 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB;
154 case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR:
155 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR;
157 NOTREACHED() << "Unhandled subpixel rendering style "
158 << subpixel_rendering;
159 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT;
163 void OnIoThreadClientReady(content::RenderFrameHost* rfh) {
164 int render_process_id = rfh->GetProcess()->GetID();
165 int render_frame_id = rfh->GetRoutingID();
166 AwResourceDispatcherHostDelegate::OnIoThreadClientReady(
167 render_process_id, render_frame_id);
173 AwContents* AwContents::FromWebContents(WebContents* web_contents) {
174 return AwContentsUserData::GetContents(web_contents);
178 AwContents* AwContents::FromID(int render_process_id, int render_view_id) {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
180 const content::RenderViewHost* rvh =
181 content::RenderViewHost::FromID(render_process_id, render_view_id);
182 if (!rvh) return NULL;
183 content::WebContents* web_contents =
184 content::WebContents::FromRenderViewHost(rvh);
185 if (!web_contents) return NULL;
186 return FromWebContents(web_contents);
189 AwContents::AwContents(scoped_ptr<WebContents> web_contents)
190 : web_contents_(web_contents.Pass()),
191 browser_view_renderer_(
192 new InProcessViewRenderer(this, java_renderer_helper(),
193 web_contents_.get())) {
194 base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1);
195 icon_helper_.reset(new IconHelper(web_contents_.get()));
196 icon_helper_->SetListener(this);
197 web_contents_->SetUserData(kAwContentsUserDataKey,
198 new AwContentsUserData(this));
199 render_view_host_ext_.reset(
200 new AwRenderViewHostExt(this, web_contents_.get()));
202 AwAutofillManagerDelegate* autofill_manager_delegate =
203 AwAutofillManagerDelegate::FromWebContents(web_contents_.get());
204 if (autofill_manager_delegate)
205 InitAutofillIfNecessary(autofill_manager_delegate->GetSaveFormData());
207 SetAndroidWebViewRendererPrefs();
210 void AwContents::SetJavaPeers(JNIEnv* env,
213 jobject web_contents_delegate,
214 jobject contents_client_bridge,
215 jobject io_thread_client,
216 jobject intercept_navigation_delegate) {
217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
218 // The |aw_content| param is technically spurious as it duplicates |obj| but
219 // is passed over anyway to make the binding more explicit.
220 java_ref_ = JavaObjectWeakGlobalRef(env, aw_contents);
222 web_contents_delegate_.reset(
223 new AwWebContentsDelegate(env, web_contents_delegate));
224 web_contents_->SetDelegate(web_contents_delegate_.get());
226 contents_client_bridge_.reset(
227 new AwContentsClientBridge(env, contents_client_bridge));
228 AwContentsClientBridgeBase::Associate(web_contents_.get(),
229 contents_client_bridge_.get());
231 AwContentsIoThreadClientImpl::Associate(
232 web_contents_.get(), ScopedJavaLocalRef<jobject>(env, io_thread_client));
234 InterceptNavigationDelegate::Associate(
236 make_scoped_ptr(new InterceptNavigationDelegate(
237 env, intercept_navigation_delegate)));
239 // Finally, having setup the associations, release any deferred requests
240 web_contents_->ForEachFrame(base::Bind(&OnIoThreadClientReady));
243 void AwContents::SetSaveFormData(bool enabled) {
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
245 InitAutofillIfNecessary(enabled);
246 // We need to check for the existence, since autofill_manager_delegate
247 // may not be created when the setting is false.
248 if (AutofillDriverImpl::FromWebContents(web_contents_.get())) {
249 AwAutofillManagerDelegate::FromWebContents(web_contents_.get())->
250 SetSaveFormData(enabled);
254 void AwContents::InitAutofillIfNecessary(bool enabled) {
255 // Do not initialize if the feature is not enabled.
258 // Check if the autofill driver already exists.
259 content::WebContents* web_contents = web_contents_.get();
260 if (AutofillDriverImpl::FromWebContents(web_contents))
263 AwBrowserContext::FromWebContents(web_contents)->
264 CreateUserPrefServiceIfNecessary();
265 AwAutofillManagerDelegate::CreateForWebContents(web_contents);
266 AutofillDriverImpl::CreateForWebContentsAndDelegate(
268 AwAutofillManagerDelegate::FromWebContents(web_contents),
269 l10n_util::GetDefaultLocale(),
270 AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
273 void AwContents::SetAndroidWebViewRendererPrefs() {
274 content::RendererPreferences* prefs =
275 web_contents_->GetMutableRendererPrefs();
276 prefs->tap_multiple_targets_strategy =
277 content::TAP_MULTIPLE_TARGETS_STRATEGY_NONE;
279 // TODO(boliu): Deduplicate with chrome/ code.
280 const gfx::FontRenderParams& params = gfx::GetDefaultWebKitFontRenderParams();
281 prefs->should_antialias_text = params.antialiasing;
282 prefs->use_subpixel_positioning = params.subpixel_positioning;
283 prefs->hinting = GetRendererPreferencesHintingEnum(params.hinting);
284 prefs->use_autohinter = params.autohinter;
285 prefs->use_bitmaps = params.use_bitmaps;
286 prefs->subpixel_rendering =
287 GetRendererPreferencesSubpixelRenderingEnum(params.subpixel_rendering);
289 content::RenderViewHost* host = web_contents_->GetRenderViewHost();
291 host->SyncRendererPrefs();
294 void AwContents::SetAwAutofillManagerDelegate(jobject delegate) {
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
296 JNIEnv* env = AttachCurrentThread();
297 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
300 Java_AwContents_setAwAutofillManagerDelegate(env, obj.obj(), delegate);
303 AwContents::~AwContents() {
304 DCHECK(AwContents::FromWebContents(web_contents_.get()) == this);
305 web_contents_->RemoveUserData(kAwContentsUserDataKey);
306 if (find_helper_.get())
307 find_helper_->SetListener(NULL);
308 if (icon_helper_.get())
309 icon_helper_->SetListener(NULL);
310 base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, -1);
311 // When the last WebView is destroyed free all discardable memory allocated by
312 // Chromium, because the app process may continue to run for a long time
313 // without ever using another WebView.
314 if (base::subtle::NoBarrier_Load(&g_instance_count) == 0) {
315 base::MemoryPressureListener::NotifyMemoryPressure(
316 base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
320 jint AwContents::GetWebContents(JNIEnv* env, jobject obj) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322 DCHECK(web_contents_);
323 return reinterpret_cast<jint>(web_contents_.get());
326 void AwContents::Destroy(JNIEnv* env, jobject obj) {
328 // We do not delete AwContents immediately. Some applications try to delete
329 // Webview in ShouldOverrideUrlLoading callback, which is a sync IPC from
331 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
334 static jlong Init(JNIEnv* env, jclass, jobject browser_context) {
335 // TODO(joth): Use |browser_context| to get the native BrowserContext, rather
336 // than hard-code the default instance lookup here.
337 scoped_ptr<WebContents> web_contents(content::WebContents::Create(
338 content::WebContents::CreateParams(AwBrowserContext::GetDefault())));
339 // Return an 'uninitialized' instance; most work is deferred until the
340 // subsequent SetJavaPeers() call.
341 return reinterpret_cast<intptr_t>(new AwContents(web_contents.Pass()));
344 static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) {
345 BrowserViewRenderer::SetAwDrawSWFunctionTable(
346 reinterpret_cast<AwDrawSWFunctionTable*>(function_table));
349 static void SetAwDrawGLFunctionTable(JNIEnv* env, jclass, jint function_table) {
350 GpuMemoryBufferFactoryImpl::SetAwDrawGLFunctionTable(
351 reinterpret_cast<AwDrawGLFunctionTable*>(function_table));
354 static jint GetAwDrawGLFunction(JNIEnv* env, jclass) {
355 return reinterpret_cast<jint>(&DrawGLFunction);
359 jint GetNativeInstanceCount(JNIEnv* env, jclass) {
360 return base::subtle::NoBarrier_Load(&g_instance_count);
363 jint AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) {
364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
365 return reinterpret_cast<jint>(browser_view_renderer_.get());
369 void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message,
371 Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(),
377 void AwContents::DocumentHasImages(JNIEnv* env, jobject obj, jobject message) {
378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
379 ScopedJavaGlobalRef<jobject> j_message;
380 j_message.Reset(env, message);
381 render_view_host_ext_->DocumentHasImages(
382 base::Bind(&DocumentHasImagesCallback, j_message));
386 void GenerateMHTMLCallback(ScopedJavaGlobalRef<jobject>* callback,
387 const base::FilePath& path, int64 size) {
388 JNIEnv* env = AttachCurrentThread();
389 // Android files are UTF8, so the path conversion below is safe.
390 Java_AwContents_generateMHTMLCallback(
392 ConvertUTF8ToJavaString(env, path.AsUTF8Unsafe()).obj(),
393 size, callback->obj());
397 void AwContents::GenerateMHTML(JNIEnv* env, jobject obj,
398 jstring jpath, jobject callback) {
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
400 ScopedJavaGlobalRef<jobject>* j_callback = new ScopedJavaGlobalRef<jobject>();
401 j_callback->Reset(env, callback);
402 base::FilePath target_path(ConvertJavaStringToUTF8(env, jpath));
403 web_contents_->GenerateMHTML(
405 base::Bind(&GenerateMHTMLCallback, base::Owned(j_callback), target_path));
408 void AwContents::CreatePdfExporter(JNIEnv* env,
410 jobject pdfExporter) {
412 new AwPdfExporter(env,
414 browser_view_renderer_.get(),
415 web_contents_.get()));
418 bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler,
419 const std::string& host,
420 const std::string& realm) {
421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
422 JNIEnv* env = AttachCurrentThread();
423 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
427 ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host);
428 ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm);
429 Java_AwContents_onReceivedHttpAuthRequest(env, obj.obj(), handler.obj(),
430 jhost.obj(), jrealm.obj());
434 void AwContents::AddVisitedLinks(JNIEnv* env,
436 jobjectArray jvisited_links) {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
438 std::vector<base::string16> visited_link_strings;
439 base::android::AppendJavaStringArrayToStringVector(
440 env, jvisited_links, &visited_link_strings);
442 std::vector<GURL> visited_link_gurls;
443 std::vector<base::string16>::const_iterator itr;
444 for (itr = visited_link_strings.begin(); itr != visited_link_strings.end();
446 visited_link_gurls.push_back(GURL(*itr));
449 AwBrowserContext::FromWebContents(web_contents_.get())
450 ->AddVisitedURLs(visited_link_gurls);
453 bool RegisterAwContents(JNIEnv* env) {
454 return RegisterNativesImpl(env) >= 0;
459 void ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef& java_ref,
460 const GURL& origin) {
461 JNIEnv* env = AttachCurrentThread();
462 ScopedJavaLocalRef<jobject> j_ref = java_ref.get(env);
464 ScopedJavaLocalRef<jstring> j_origin(
465 ConvertUTF8ToJavaString(env, origin.spec()));
466 Java_AwContents_onGeolocationPermissionsShowPrompt(env,
472 void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref,
473 const GURL& origin) {
474 JNIEnv* env = AttachCurrentThread();
475 if (java_ref.get(env).obj()) {
476 content::BrowserThread::PostTask(
477 content::BrowserThread::UI,
479 base::Bind(&ShowGeolocationPromptHelperTask,
485 } // anonymous namespace
487 void AwContents::ShowGeolocationPrompt(const GURL& requesting_frame,
488 base::Callback<void(bool)> callback) {
489 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
491 GURL origin = requesting_frame.GetOrigin();
492 bool show_prompt = pending_geolocation_prompts_.empty();
493 pending_geolocation_prompts_.push_back(OriginCallback(origin, callback));
495 ShowGeolocationPromptHelper(java_ref_, origin);
500 void AwContents::InvokeGeolocationCallback(JNIEnv* env,
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
506 GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin));
507 if (callback_origin.GetOrigin() ==
508 pending_geolocation_prompts_.front().first) {
509 pending_geolocation_prompts_.front().second.Run(value);
510 pending_geolocation_prompts_.pop_front();
511 if (!pending_geolocation_prompts_.empty()) {
512 ShowGeolocationPromptHelper(java_ref_,
513 pending_geolocation_prompts_.front().first);
518 void AwContents::HideGeolocationPrompt(const GURL& origin) {
519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
520 bool removed_current_outstanding_callback = false;
521 std::list<OriginCallback>::iterator it = pending_geolocation_prompts_.begin();
522 while (it != pending_geolocation_prompts_.end()) {
523 if ((*it).first == origin.GetOrigin()) {
524 if (it == pending_geolocation_prompts_.begin()) {
525 removed_current_outstanding_callback = true;
527 it = pending_geolocation_prompts_.erase(it);
533 if (removed_current_outstanding_callback) {
534 JNIEnv* env = AttachCurrentThread();
535 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
537 Java_AwContents_onGeolocationPermissionsHidePrompt(env, j_ref.obj());
539 if (!pending_geolocation_prompts_.empty()) {
540 ShowGeolocationPromptHelper(java_ref_,
541 pending_geolocation_prompts_.front().first);
546 void AwContents::FindAllAsync(JNIEnv* env, jobject obj, jstring search_string) {
547 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
548 GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string));
551 void AwContents::FindNext(JNIEnv* env, jobject obj, jboolean forward) {
552 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
553 GetFindHelper()->FindNext(forward);
556 void AwContents::ClearMatches(JNIEnv* env, jobject obj) {
557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
558 GetFindHelper()->ClearMatches();
561 void AwContents::ClearCache(
564 jboolean include_disk_files) {
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
566 render_view_host_ext_->ClearCache();
568 if (include_disk_files) {
569 RemoveHttpDiskCache(web_contents_->GetBrowserContext(),
570 web_contents_->GetRoutingID());
574 FindHelper* AwContents::GetFindHelper() {
575 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
576 if (!find_helper_.get()) {
577 find_helper_.reset(new FindHelper(web_contents_.get()));
578 find_helper_->SetListener(this);
580 return find_helper_.get();
583 void AwContents::OnFindResultReceived(int active_ordinal,
586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
587 JNIEnv* env = AttachCurrentThread();
588 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
592 Java_AwContents_onFindResultReceived(
593 env, obj.obj(), active_ordinal, match_count, finished);
596 bool AwContents::ShouldDownloadFavicon(const GURL& icon_url) {
597 return g_should_download_favicons;
600 void AwContents::OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap) {
601 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
602 JNIEnv* env = AttachCurrentThread();
603 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
607 content::NavigationEntry* entry =
608 web_contents_->GetController().GetActiveEntry();
611 entry->GetFavicon().valid = true;
612 entry->GetFavicon().url = icon_url;
613 entry->GetFavicon().image = gfx::Image::CreateFrom1xBitmap(bitmap);
616 Java_AwContents_onReceivedIcon(
617 env, obj.obj(), gfx::ConvertToJavaBitmap(&bitmap).obj());
620 void AwContents::OnReceivedTouchIconUrl(const std::string& url,
622 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
623 JNIEnv* env = AttachCurrentThread();
624 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
628 Java_AwContents_onReceivedTouchIconUrl(
629 env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed);
632 bool AwContents::RequestDrawGL(jobject canvas) {
633 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
634 JNIEnv* env = AttachCurrentThread();
635 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
638 return Java_AwContents_requestDrawGL(env, obj.obj(), canvas);
641 void AwContents::PostInvalidate() {
642 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
643 JNIEnv* env = AttachCurrentThread();
644 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
646 Java_AwContents_postInvalidateOnAnimation(env, obj.obj());
649 void AwContents::UpdateGlobalVisibleRect() {
650 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
651 JNIEnv* env = AttachCurrentThread();
652 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
654 Java_AwContents_updateGlobalVisibleRect(env, obj.obj());
657 void AwContents::OnNewPicture() {
658 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
659 JNIEnv* env = AttachCurrentThread();
660 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
662 Java_AwContents_onNewPicture(env, obj.obj());
665 base::android::ScopedJavaLocalRef<jbyteArray>
666 AwContents::GetCertificate(JNIEnv* env,
668 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
669 content::NavigationEntry* entry =
670 web_contents_->GetController().GetActiveEntry();
672 return ScopedJavaLocalRef<jbyteArray>();
673 // Get the certificate
674 int cert_id = entry->GetSSL().cert_id;
675 scoped_refptr<net::X509Certificate> cert;
676 bool ok = content::CertStore::GetInstance()->RetrieveCert(cert_id, &cert);
678 return ScopedJavaLocalRef<jbyteArray>();
680 // Convert the certificate and return it
681 std::string der_string;
682 net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_string);
683 return base::android::ToJavaByteArray(env,
684 reinterpret_cast<const uint8*>(der_string.data()), der_string.length());
687 void AwContents::RequestNewHitTestDataAt(JNIEnv* env, jobject obj,
689 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
690 render_view_host_ext_->RequestNewHitTestDataAt(x, y);
693 void AwContents::UpdateLastHitTestData(JNIEnv* env, jobject obj) {
694 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
695 if (!render_view_host_ext_->HasNewHitTestData()) return;
697 const AwHitTestData& data = render_view_host_ext_->GetLastHitTestData();
698 render_view_host_ext_->MarkHitTestDataRead();
700 // Make sure to null the Java object if data is empty/invalid.
701 ScopedJavaLocalRef<jstring> extra_data_for_type;
702 if (data.extra_data_for_type.length())
703 extra_data_for_type = ConvertUTF8ToJavaString(
704 env, data.extra_data_for_type);
706 ScopedJavaLocalRef<jstring> href;
707 if (data.href.length())
708 href = ConvertUTF16ToJavaString(env, data.href);
710 ScopedJavaLocalRef<jstring> anchor_text;
711 if (data.anchor_text.length())
712 anchor_text = ConvertUTF16ToJavaString(env, data.anchor_text);
714 ScopedJavaLocalRef<jstring> img_src;
715 if (data.img_src.is_valid())
716 img_src = ConvertUTF8ToJavaString(env, data.img_src.spec());
718 Java_AwContents_updateHitTestData(env,
721 extra_data_for_type.obj(),
727 void AwContents::OnSizeChanged(JNIEnv* env, jobject obj,
728 int w, int h, int ow, int oh) {
729 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
730 browser_view_renderer_->OnSizeChanged(w, h);
733 void AwContents::SetViewVisibility(JNIEnv* env, jobject obj, bool visible) {
734 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
735 browser_view_renderer_->SetViewVisibility(visible);
738 void AwContents::SetWindowVisibility(JNIEnv* env, jobject obj, bool visible) {
739 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
740 browser_view_renderer_->SetWindowVisibility(visible);
743 void AwContents::SetIsPaused(JNIEnv* env, jobject obj, bool paused) {
744 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
745 browser_view_renderer_->SetIsPaused(paused);
746 ContentViewCore* cvc =
747 ContentViewCore::FromWebContents(web_contents_.get());
749 cvc->PauseOrResumeGeolocation(paused);
756 void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) {
757 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
758 browser_view_renderer_->OnAttachedToWindow(w, h);
761 void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) {
762 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
763 browser_view_renderer_->OnDetachedFromWindow();
766 base::android::ScopedJavaLocalRef<jbyteArray>
767 AwContents::GetOpaqueState(JNIEnv* env, jobject obj) {
768 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
769 // Required optimization in WebViewClassic to not save any state if
770 // there has been no navigations.
771 if (!web_contents_->GetController().GetEntryCount())
772 return ScopedJavaLocalRef<jbyteArray>();
775 if (!WriteToPickle(*web_contents_, &pickle)) {
776 return ScopedJavaLocalRef<jbyteArray>();
778 return base::android::ToJavaByteArray(env,
779 reinterpret_cast<const uint8*>(pickle.data()), pickle.size());
783 jboolean AwContents::RestoreFromOpaqueState(
784 JNIEnv* env, jobject obj, jbyteArray state) {
785 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
786 // TODO(boliu): This copy can be optimized out if this is a performance
788 std::vector<uint8> state_vector;
789 base::android::JavaByteArrayToByteVector(env, state, &state_vector);
791 Pickle pickle(reinterpret_cast<const char*>(state_vector.begin()),
792 state_vector.size());
793 PickleIterator iterator(pickle);
795 return RestoreFromPickle(&iterator, web_contents_.get());
798 bool AwContents::OnDraw(JNIEnv* env,
801 jboolean is_hardware_accelerated,
808 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
809 return browser_view_renderer_->OnDraw(
811 is_hardware_accelerated,
812 gfx::Vector2d(scroll_x, scroll_y),
814 clip_left, clip_top, clip_right - clip_left, clip_bottom - clip_top));
817 void AwContents::SetGlobalVisibleRect(JNIEnv* env,
822 jint visible_bottom) {
823 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
824 browser_view_renderer_->SetGlobalVisibleRect(
825 gfx::Rect(visible_left,
827 visible_right - visible_left,
828 visible_bottom - visible_top));
831 void AwContents::SetPendingWebContentsForPopup(
832 scoped_ptr<content::WebContents> pending) {
833 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
834 if (pending_contents_.get()) {
835 // TODO(benm): Support holding multiple pop up window requests.
836 LOG(WARNING) << "Blocking popup window creation as an outstanding "
837 << "popup window is still pending.";
838 base::MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release());
841 pending_contents_.reset(new AwContents(pending.Pass()));
844 void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) {
845 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
846 web_contents_->FocusThroughTabTraversal(false);
849 void AwContents::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) {
850 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
851 render_view_host_ext_->SetBackgroundColor(color);
854 jint AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) {
855 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
856 return reinterpret_cast<jint>(pending_contents_.release());
859 gfx::Point AwContents::GetLocationOnScreen() {
860 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
861 JNIEnv* env = AttachCurrentThread();
862 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
865 std::vector<int> location;
866 base::android::JavaIntArrayToIntVector(
868 Java_AwContents_getLocationOnScreen(env, obj.obj()).obj(),
870 return gfx::Point(location[0], location[1]);
873 void AwContents::SetMaxContainerViewScrollOffset(gfx::Vector2d new_value) {
874 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
875 JNIEnv* env = AttachCurrentThread();
876 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
879 Java_AwContents_setMaxContainerViewScrollOffset(
880 env, obj.obj(), new_value.x(), new_value.y());
883 void AwContents::ScrollContainerViewTo(gfx::Vector2d new_value) {
884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
885 JNIEnv* env = AttachCurrentThread();
886 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
889 Java_AwContents_scrollContainerViewTo(
890 env, obj.obj(), new_value.x(), new_value.y());
893 bool AwContents::IsFlingActive() const {
894 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
895 JNIEnv* env = AttachCurrentThread();
896 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
899 return Java_AwContents_isFlingActive(env, obj.obj());
902 void AwContents::SetPageScaleFactorAndLimits(
903 float page_scale_factor,
904 float min_page_scale_factor,
905 float max_page_scale_factor) {
906 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
907 JNIEnv* env = AttachCurrentThread();
908 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
911 Java_AwContents_setPageScaleFactorAndLimits(env,
914 min_page_scale_factor,
915 max_page_scale_factor);
918 void AwContents::SetContentsSize(gfx::SizeF contents_size_dip) {
919 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
920 JNIEnv* env = AttachCurrentThread();
921 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
924 Java_AwContents_setContentsSize(
925 env, obj.obj(), contents_size_dip.width(), contents_size_dip.height());
928 void AwContents::DidOverscroll(gfx::Vector2d overscroll_delta) {
929 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
930 JNIEnv* env = AttachCurrentThread();
931 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
934 Java_AwContents_didOverscroll(
935 env, obj.obj(), overscroll_delta.x(), overscroll_delta.y());
938 void AwContents::SetDipScale(JNIEnv* env, jobject obj, jfloat dip_scale) {
939 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
940 browser_view_renderer_->SetDipScale(dip_scale);
943 void AwContents::SetFixedLayoutSize(JNIEnv* env,
947 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
948 render_view_host_ext_->SetFixedLayoutSize(gfx::Size(width_dip, height_dip));
951 void AwContents::ScrollTo(JNIEnv* env, jobject obj, jint x, jint y) {
952 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
953 browser_view_renderer_->ScrollTo(gfx::Vector2d(x, y));
956 void AwContents::OnWebLayoutPageScaleFactorChanged(float page_scale_factor) {
957 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
958 JNIEnv* env = AttachCurrentThread();
959 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
962 Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj.obj(),
966 void AwContents::OnWebLayoutContentsSizeChanged(
967 const gfx::Size& contents_size) {
968 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
969 JNIEnv* env = AttachCurrentThread();
970 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
973 Java_AwContents_onWebLayoutContentsSizeChanged(
974 env, obj.obj(), contents_size.width(), contents_size.height());
977 jlong AwContents::CapturePicture(JNIEnv* env,
981 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
982 return reinterpret_cast<intptr_t>(new AwPicture(
983 browser_view_renderer_->CapturePicture(width, height)));
986 void AwContents::EnableOnNewPicture(JNIEnv* env,
989 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
990 browser_view_renderer_->EnableOnNewPicture(enabled);
993 void AwContents::ClearView(JNIEnv* env, jobject obj) {
994 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
995 browser_view_renderer_->ClearView();
998 void AwContents::SetExtraHeadersForUrl(JNIEnv* env, jobject obj,
999 jstring url, jstring jextra_headers) {
1000 std::string extra_headers;
1002 extra_headers = ConvertJavaStringToUTF8(env, jextra_headers);
1003 AwResourceContext* resource_context = static_cast<AwResourceContext*>(
1004 AwBrowserContext::FromWebContents(web_contents_.get())->
1005 GetResourceContext());
1006 resource_context->SetExtraHeaders(GURL(ConvertJavaStringToUTF8(env, url)),
1010 void AwContents::SetJsOnlineProperty(JNIEnv* env,
1012 jboolean network_up) {
1013 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1014 render_view_host_ext_->SetJsOnlineProperty(network_up);
1017 void AwContents::TrimMemory(JNIEnv* env, jobject obj, jint level) {
1018 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1019 browser_view_renderer_->TrimMemory(level);
1022 void SetShouldDownloadFavicons(JNIEnv* env, jclass jclazz) {
1023 g_should_download_favicons = true;
1026 } // namespace android_webview