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