Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / android_webview / native / aw_contents.cc
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
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/browser_view_renderer.h"
13 #include "android_webview/browser/deferred_gpu_command_service.h"
14 #include "android_webview/browser/gpu_memory_buffer_factory_impl.h"
15 #include "android_webview/browser/hardware_renderer.h"
16 #include "android_webview/browser/net_disk_cache_remover.h"
17 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h"
18 #include "android_webview/browser/scoped_app_gl_state_restore.h"
19 #include "android_webview/common/aw_hit_test_data.h"
20 #include "android_webview/common/devtools_instrumentation.h"
21 #include "android_webview/native/aw_autofill_manager_delegate.h"
22 #include "android_webview/native/aw_browser_dependency_factory.h"
23 #include "android_webview/native/aw_contents_client_bridge.h"
24 #include "android_webview/native/aw_contents_io_thread_client_impl.h"
25 #include "android_webview/native/aw_pdf_exporter.h"
26 #include "android_webview/native/aw_picture.h"
27 #include "android_webview/native/aw_web_contents_delegate.h"
28 #include "android_webview/native/java_browser_view_renderer_helper.h"
29 #include "android_webview/native/permission/aw_permission_request.h"
30 #include "android_webview/native/permission/permission_request_handler.h"
31 #include "android_webview/native/state_serializer.h"
32 #include "android_webview/public/browser/draw_gl.h"
33 #include "base/android/jni_android.h"
34 #include "base/android/jni_array.h"
35 #include "base/android/jni_string.h"
36 #include "base/android/scoped_java_ref.h"
37 #include "base/atomicops.h"
38 #include "base/bind.h"
39 #include "base/callback.h"
40 #include "base/memory/memory_pressure_listener.h"
41 #include "base/message_loop/message_loop.h"
42 #include "base/pickle.h"
43 #include "base/strings/string16.h"
44 #include "base/supports_user_data.h"
45 #include "components/autofill/content/browser/content_autofill_driver.h"
46 #include "components/autofill/core/browser/autofill_manager.h"
47 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
48 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
49 #include "components/navigation_interception/intercept_navigation_delegate.h"
50 #include "content/public/browser/android/content_view_core.h"
51 #include "content/public/browser/browser_thread.h"
52 #include "content/public/browser/cert_store.h"
53 #include "content/public/browser/favicon_status.h"
54 #include "content/public/browser/navigation_entry.h"
55 #include "content/public/browser/render_frame_host.h"
56 #include "content/public/browser/render_process_host.h"
57 #include "content/public/browser/render_view_host.h"
58 #include "content/public/browser/web_contents.h"
59 #include "content/public/common/renderer_preferences.h"
60 #include "content/public/common/ssl_status.h"
61 #include "jni/AwContents_jni.h"
62 #include "net/base/auth.h"
63 #include "net/cert/x509_certificate.h"
64 #include "third_party/skia/include/core/SkPicture.h"
65 #include "ui/base/l10n/l10n_util_android.h"
66 #include "ui/gfx/android/java_bitmap.h"
67 #include "ui/gfx/image/image.h"
68 #include "ui/gfx/size.h"
69
70 struct AwDrawSWFunctionTable;
71 struct AwDrawGLFunctionTable;
72
73 using autofill::ContentAutofillDriver;
74 using autofill::AutofillManager;
75 using base::android::AttachCurrentThread;
76 using base::android::ConvertJavaStringToUTF16;
77 using base::android::ConvertJavaStringToUTF8;
78 using base::android::ConvertUTF16ToJavaString;
79 using base::android::ConvertUTF8ToJavaString;
80 using base::android::JavaRef;
81 using base::android::ScopedJavaGlobalRef;
82 using base::android::ScopedJavaLocalRef;
83 using data_reduction_proxy::DataReductionProxySettings;
84 using navigation_interception::InterceptNavigationDelegate;
85 using content::BrowserThread;
86 using content::ContentViewCore;
87 using content::WebContents;
88
89 extern "C" {
90 static AwDrawGLFunction DrawGLFunction;
91 static void DrawGLFunction(long view_context,
92                            AwDrawGLInfo* draw_info,
93                            void* spare) {
94   // |view_context| is the value that was returned from the java
95   // AwContents.onPrepareDrawGL; this cast must match the code there.
96   reinterpret_cast<android_webview::AwContents*>(view_context)
97       ->DrawGL(draw_info);
98 }
99 }
100
101 namespace android_webview {
102
103 namespace {
104
105 bool g_should_download_favicons = false;
106
107 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
108
109 class AwContentsUserData : public base::SupportsUserData::Data {
110  public:
111   AwContentsUserData(AwContents* ptr) : contents_(ptr) {}
112
113   static AwContents* GetContents(WebContents* web_contents) {
114     if (!web_contents)
115       return NULL;
116     AwContentsUserData* data = reinterpret_cast<AwContentsUserData*>(
117         web_contents->GetUserData(kAwContentsUserDataKey));
118     return data ? data->contents_ : NULL;
119   }
120
121  private:
122   AwContents* contents_;
123 };
124
125 base::subtle::Atomic32 g_instance_count = 0;
126
127 void OnIoThreadClientReady(content::RenderFrameHost* rfh) {
128   int render_process_id = rfh->GetProcess()->GetID();
129   int render_frame_id = rfh->GetRoutingID();
130   AwResourceDispatcherHostDelegate::OnIoThreadClientReady(
131       render_process_id, render_frame_id);
132 }
133
134 }  // namespace
135
136 // static
137 AwContents* AwContents::FromWebContents(WebContents* web_contents) {
138   return AwContentsUserData::GetContents(web_contents);
139 }
140
141 // static
142 AwContents* AwContents::FromID(int render_process_id, int render_view_id) {
143   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144   const content::RenderViewHost* rvh =
145       content::RenderViewHost::FromID(render_process_id, render_view_id);
146   if (!rvh) return NULL;
147   content::WebContents* web_contents =
148       content::WebContents::FromRenderViewHost(rvh);
149   if (!web_contents) return NULL;
150   return FromWebContents(web_contents);
151 }
152
153 AwContents::AwContents(scoped_ptr<WebContents> web_contents)
154     : weak_factory_on_ui_thread_(this),
155       ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
156       web_contents_(web_contents.Pass()),
157       shared_renderer_state_(
158           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
159           this),
160       browser_view_renderer_(
161           this,
162           &shared_renderer_state_,
163           web_contents_.get(),
164           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)),
165       renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()) {
166   base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1);
167   icon_helper_.reset(new IconHelper(web_contents_.get()));
168   icon_helper_->SetListener(this);
169   web_contents_->SetUserData(kAwContentsUserDataKey,
170                              new AwContentsUserData(this));
171   render_view_host_ext_.reset(
172       new AwRenderViewHostExt(this, web_contents_.get()));
173
174   permission_request_handler_.reset(new PermissionRequestHandler(this));
175
176   AwAutofillManagerDelegate* autofill_manager_delegate =
177       AwAutofillManagerDelegate::FromWebContents(web_contents_.get());
178   InitDataReductionProxyIfNecessary();
179   if (autofill_manager_delegate)
180     InitAutofillIfNecessary(autofill_manager_delegate->GetSaveFormData());
181 }
182
183 void AwContents::SetJavaPeers(JNIEnv* env,
184                               jobject obj,
185                               jobject aw_contents,
186                               jobject web_contents_delegate,
187                               jobject contents_client_bridge,
188                               jobject io_thread_client,
189                               jobject intercept_navigation_delegate) {
190   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191   // The |aw_content| param is technically spurious as it duplicates |obj| but
192   // is passed over anyway to make the binding more explicit.
193   java_ref_ = JavaObjectWeakGlobalRef(env, aw_contents);
194
195   web_contents_delegate_.reset(
196       new AwWebContentsDelegate(env, web_contents_delegate));
197   web_contents_->SetDelegate(web_contents_delegate_.get());
198
199   contents_client_bridge_.reset(
200       new AwContentsClientBridge(env, contents_client_bridge));
201   AwContentsClientBridgeBase::Associate(web_contents_.get(),
202                                         contents_client_bridge_.get());
203
204   AwContentsIoThreadClientImpl::Associate(
205       web_contents_.get(), ScopedJavaLocalRef<jobject>(env, io_thread_client));
206
207   InterceptNavigationDelegate::Associate(
208       web_contents_.get(),
209       make_scoped_ptr(new InterceptNavigationDelegate(
210           env, intercept_navigation_delegate)));
211
212   // Finally, having setup the associations, release any deferred requests
213   web_contents_->ForEachFrame(base::Bind(&OnIoThreadClientReady));
214 }
215
216 void AwContents::SetSaveFormData(bool enabled) {
217   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
218   InitAutofillIfNecessary(enabled);
219   // We need to check for the existence, since autofill_manager_delegate
220   // may not be created when the setting is false.
221   if (ContentAutofillDriver::FromWebContents(web_contents_.get())) {
222     AwAutofillManagerDelegate::FromWebContents(web_contents_.get())->
223         SetSaveFormData(enabled);
224   }
225 }
226
227 void AwContents::InitDataReductionProxyIfNecessary() {
228   AwBrowserContext* browser_context =
229       AwBrowserContext::FromWebContents(web_contents_.get());
230   browser_context->CreateUserPrefServiceIfNecessary();
231 }
232
233 void AwContents::InitAutofillIfNecessary(bool enabled) {
234   // Do not initialize if the feature is not enabled.
235   if (!enabled)
236     return;
237   // Check if the autofill driver already exists.
238   content::WebContents* web_contents = web_contents_.get();
239   if (ContentAutofillDriver::FromWebContents(web_contents))
240     return;
241
242   AwBrowserContext::FromWebContents(web_contents)->
243       CreateUserPrefServiceIfNecessary();
244   AwAutofillManagerDelegate::CreateForWebContents(web_contents);
245   ContentAutofillDriver::CreateForWebContentsAndDelegate(
246       web_contents,
247       AwAutofillManagerDelegate::FromWebContents(web_contents),
248       l10n_util::GetDefaultLocale(),
249       AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
250 }
251
252 void AwContents::SetAwAutofillManagerDelegate(jobject delegate) {
253   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254   JNIEnv* env = AttachCurrentThread();
255   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
256   if (obj.is_null())
257     return;
258   Java_AwContents_setAwAutofillManagerDelegate(env, obj.obj(), delegate);
259 }
260
261 AwContents::~AwContents() {
262   DCHECK(AwContents::FromWebContents(web_contents_.get()) == this);
263   DCHECK(!hardware_renderer_.get());
264   web_contents_->RemoveUserData(kAwContentsUserDataKey);
265   if (find_helper_.get())
266     find_helper_->SetListener(NULL);
267   if (icon_helper_.get())
268     icon_helper_->SetListener(NULL);
269   base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, -1);
270   // When the last WebView is destroyed free all discardable memory allocated by
271   // Chromium, because the app process may continue to run for a long time
272   // without ever using another WebView.
273   if (base::subtle::NoBarrier_Load(&g_instance_count) == 0) {
274     base::MemoryPressureListener::NotifyMemoryPressure(
275         base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
276   }
277 }
278
279 jlong AwContents::GetWebContents(JNIEnv* env, jobject obj) {
280   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
281   DCHECK(web_contents_);
282   return reinterpret_cast<intptr_t>(web_contents_.get());
283 }
284
285 void AwContents::Destroy(JNIEnv* env, jobject obj) {
286   java_ref_.reset();
287   // We do not delete AwContents immediately. Some applications try to delete
288   // Webview in ShouldOverrideUrlLoading callback, which is a sync IPC from
289   // Webkit.
290   BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
291 }
292
293 static jlong Init(JNIEnv* env, jclass, jobject browser_context) {
294   // TODO(joth): Use |browser_context| to get the native BrowserContext, rather
295   // than hard-code the default instance lookup here.
296   scoped_ptr<WebContents> web_contents(content::WebContents::Create(
297       content::WebContents::CreateParams(AwBrowserContext::GetDefault())));
298   // Return an 'uninitialized' instance; most work is deferred until the
299   // subsequent SetJavaPeers() call.
300   return reinterpret_cast<intptr_t>(new AwContents(web_contents.Pass()));
301 }
302
303 static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass,
304                                      jlong function_table) {
305   JavaBrowserViewRendererHelper::SetAwDrawSWFunctionTable(
306       reinterpret_cast<AwDrawSWFunctionTable*>(function_table));
307 }
308
309 static void SetAwDrawGLFunctionTable(JNIEnv* env, jclass,
310                                      jlong function_table) {
311   GpuMemoryBufferFactoryImpl::SetAwDrawGLFunctionTable(
312       reinterpret_cast<AwDrawGLFunctionTable*>(function_table));
313 }
314
315 static jlong GetAwDrawGLFunction(JNIEnv* env, jclass) {
316   return reinterpret_cast<intptr_t>(&DrawGLFunction);
317 }
318
319 // static
320 jint GetNativeInstanceCount(JNIEnv* env, jclass) {
321   return base::subtle::NoBarrier_Load(&g_instance_count);
322 }
323
324 jlong AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) {
325   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
326   return reinterpret_cast<intptr_t>(this);
327 }
328
329 void AwContents::DrawGL(AwDrawGLInfo* draw_info) {
330   GLViewRendererManager::GetInstance()->DidDrawGL(renderer_manager_key_);
331
332   ScopedAppGLStateRestore state_restore(
333       draw_info->mode == AwDrawGLInfo::kModeDraw
334           ? ScopedAppGLStateRestore::MODE_DRAW
335           : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
336   ScopedAllowGL allow_gl;
337
338   for (base::Closure c = shared_renderer_state_.PopFrontClosure(); !c.is_null();
339        c = shared_renderer_state_.PopFrontClosure()) {
340     c.Run();
341   }
342
343   if (!hardware_renderer_)
344     return;
345
346   // TODO(boliu): Make this a task as well.
347   DrawGLResult result;
348   if (hardware_renderer_->DrawGL(state_restore.stencil_enabled(),
349                                  state_restore.framebuffer_binding_ext(),
350                                  draw_info,
351                                  &result)) {
352     content::BrowserThread::PostTask(
353         content::BrowserThread::UI,
354         FROM_HERE,
355         base::Bind(&AwContents::DidDrawGL, ui_thread_weak_ptr_, result));
356   }
357 }
358
359 void AwContents::DidDrawGL(const DrawGLResult& result) {
360   browser_view_renderer_.DidDrawGL(result);
361 }
362
363 namespace {
364 void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message,
365                                bool has_images) {
366   Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(),
367                                               has_images,
368                                               message.obj());
369 }
370 }  // namespace
371
372 void AwContents::DocumentHasImages(JNIEnv* env, jobject obj, jobject message) {
373   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
374   ScopedJavaGlobalRef<jobject> j_message;
375   j_message.Reset(env, message);
376   render_view_host_ext_->DocumentHasImages(
377       base::Bind(&DocumentHasImagesCallback, j_message));
378 }
379
380 namespace {
381 void GenerateMHTMLCallback(ScopedJavaGlobalRef<jobject>* callback,
382                            const base::FilePath& path, int64 size) {
383   JNIEnv* env = AttachCurrentThread();
384   // Android files are UTF8, so the path conversion below is safe.
385   Java_AwContents_generateMHTMLCallback(
386       env,
387       ConvertUTF8ToJavaString(env, path.AsUTF8Unsafe()).obj(),
388       size, callback->obj());
389 }
390 }  // namespace
391
392 void AwContents::GenerateMHTML(JNIEnv* env, jobject obj,
393                                jstring jpath, jobject callback) {
394   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395   ScopedJavaGlobalRef<jobject>* j_callback = new ScopedJavaGlobalRef<jobject>();
396   j_callback->Reset(env, callback);
397   base::FilePath target_path(ConvertJavaStringToUTF8(env, jpath));
398   web_contents_->GenerateMHTML(
399       target_path,
400       base::Bind(&GenerateMHTMLCallback, base::Owned(j_callback), target_path));
401 }
402
403 void AwContents::CreatePdfExporter(JNIEnv* env,
404                                    jobject obj,
405                                    jobject pdfExporter) {
406   pdf_exporter_.reset(
407       new AwPdfExporter(env,
408                         pdfExporter,
409                         web_contents_.get()));
410 }
411
412 bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler,
413                                            const std::string& host,
414                                            const std::string& realm) {
415   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
416   JNIEnv* env = AttachCurrentThread();
417   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
418   if (obj.is_null())
419     return false;
420
421   ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host);
422   ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm);
423   devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
424       "onReceivedHttpAuthRequest");
425   Java_AwContents_onReceivedHttpAuthRequest(env, obj.obj(), handler.obj(),
426       jhost.obj(), jrealm.obj());
427   return true;
428 }
429
430 void AwContents::AddVisitedLinks(JNIEnv* env,
431                                    jobject obj,
432                                    jobjectArray jvisited_links) {
433   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
434   std::vector<base::string16> visited_link_strings;
435   base::android::AppendJavaStringArrayToStringVector(
436       env, jvisited_links, &visited_link_strings);
437
438   std::vector<GURL> visited_link_gurls;
439   std::vector<base::string16>::const_iterator itr;
440   for (itr = visited_link_strings.begin(); itr != visited_link_strings.end();
441        ++itr) {
442     visited_link_gurls.push_back(GURL(*itr));
443   }
444
445   AwBrowserContext::FromWebContents(web_contents_.get())
446       ->AddVisitedURLs(visited_link_gurls);
447 }
448
449 bool RegisterAwContents(JNIEnv* env) {
450   return RegisterNativesImpl(env);
451 }
452
453 namespace {
454
455 void ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef& java_ref,
456                                      const GURL& origin) {
457   JNIEnv* env = AttachCurrentThread();
458   ScopedJavaLocalRef<jobject> j_ref = java_ref.get(env);
459   if (j_ref.obj()) {
460     ScopedJavaLocalRef<jstring> j_origin(
461         ConvertUTF8ToJavaString(env, origin.spec()));
462     devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
463         "onGeolocationPermissionsShowPrompt");
464     Java_AwContents_onGeolocationPermissionsShowPrompt(env,
465                                                        j_ref.obj(),
466                                                        j_origin.obj());
467   }
468 }
469
470 void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref,
471                                  const GURL& origin) {
472   JNIEnv* env = AttachCurrentThread();
473   if (java_ref.get(env).obj()) {
474     content::BrowserThread::PostTask(
475         content::BrowserThread::UI,
476         FROM_HERE,
477         base::Bind(&ShowGeolocationPromptHelperTask,
478                    java_ref,
479                    origin));
480   }
481 }
482
483 } // anonymous namespace
484
485 void AwContents::ShowGeolocationPrompt(const GURL& requesting_frame,
486                                        base::Callback<void(bool)> callback) {
487   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
488
489   GURL origin = requesting_frame.GetOrigin();
490   bool show_prompt = pending_geolocation_prompts_.empty();
491   pending_geolocation_prompts_.push_back(OriginCallback(origin, callback));
492   if (show_prompt) {
493     ShowGeolocationPromptHelper(java_ref_, origin);
494   }
495 }
496
497 // Invoked from Java
498 void AwContents::InvokeGeolocationCallback(JNIEnv* env,
499                                            jobject obj,
500                                            jboolean value,
501                                            jstring origin) {
502   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
503
504   GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin));
505   if (callback_origin.GetOrigin() ==
506       pending_geolocation_prompts_.front().first) {
507     pending_geolocation_prompts_.front().second.Run(value);
508     pending_geolocation_prompts_.pop_front();
509     if (!pending_geolocation_prompts_.empty()) {
510       ShowGeolocationPromptHelper(java_ref_,
511                                   pending_geolocation_prompts_.front().first);
512     }
513   }
514 }
515
516 void AwContents::HideGeolocationPrompt(const GURL& origin) {
517   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
518   bool removed_current_outstanding_callback = false;
519   std::list<OriginCallback>::iterator it = pending_geolocation_prompts_.begin();
520   while (it != pending_geolocation_prompts_.end()) {
521     if ((*it).first == origin.GetOrigin()) {
522       if (it == pending_geolocation_prompts_.begin()) {
523         removed_current_outstanding_callback = true;
524       }
525       it = pending_geolocation_prompts_.erase(it);
526     } else {
527       ++it;
528     }
529   }
530
531   if (removed_current_outstanding_callback) {
532     JNIEnv* env = AttachCurrentThread();
533     ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
534     if (j_ref.obj()) {
535       devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
536           "onGeolocationPermissionsHidePrompt");
537       Java_AwContents_onGeolocationPermissionsHidePrompt(env, j_ref.obj());
538     }
539     if (!pending_geolocation_prompts_.empty()) {
540       ShowGeolocationPromptHelper(java_ref_,
541                             pending_geolocation_prompts_.front().first);
542     }
543   }
544 }
545
546 void AwContents::OnPermissionRequest(AwPermissionRequest* request) {
547   JNIEnv* env = AttachCurrentThread();
548   ScopedJavaLocalRef<jobject> j_request = request->CreateJavaPeer();
549   ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
550   if (j_request.is_null() || j_ref.is_null()) {
551     permission_request_handler_->CancelRequest(
552         request->GetOrigin(), request->GetResources());
553     return;
554   }
555
556   Java_AwContents_onPermissionRequest(env, j_ref.obj(), j_request.obj());
557 }
558
559 void AwContents::OnPermissionRequestCanceled(AwPermissionRequest* request) {
560   JNIEnv* env = AttachCurrentThread();
561   ScopedJavaLocalRef<jobject> j_request = request->GetJavaObject();
562   ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
563   if (j_request.is_null() || j_ref.is_null())
564     return;
565
566   Java_AwContents_onPermissionRequestCanceled(
567       env, j_ref.obj(), j_request.obj());
568 }
569
570 void AwContents::PreauthorizePermission(
571     JNIEnv* env,
572     jobject obj,
573     jstring origin,
574     jlong resources) {
575   permission_request_handler_->PreauthorizePermission(
576       GURL(base::android::ConvertJavaStringToUTF8(env, origin)), resources);
577 }
578
579 void AwContents::FindAllAsync(JNIEnv* env, jobject obj, jstring search_string) {
580   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
581   GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string));
582 }
583
584 void AwContents::FindNext(JNIEnv* env, jobject obj, jboolean forward) {
585   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
586   GetFindHelper()->FindNext(forward);
587 }
588
589 void AwContents::ClearMatches(JNIEnv* env, jobject obj) {
590   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
591   GetFindHelper()->ClearMatches();
592 }
593
594 void AwContents::ClearCache(
595     JNIEnv* env,
596     jobject obj,
597     jboolean include_disk_files) {
598   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
599   render_view_host_ext_->ClearCache();
600
601   if (include_disk_files) {
602     RemoveHttpDiskCache(web_contents_->GetBrowserContext(),
603                         web_contents_->GetRoutingID());
604   }
605 }
606
607 FindHelper* AwContents::GetFindHelper() {
608   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
609   if (!find_helper_.get()) {
610     find_helper_.reset(new FindHelper(web_contents_.get()));
611     find_helper_->SetListener(this);
612   }
613   return find_helper_.get();
614 }
615
616 void AwContents::OnFindResultReceived(int active_ordinal,
617                                       int match_count,
618                                       bool finished) {
619   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
620   JNIEnv* env = AttachCurrentThread();
621   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
622   if (obj.is_null())
623     return;
624
625   Java_AwContents_onFindResultReceived(
626       env, obj.obj(), active_ordinal, match_count, finished);
627 }
628
629 bool AwContents::ShouldDownloadFavicon(const GURL& icon_url) {
630   return g_should_download_favicons;
631 }
632
633 void AwContents::OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap) {
634   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
635   JNIEnv* env = AttachCurrentThread();
636   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
637   if (obj.is_null())
638     return;
639
640   content::NavigationEntry* entry =
641       web_contents_->GetController().GetActiveEntry();
642
643   if (entry) {
644     entry->GetFavicon().valid = true;
645     entry->GetFavicon().url = icon_url;
646     entry->GetFavicon().image = gfx::Image::CreateFrom1xBitmap(bitmap);
647   }
648
649   Java_AwContents_onReceivedIcon(
650       env, obj.obj(), gfx::ConvertToJavaBitmap(&bitmap).obj());
651 }
652
653 void AwContents::OnReceivedTouchIconUrl(const std::string& url,
654                                         bool precomposed) {
655   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
656   JNIEnv* env = AttachCurrentThread();
657   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
658   if (obj.is_null())
659     return;
660
661   Java_AwContents_onReceivedTouchIconUrl(
662       env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed);
663 }
664
665 bool AwContents::RequestDrawGL(jobject canvas, bool wait_for_completion) {
666   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
667   DCHECK(!canvas || !wait_for_completion);
668   JNIEnv* env = AttachCurrentThread();
669   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
670   if (obj.is_null())
671     return false;
672   return Java_AwContents_requestDrawGL(
673       env, obj.obj(), canvas, wait_for_completion);
674 }
675
676 void AwContents::PostInvalidate() {
677   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
678   JNIEnv* env = AttachCurrentThread();
679   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
680   if (!obj.is_null())
681     Java_AwContents_postInvalidateOnAnimation(env, obj.obj());
682 }
683
684 void AwContents::OnNewPicture() {
685   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
686   JNIEnv* env = AttachCurrentThread();
687   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
688   if (!obj.is_null()) {
689     devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
690         "onNewPicture");
691     Java_AwContents_onNewPicture(env, obj.obj());
692   }
693 }
694
695 base::android::ScopedJavaLocalRef<jbyteArray>
696     AwContents::GetCertificate(JNIEnv* env,
697                                jobject obj) {
698   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
699   content::NavigationEntry* entry =
700       web_contents_->GetController().GetActiveEntry();
701   if (!entry)
702     return ScopedJavaLocalRef<jbyteArray>();
703   // Get the certificate
704   int cert_id = entry->GetSSL().cert_id;
705   scoped_refptr<net::X509Certificate> cert;
706   bool ok = content::CertStore::GetInstance()->RetrieveCert(cert_id, &cert);
707   if (!ok)
708     return ScopedJavaLocalRef<jbyteArray>();
709
710   // Convert the certificate and return it
711   std::string der_string;
712   net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_string);
713   return base::android::ToJavaByteArray(env,
714       reinterpret_cast<const uint8*>(der_string.data()), der_string.length());
715 }
716
717 void AwContents::RequestNewHitTestDataAt(JNIEnv* env, jobject obj,
718                                          jint x, jint y) {
719   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
720   render_view_host_ext_->RequestNewHitTestDataAt(x, y);
721 }
722
723 void AwContents::UpdateLastHitTestData(JNIEnv* env, jobject obj) {
724   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
725   if (!render_view_host_ext_->HasNewHitTestData()) return;
726
727   const AwHitTestData& data = render_view_host_ext_->GetLastHitTestData();
728   render_view_host_ext_->MarkHitTestDataRead();
729
730   // Make sure to null the Java object if data is empty/invalid.
731   ScopedJavaLocalRef<jstring> extra_data_for_type;
732   if (data.extra_data_for_type.length())
733     extra_data_for_type = ConvertUTF8ToJavaString(
734         env, data.extra_data_for_type);
735
736   ScopedJavaLocalRef<jstring> href;
737   if (data.href.length())
738     href = ConvertUTF16ToJavaString(env, data.href);
739
740   ScopedJavaLocalRef<jstring> anchor_text;
741   if (data.anchor_text.length())
742     anchor_text = ConvertUTF16ToJavaString(env, data.anchor_text);
743
744   ScopedJavaLocalRef<jstring> img_src;
745   if (data.img_src.is_valid())
746     img_src = ConvertUTF8ToJavaString(env, data.img_src.spec());
747
748   Java_AwContents_updateHitTestData(env,
749                                     obj,
750                                     data.type,
751                                     extra_data_for_type.obj(),
752                                     href.obj(),
753                                     anchor_text.obj(),
754                                     img_src.obj());
755 }
756
757 void AwContents::OnSizeChanged(JNIEnv* env, jobject obj,
758                                int w, int h, int ow, int oh) {
759   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
760   browser_view_renderer_.OnSizeChanged(w, h);
761 }
762
763 void AwContents::SetViewVisibility(JNIEnv* env, jobject obj, bool visible) {
764   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
765   browser_view_renderer_.SetViewVisibility(visible);
766 }
767
768 void AwContents::SetWindowVisibility(JNIEnv* env, jobject obj, bool visible) {
769   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
770   browser_view_renderer_.SetWindowVisibility(visible);
771 }
772
773 void AwContents::SetIsPaused(JNIEnv* env, jobject obj, bool paused) {
774   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
775   browser_view_renderer_.SetIsPaused(paused);
776   ContentViewCore* cvc =
777       ContentViewCore::FromWebContents(web_contents_.get());
778   if (cvc) {
779     cvc->PauseOrResumeGeolocation(paused);
780     if (paused) {
781       cvc->PauseVideo();
782     }
783   }
784 }
785
786 void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) {
787   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
788   browser_view_renderer_.OnAttachedToWindow(w, h);
789 }
790
791 void AwContents::InitializeHardwareDrawIfNeeded() {
792   GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
793   if (renderer_manager_key_ == manager->NullKey()) {
794     // Add task but don't schedule it. It will run when DrawGL is called for
795     // the first time.
796     shared_renderer_state_.AppendClosure(
797         base::Bind(&AwContents::InitializeHardwareDrawOnRenderThread,
798                    base::Unretained(this)));
799     renderer_manager_key_ = manager->PushBack(&shared_renderer_state_);
800     DeferredGpuCommandService::SetInstance();
801   }
802 }
803
804 void AwContents::InitializeHardwareDrawOnRenderThread() {
805   DCHECK(!hardware_renderer_);
806   DCHECK(!shared_renderer_state_.IsHardwareInitialized());
807   hardware_renderer_.reset(new HardwareRenderer(&shared_renderer_state_));
808   shared_renderer_state_.SetHardwareInitialized(true);
809 }
810
811 void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) {
812   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
813
814   shared_renderer_state_.ClearClosureQueue();
815   shared_renderer_state_.AppendClosure(base::Bind(
816       &AwContents::ReleaseHardwareDrawOnRenderThread, base::Unretained(this)));
817   bool draw_functor_succeeded = RequestDrawGL(NULL, true);
818   if (!draw_functor_succeeded &&
819       shared_renderer_state_.IsHardwareInitialized()) {
820     LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?";
821     // Calling release on wrong thread intentionally.
822     AwDrawGLInfo info;
823     info.mode = AwDrawGLInfo::kModeProcess;
824     DrawGL(&info);
825   } else {
826     shared_renderer_state_.ClearClosureQueue();
827   }
828
829   browser_view_renderer_.OnDetachedFromWindow();
830
831   GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
832   if (renderer_manager_key_ != manager->NullKey()) {
833     manager->Remove(renderer_manager_key_);
834     renderer_manager_key_ = manager->NullKey();
835   }
836 }
837
838 void AwContents::ReleaseHardwareDrawOnRenderThread() {
839   // No point in running any other commands if we released hardware already.
840   shared_renderer_state_.ClearClosureQueue();
841   if (!shared_renderer_state_.IsHardwareInitialized())
842     return;
843
844   hardware_renderer_.reset();
845   shared_renderer_state_.SetHardwareInitialized(false);
846 }
847
848 base::android::ScopedJavaLocalRef<jbyteArray>
849 AwContents::GetOpaqueState(JNIEnv* env, jobject obj) {
850   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
851   // Required optimization in WebViewClassic to not save any state if
852   // there has been no navigations.
853   if (!web_contents_->GetController().GetEntryCount())
854     return ScopedJavaLocalRef<jbyteArray>();
855
856   Pickle pickle;
857   if (!WriteToPickle(*web_contents_, &pickle)) {
858     return ScopedJavaLocalRef<jbyteArray>();
859   } else {
860     return base::android::ToJavaByteArray(env,
861        reinterpret_cast<const uint8*>(pickle.data()), pickle.size());
862   }
863 }
864
865 jboolean AwContents::RestoreFromOpaqueState(
866     JNIEnv* env, jobject obj, jbyteArray state) {
867   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
868   // TODO(boliu): This copy can be optimized out if this is a performance
869   // problem.
870   std::vector<uint8> state_vector;
871   base::android::JavaByteArrayToByteVector(env, state, &state_vector);
872
873   Pickle pickle(reinterpret_cast<const char*>(state_vector.begin()),
874                 state_vector.size());
875   PickleIterator iterator(pickle);
876
877   return RestoreFromPickle(&iterator, web_contents_.get());
878 }
879
880 bool AwContents::OnDraw(JNIEnv* env,
881                         jobject obj,
882                         jobject canvas,
883                         jboolean is_hardware_accelerated,
884                         jint scroll_x,
885                         jint scroll_y,
886                         jint visible_left,
887                         jint visible_top,
888                         jint visible_right,
889                         jint visible_bottom,
890                         jint clip_left,
891                         jint clip_top,
892                         jint clip_right,
893                         jint clip_bottom) {
894   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
895   if (is_hardware_accelerated)
896     InitializeHardwareDrawIfNeeded();
897   return browser_view_renderer_.OnDraw(
898       canvas,
899       is_hardware_accelerated,
900       gfx::Vector2d(scroll_x, scroll_y),
901       gfx::Rect(visible_left,
902                 visible_top,
903                 visible_right - visible_left,
904                 visible_bottom - visible_top),
905       gfx::Rect(
906           clip_left, clip_top, clip_right - clip_left, clip_bottom - clip_top));
907 }
908
909 void AwContents::SetPendingWebContentsForPopup(
910     scoped_ptr<content::WebContents> pending) {
911   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
912   if (pending_contents_.get()) {
913     // TODO(benm): Support holding multiple pop up window requests.
914     LOG(WARNING) << "Blocking popup window creation as an outstanding "
915                  << "popup window is still pending.";
916     base::MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release());
917     return;
918   }
919   pending_contents_.reset(new AwContents(pending.Pass()));
920 }
921
922 void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) {
923   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
924   web_contents_->FocusThroughTabTraversal(false);
925 }
926
927 void AwContents::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) {
928   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
929   render_view_host_ext_->SetBackgroundColor(color);
930 }
931
932 jlong AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) {
933   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
934   return reinterpret_cast<intptr_t>(pending_contents_.release());
935 }
936
937 gfx::Point AwContents::GetLocationOnScreen() {
938   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
939   JNIEnv* env = AttachCurrentThread();
940   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
941   if (obj.is_null())
942     return gfx::Point();
943   std::vector<int> location;
944   base::android::JavaIntArrayToIntVector(
945       env,
946       Java_AwContents_getLocationOnScreen(env, obj.obj()).obj(),
947       &location);
948   return gfx::Point(location[0], location[1]);
949 }
950
951 void AwContents::SetMaxContainerViewScrollOffset(gfx::Vector2d new_value) {
952   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
953   JNIEnv* env = AttachCurrentThread();
954   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
955   if (obj.is_null())
956     return;
957   Java_AwContents_setMaxContainerViewScrollOffset(
958       env, obj.obj(), new_value.x(), new_value.y());
959 }
960
961 void AwContents::ScrollContainerViewTo(gfx::Vector2d new_value) {
962   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
963   JNIEnv* env = AttachCurrentThread();
964   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
965   if (obj.is_null())
966     return;
967   Java_AwContents_scrollContainerViewTo(
968       env, obj.obj(), new_value.x(), new_value.y());
969 }
970
971 bool AwContents::IsFlingActive() const {
972   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
973   JNIEnv* env = AttachCurrentThread();
974   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
975   if (obj.is_null())
976     return false;
977   return Java_AwContents_isFlingActive(env, obj.obj());
978 }
979
980 void AwContents::SetPageScaleFactorAndLimits(
981     float page_scale_factor,
982     float min_page_scale_factor,
983     float max_page_scale_factor) {
984   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
985   JNIEnv* env = AttachCurrentThread();
986   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
987   if (obj.is_null())
988     return;
989   Java_AwContents_setPageScaleFactorAndLimits(env,
990                                               obj.obj(),
991                                               page_scale_factor,
992                                               min_page_scale_factor,
993                                               max_page_scale_factor);
994 }
995
996 void AwContents::SetContentsSize(gfx::SizeF contents_size_dip) {
997   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
998   JNIEnv* env = AttachCurrentThread();
999   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1000   if (obj.is_null())
1001     return;
1002   Java_AwContents_setContentsSize(
1003       env, obj.obj(), contents_size_dip.width(), contents_size_dip.height());
1004 }
1005
1006 void AwContents::DidOverscroll(gfx::Vector2d overscroll_delta) {
1007   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1008   JNIEnv* env = AttachCurrentThread();
1009   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1010   if (obj.is_null())
1011     return;
1012   Java_AwContents_didOverscroll(
1013       env, obj.obj(), overscroll_delta.x(), overscroll_delta.y());
1014 }
1015
1016 const BrowserViewRenderer* AwContents::GetBrowserViewRenderer() const {
1017   return &browser_view_renderer_;
1018 }
1019
1020 void AwContents::SetDipScale(JNIEnv* env, jobject obj, jfloat dip_scale) {
1021   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1022   browser_view_renderer_.SetDipScale(dip_scale);
1023 }
1024
1025 void AwContents::SetFixedLayoutSize(JNIEnv* env,
1026                                     jobject obj,
1027                                     jint width_dip,
1028                                     jint height_dip) {
1029   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1030   render_view_host_ext_->SetFixedLayoutSize(gfx::Size(width_dip, height_dip));
1031 }
1032
1033 void AwContents::ScrollTo(JNIEnv* env, jobject obj, jint x, jint y) {
1034   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1035   browser_view_renderer_.ScrollTo(gfx::Vector2d(x, y));
1036 }
1037
1038 void AwContents::OnWebLayoutPageScaleFactorChanged(float page_scale_factor) {
1039   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1040   JNIEnv* env = AttachCurrentThread();
1041   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1042   if (obj.is_null())
1043     return;
1044   Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj.obj(),
1045                                                          page_scale_factor);
1046 }
1047
1048 void AwContents::OnWebLayoutContentsSizeChanged(
1049     const gfx::Size& contents_size) {
1050   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1051   JNIEnv* env = AttachCurrentThread();
1052   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1053   if (obj.is_null())
1054     return;
1055   Java_AwContents_onWebLayoutContentsSizeChanged(
1056       env, obj.obj(), contents_size.width(), contents_size.height());
1057 }
1058
1059 jlong AwContents::CapturePicture(JNIEnv* env,
1060                                  jobject obj,
1061                                  int width,
1062                                  int height) {
1063   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1064   return reinterpret_cast<intptr_t>(
1065       new AwPicture(browser_view_renderer_.CapturePicture(width, height)));
1066 }
1067
1068 void AwContents::EnableOnNewPicture(JNIEnv* env,
1069                                     jobject obj,
1070                                     jboolean enabled) {
1071   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1072   browser_view_renderer_.EnableOnNewPicture(enabled);
1073 }
1074
1075 void AwContents::ClearView(JNIEnv* env, jobject obj) {
1076   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1077   browser_view_renderer_.ClearView();
1078 }
1079
1080 void AwContents::SetExtraHeadersForUrl(JNIEnv* env, jobject obj,
1081                                        jstring url, jstring jextra_headers) {
1082   std::string extra_headers;
1083   if (jextra_headers)
1084     extra_headers = ConvertJavaStringToUTF8(env, jextra_headers);
1085   AwResourceContext* resource_context = static_cast<AwResourceContext*>(
1086       AwBrowserContext::FromWebContents(web_contents_.get())->
1087       GetResourceContext());
1088   resource_context->SetExtraHeaders(GURL(ConvertJavaStringToUTF8(env, url)),
1089                                     extra_headers);
1090 }
1091
1092 void AwContents::SetJsOnlineProperty(JNIEnv* env,
1093                                      jobject obj,
1094                                      jboolean network_up) {
1095   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1096   render_view_host_ext_->SetJsOnlineProperty(network_up);
1097 }
1098
1099 void AwContents::TrimMemory(JNIEnv* env,
1100                             jobject obj,
1101                             jint level,
1102                             jboolean visible) {
1103   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1104
1105   if (!shared_renderer_state_.IsHardwareInitialized())
1106     return;
1107
1108   browser_view_renderer_.TrimMemory(level, visible);
1109 }
1110
1111 void SetShouldDownloadFavicons(JNIEnv* env, jclass jclazz) {
1112   g_should_download_favicons = true;
1113 }
1114
1115 }  // namespace android_webview