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 71 struct AwDrawSWFunctionTable; 72 struct AwDrawGLFunctionTable; 73 74 using autofill::ContentAutofillDriver; 75 using autofill::AutofillManager; 76 using base::android::AttachCurrentThread; 77 using base::android::ConvertJavaStringToUTF16; 78 using base::android::ConvertJavaStringToUTF8; 79 using base::android::ConvertUTF16ToJavaString; 80 using base::android::ConvertUTF8ToJavaString; 81 using base::android::JavaRef; 82 using base::android::ScopedJavaGlobalRef; 83 using base::android::ScopedJavaLocalRef; 84 using data_reduction_proxy::DataReductionProxySettings; 85 using navigation_interception::InterceptNavigationDelegate; 86 using content::BrowserThread; 87 using content::ContentViewCore; 88 using content::WebContents; 89 90 extern "C" { 91 static AwDrawGLFunction DrawGLFunction; 92 static 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 102 namespace android_webview { 103 104 namespace { 105 106 bool g_should_download_favicons = false; 107 108 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey; 109 110 class 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 126 base::subtle::Atomic32 g_instance_count = 0; 127 128 void 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 138 AwContents* AwContents::FromWebContents(WebContents* web_contents) { 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 140 return AwContentsUserData::GetContents(web_contents); 141 } 142 143 // static 144 AwContents* 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 155 AwBrowserPermissionRequestDelegate* 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 162 AwContents::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 191 void 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 224 void 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 235 void AwContents::InitDataReductionProxyIfNecessary() { 236 AwBrowserContext* browser_context = 237 AwBrowserContext::FromWebContents(web_contents_.get()); 238 browser_context->CreateUserPrefServiceIfNecessary(); 239 } 240 241 void 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 260 void 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 269 AwContents::~AwContents() { 270 DCHECK(AwContents::FromWebContents(web_contents_.get()) == this); 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 287 jlong 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 293 void 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 // We do not delete AwContents immediately. Some applications try to delete 304 // Webview in ShouldOverrideUrlLoading callback, which is a sync IPC from 305 // Webkit. 306 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); 307 } 308 309 static jlong Init(JNIEnv* env, jclass, jobject browser_context) { 310 // TODO(joth): Use |browser_context| to get the native BrowserContext, rather 311 // than hard-code the default instance lookup here. 312 scoped_ptr<WebContents> web_contents(content::WebContents::Create( 313 content::WebContents::CreateParams(AwBrowserContext::GetDefault()))); 314 // Return an 'uninitialized' instance; most work is deferred until the 315 // subsequent SetJavaPeers() call. 316 return reinterpret_cast<intptr_t>(new AwContents(web_contents.Pass())); 317 } 318 319 static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, 320 jlong function_table) { 321 JavaBrowserViewRendererHelper::SetAwDrawSWFunctionTable( 322 reinterpret_cast<AwDrawSWFunctionTable*>(function_table)); 323 } 324 325 static void SetAwDrawGLFunctionTable(JNIEnv* env, jclass, 326 jlong function_table) { 327 GpuMemoryBufferFactoryImpl::SetAwDrawGLFunctionTable( 328 reinterpret_cast<AwDrawGLFunctionTable*>(function_table)); 329 } 330 331 static jlong GetAwDrawGLFunction(JNIEnv* env, jclass) { 332 return reinterpret_cast<intptr_t>(&DrawGLFunction); 333 } 334 335 // static 336 jint GetNativeInstanceCount(JNIEnv* env, jclass) { 337 return base::subtle::NoBarrier_Load(&g_instance_count); 338 } 339 340 jlong AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) { 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 342 return reinterpret_cast<intptr_t>(this); 343 } 344 345 void AwContents::DrawGL(AwDrawGLInfo* draw_info) { 346 if (draw_info->mode == AwDrawGLInfo::kModeSync) { 347 if (hardware_renderer_) 348 hardware_renderer_->CommitFrame(); 349 return; 350 } 351 352 { 353 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); 354 base::AutoLock lock(render_thread_lock_); 355 if (renderer_manager_key_ != manager->NullKey()) { 356 manager->DidDrawGL(renderer_manager_key_); 357 } 358 } 359 360 ScopedAppGLStateRestore state_restore( 361 draw_info->mode == AwDrawGLInfo::kModeDraw 362 ? ScopedAppGLStateRestore::MODE_DRAW 363 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); 364 ScopedAllowGL allow_gl; 365 366 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { 367 LOG(ERROR) << "Received unexpected kModeProcessNoContext"; 368 } 369 370 // kModeProcessNoContext should never happen because we tear down hardware 371 // in onTrimMemory. However that guarantee is maintained outside of chromium 372 // code. Not notifying shared state in kModeProcessNoContext can lead to 373 // immediate deadlock, which is slightly more catastrophic than leaks or 374 // corruption. 375 if (draw_info->mode == AwDrawGLInfo::kModeProcess || 376 draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) { 377 shared_renderer_state_.DidDrawGLProcess(); 378 } 379 380 if (shared_renderer_state_.IsInsideHardwareRelease()) { 381 hardware_renderer_.reset(); 382 // Flush the idle queue in tear down. 383 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork(); 384 return; 385 } 386 387 if (draw_info->mode != AwDrawGLInfo::kModeDraw) { 388 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { 389 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true); 390 } 391 return; 392 } 393 394 if (!hardware_renderer_) { 395 hardware_renderer_.reset(new HardwareRenderer(&shared_renderer_state_)); 396 hardware_renderer_->CommitFrame(); 397 } 398 399 hardware_renderer_->DrawGL(state_restore.stencil_enabled(), 400 state_restore.framebuffer_binding_ext(), 401 draw_info); 402 DeferredGpuCommandService::GetInstance()->PerformIdleWork(false); 403 } 404 405 namespace { 406 void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message, 407 bool has_images) { 408 Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(), 409 has_images, 410 message.obj()); 411 } 412 } // namespace 413 414 void AwContents::DocumentHasImages(JNIEnv* env, jobject obj, jobject message) { 415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 416 ScopedJavaGlobalRef<jobject> j_message; 417 j_message.Reset(env, message); 418 render_view_host_ext_->DocumentHasImages( 419 base::Bind(&DocumentHasImagesCallback, j_message)); 420 } 421 422 namespace { 423 void GenerateMHTMLCallback(ScopedJavaGlobalRef<jobject>* callback, 424 const base::FilePath& path, int64 size) { 425 JNIEnv* env = AttachCurrentThread(); 426 // Android files are UTF8, so the path conversion below is safe. 427 Java_AwContents_generateMHTMLCallback( 428 env, 429 ConvertUTF8ToJavaString(env, path.AsUTF8Unsafe()).obj(), 430 size, callback->obj()); 431 } 432 } // namespace 433 434 void AwContents::GenerateMHTML(JNIEnv* env, jobject obj, 435 jstring jpath, jobject callback) { 436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 437 ScopedJavaGlobalRef<jobject>* j_callback = new ScopedJavaGlobalRef<jobject>(); 438 j_callback->Reset(env, callback); 439 base::FilePath target_path(ConvertJavaStringToUTF8(env, jpath)); 440 web_contents_->GenerateMHTML( 441 target_path, 442 base::Bind(&GenerateMHTMLCallback, base::Owned(j_callback), target_path)); 443 } 444 445 void AwContents::CreatePdfExporter(JNIEnv* env, 446 jobject obj, 447 jobject pdfExporter) { 448 pdf_exporter_.reset( 449 new AwPdfExporter(env, 450 pdfExporter, 451 web_contents_.get())); 452 } 453 454 bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler, 455 const std::string& host, 456 const std::string& realm) { 457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 458 JNIEnv* env = AttachCurrentThread(); 459 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 460 if (obj.is_null()) 461 return false; 462 463 ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host); 464 ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm); 465 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( 466 "onReceivedHttpAuthRequest"); 467 Java_AwContents_onReceivedHttpAuthRequest(env, obj.obj(), handler.obj(), 468 jhost.obj(), jrealm.obj()); 469 return true; 470 } 471 472 void AwContents::AddVisitedLinks(JNIEnv* env, 473 jobject obj, 474 jobjectArray jvisited_links) { 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 476 std::vector<base::string16> visited_link_strings; 477 base::android::AppendJavaStringArrayToStringVector( 478 env, jvisited_links, &visited_link_strings); 479 480 std::vector<GURL> visited_link_gurls; 481 std::vector<base::string16>::const_iterator itr; 482 for (itr = visited_link_strings.begin(); itr != visited_link_strings.end(); 483 ++itr) { 484 visited_link_gurls.push_back(GURL(*itr)); 485 } 486 487 AwBrowserContext::FromWebContents(web_contents_.get()) 488 ->AddVisitedURLs(visited_link_gurls); 489 } 490 491 bool RegisterAwContents(JNIEnv* env) { 492 return RegisterNativesImpl(env); 493 } 494 495 namespace { 496 497 void ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef& java_ref, 498 const GURL& origin) { 499 JNIEnv* env = AttachCurrentThread(); 500 ScopedJavaLocalRef<jobject> j_ref = java_ref.get(env); 501 if (j_ref.obj()) { 502 ScopedJavaLocalRef<jstring> j_origin( 503 ConvertUTF8ToJavaString(env, origin.spec())); 504 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( 505 "onGeolocationPermissionsShowPrompt"); 506 Java_AwContents_onGeolocationPermissionsShowPrompt(env, 507 j_ref.obj(), 508 j_origin.obj()); 509 } 510 } 511 512 void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref, 513 const GURL& origin) { 514 JNIEnv* env = AttachCurrentThread(); 515 if (java_ref.get(env).obj()) { 516 content::BrowserThread::PostTask( 517 content::BrowserThread::UI, 518 FROM_HERE, 519 base::Bind(&ShowGeolocationPromptHelperTask, 520 java_ref, 521 origin)); 522 } 523 } 524 525 } // anonymous namespace 526 527 void AwContents::ShowGeolocationPrompt(const GURL& requesting_frame, 528 base::Callback<void(bool)> callback) { 529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 530 531 GURL origin = requesting_frame.GetOrigin(); 532 bool show_prompt = pending_geolocation_prompts_.empty(); 533 pending_geolocation_prompts_.push_back(OriginCallback(origin, callback)); 534 if (show_prompt) { 535 ShowGeolocationPromptHelper(java_ref_, origin); 536 } 537 } 538 539 // Invoked from Java 540 void AwContents::InvokeGeolocationCallback(JNIEnv* env, 541 jobject obj, 542 jboolean value, 543 jstring origin) { 544 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 545 546 GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin)); 547 if (callback_origin.GetOrigin() == 548 pending_geolocation_prompts_.front().first) { 549 pending_geolocation_prompts_.front().second.Run(value); 550 pending_geolocation_prompts_.pop_front(); 551 if (!pending_geolocation_prompts_.empty()) { 552 ShowGeolocationPromptHelper(java_ref_, 553 pending_geolocation_prompts_.front().first); 554 } 555 } 556 } 557 558 void AwContents::HideGeolocationPrompt(const GURL& origin) { 559 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 560 bool removed_current_outstanding_callback = false; 561 std::list<OriginCallback>::iterator it = pending_geolocation_prompts_.begin(); 562 while (it != pending_geolocation_prompts_.end()) { 563 if ((*it).first == origin.GetOrigin()) { 564 if (it == pending_geolocation_prompts_.begin()) { 565 removed_current_outstanding_callback = true; 566 } 567 it = pending_geolocation_prompts_.erase(it); 568 } else { 569 ++it; 570 } 571 } 572 573 if (removed_current_outstanding_callback) { 574 JNIEnv* env = AttachCurrentThread(); 575 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); 576 if (j_ref.obj()) { 577 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( 578 "onGeolocationPermissionsHidePrompt"); 579 Java_AwContents_onGeolocationPermissionsHidePrompt(env, j_ref.obj()); 580 } 581 if (!pending_geolocation_prompts_.empty()) { 582 ShowGeolocationPromptHelper(java_ref_, 583 pending_geolocation_prompts_.front().first); 584 } 585 } 586 } 587 588 void AwContents::OnPermissionRequest(AwPermissionRequest* request) { 589 JNIEnv* env = AttachCurrentThread(); 590 ScopedJavaLocalRef<jobject> j_request = request->CreateJavaPeer(); 591 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); 592 if (j_request.is_null() || j_ref.is_null()) { 593 permission_request_handler_->CancelRequest( 594 request->GetOrigin(), request->GetResources()); 595 return; 596 } 597 598 Java_AwContents_onPermissionRequest(env, j_ref.obj(), j_request.obj()); 599 } 600 601 void AwContents::OnPermissionRequestCanceled(AwPermissionRequest* request) { 602 JNIEnv* env = AttachCurrentThread(); 603 ScopedJavaLocalRef<jobject> j_request = request->GetJavaObject(); 604 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); 605 if (j_request.is_null() || j_ref.is_null()) 606 return; 607 608 Java_AwContents_onPermissionRequestCanceled( 609 env, j_ref.obj(), j_request.obj()); 610 } 611 612 void AwContents::PreauthorizePermission( 613 JNIEnv* env, 614 jobject obj, 615 jstring origin, 616 jlong resources) { 617 permission_request_handler_->PreauthorizePermission( 618 GURL(base::android::ConvertJavaStringToUTF8(env, origin)), resources); 619 } 620 621 void AwContents::RequestProtectedMediaIdentifierPermission( 622 const GURL& origin, 623 const base::Callback<void(bool)>& callback) { 624 permission_request_handler_->SendRequest( 625 scoped_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest( 626 origin, AwPermissionRequest::ProtectedMediaId, callback))); 627 } 628 629 void AwContents::CancelProtectedMediaIdentifierPermissionRequests( 630 const GURL& origin) { 631 permission_request_handler_->CancelRequest( 632 origin, AwPermissionRequest::ProtectedMediaId); 633 } 634 635 void AwContents::RequestGeolocationPermission( 636 const GURL& origin, 637 const base::Callback<void(bool)>& callback) { 638 JNIEnv* env = AttachCurrentThread(); 639 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 640 if (obj.is_null()) 641 return; 642 643 if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj.obj())) { 644 ShowGeolocationPrompt(origin, callback); 645 return; 646 } 647 permission_request_handler_->SendRequest( 648 scoped_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest( 649 origin, AwPermissionRequest::Geolocation, callback))); 650 } 651 652 void AwContents::CancelGeolocationPermissionRequests(const GURL& origin) { 653 JNIEnv* env = AttachCurrentThread(); 654 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 655 if (obj.is_null()) 656 return; 657 658 if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj.obj())) { 659 HideGeolocationPrompt(origin); 660 return; 661 } 662 permission_request_handler_->CancelRequest( 663 origin, AwPermissionRequest::Geolocation); 664 } 665 666 void AwContents::FindAllAsync(JNIEnv* env, jobject obj, jstring search_string) { 667 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 668 GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string)); 669 } 670 671 void AwContents::FindNext(JNIEnv* env, jobject obj, jboolean forward) { 672 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 673 GetFindHelper()->FindNext(forward); 674 } 675 676 void AwContents::ClearMatches(JNIEnv* env, jobject obj) { 677 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 678 GetFindHelper()->ClearMatches(); 679 } 680 681 void AwContents::ClearCache( 682 JNIEnv* env, 683 jobject obj, 684 jboolean include_disk_files) { 685 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 686 render_view_host_ext_->ClearCache(); 687 688 if (include_disk_files) { 689 RemoveHttpDiskCache(web_contents_->GetBrowserContext(), 690 web_contents_->GetRoutingID()); 691 } 692 } 693 694 FindHelper* AwContents::GetFindHelper() { 695 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 696 if (!find_helper_.get()) { 697 find_helper_.reset(new FindHelper(web_contents_.get())); 698 find_helper_->SetListener(this); 699 } 700 return find_helper_.get(); 701 } 702 703 void AwContents::OnFindResultReceived(int active_ordinal, 704 int match_count, 705 bool finished) { 706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 707 JNIEnv* env = AttachCurrentThread(); 708 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 709 if (obj.is_null()) 710 return; 711 712 Java_AwContents_onFindResultReceived( 713 env, obj.obj(), active_ordinal, match_count, finished); 714 } 715 716 bool AwContents::ShouldDownloadFavicon(const GURL& icon_url) { 717 return g_should_download_favicons; 718 } 719 720 void AwContents::OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap) { 721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 722 JNIEnv* env = AttachCurrentThread(); 723 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 724 if (obj.is_null()) 725 return; 726 727 content::NavigationEntry* entry = 728 web_contents_->GetController().GetActiveEntry(); 729 730 if (entry) { 731 entry->GetFavicon().valid = true; 732 entry->GetFavicon().url = icon_url; 733 entry->GetFavicon().image = gfx::Image::CreateFrom1xBitmap(bitmap); 734 } 735 736 Java_AwContents_onReceivedIcon( 737 env, obj.obj(), gfx::ConvertToJavaBitmap(&bitmap).obj()); 738 } 739 740 void AwContents::OnReceivedTouchIconUrl(const std::string& url, 741 bool precomposed) { 742 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 743 JNIEnv* env = AttachCurrentThread(); 744 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 745 if (obj.is_null()) 746 return; 747 748 Java_AwContents_onReceivedTouchIconUrl( 749 env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed); 750 } 751 752 bool AwContents::RequestDrawGL(jobject canvas, bool wait_for_completion) { 753 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 754 DCHECK(!canvas || !wait_for_completion); 755 JNIEnv* env = AttachCurrentThread(); 756 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 757 if (obj.is_null()) 758 return false; 759 return Java_AwContents_requestDrawGL( 760 env, obj.obj(), canvas, wait_for_completion); 761 } 762 763 void AwContents::PostInvalidate() { 764 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 765 JNIEnv* env = AttachCurrentThread(); 766 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 767 if (!obj.is_null()) 768 Java_AwContents_postInvalidateOnAnimation(env, obj.obj()); 769 } 770 771 void AwContents::UpdateParentDrawConstraints() { 772 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 773 browser_view_renderer_.UpdateParentDrawConstraints(); 774 } 775 776 void AwContents::OnNewPicture() { 777 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 778 JNIEnv* env = AttachCurrentThread(); 779 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 780 if (!obj.is_null()) { 781 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback( 782 "onNewPicture"); 783 Java_AwContents_onNewPicture(env, obj.obj()); 784 } 785 } 786 787 base::android::ScopedJavaLocalRef<jbyteArray> 788 AwContents::GetCertificate(JNIEnv* env, 789 jobject obj) { 790 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 791 content::NavigationEntry* entry = 792 web_contents_->GetController().GetActiveEntry(); 793 if (!entry) 794 return ScopedJavaLocalRef<jbyteArray>(); 795 // Get the certificate 796 int cert_id = entry->GetSSL().cert_id; 797 scoped_refptr<net::X509Certificate> cert; 798 bool ok = content::CertStore::GetInstance()->RetrieveCert(cert_id, &cert); 799 if (!ok) 800 return ScopedJavaLocalRef<jbyteArray>(); 801 802 // Convert the certificate and return it 803 std::string der_string; 804 net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_string); 805 return base::android::ToJavaByteArray(env, 806 reinterpret_cast<const uint8*>(der_string.data()), der_string.length()); 807 } 808 809 void AwContents::RequestNewHitTestDataAt(JNIEnv* env, jobject obj, 810 jint x, jint y) { 811 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 812 render_view_host_ext_->RequestNewHitTestDataAt(x, y); 813 } 814 815 void AwContents::UpdateLastHitTestData(JNIEnv* env, jobject obj) { 816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 817 if (!render_view_host_ext_->HasNewHitTestData()) return; 818 819 const AwHitTestData& data = render_view_host_ext_->GetLastHitTestData(); 820 render_view_host_ext_->MarkHitTestDataRead(); 821 822 // Make sure to null the Java object if data is empty/invalid. 823 ScopedJavaLocalRef<jstring> extra_data_for_type; 824 if (data.extra_data_for_type.length()) 825 extra_data_for_type = ConvertUTF8ToJavaString( 826 env, data.extra_data_for_type); 827 828 ScopedJavaLocalRef<jstring> href; 829 if (data.href.length()) 830 href = ConvertUTF16ToJavaString(env, data.href); 831 832 ScopedJavaLocalRef<jstring> anchor_text; 833 if (data.anchor_text.length()) 834 anchor_text = ConvertUTF16ToJavaString(env, data.anchor_text); 835 836 ScopedJavaLocalRef<jstring> img_src; 837 if (data.img_src.is_valid()) 838 img_src = ConvertUTF8ToJavaString(env, data.img_src.spec()); 839 840 Java_AwContents_updateHitTestData(env, 841 obj, 842 data.type, 843 extra_data_for_type.obj(), 844 href.obj(), 845 anchor_text.obj(), 846 img_src.obj()); 847 } 848 849 void AwContents::OnSizeChanged(JNIEnv* env, jobject obj, 850 int w, int h, int ow, int oh) { 851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 852 browser_view_renderer_.OnSizeChanged(w, h); 853 } 854 855 void AwContents::SetViewVisibility(JNIEnv* env, jobject obj, bool visible) { 856 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 857 browser_view_renderer_.SetViewVisibility(visible); 858 } 859 860 void AwContents::SetWindowVisibility(JNIEnv* env, jobject obj, bool visible) { 861 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 862 browser_view_renderer_.SetWindowVisibility(visible); 863 } 864 865 void AwContents::SetIsPaused(JNIEnv* env, jobject obj, bool paused) { 866 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 867 browser_view_renderer_.SetIsPaused(paused); 868 ContentViewCore* cvc = 869 ContentViewCore::FromWebContents(web_contents_.get()); 870 if (cvc) { 871 cvc->PauseOrResumeGeolocation(paused); 872 cvc->PauseOrResumeVideoCaptureStream(paused); 873 if (paused) { 874 cvc->PauseVideo(); 875 } 876 } 877 } 878 879 void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) { 880 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 881 browser_view_renderer_.OnAttachedToWindow(w, h); 882 } 883 884 void AwContents::InitializeHardwareDrawIfNeeded() { 885 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); 886 887 base::AutoLock lock(render_thread_lock_); 888 if (renderer_manager_key_ == manager->NullKey()) { 889 renderer_manager_key_ = manager->PushBack(&shared_renderer_state_); 890 DeferredGpuCommandService::SetInstance(); 891 } 892 } 893 894 void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) { 895 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 896 ReleaseHardwareDrawIfNeeded(); 897 browser_view_renderer_.OnDetachedFromWindow(); 898 } 899 900 void AwContents::ReleaseHardwareDrawIfNeeded() { 901 InsideHardwareReleaseReset inside_reset(&shared_renderer_state_); 902 903 JNIEnv* env = AttachCurrentThread(); 904 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 905 if (!obj.is_null()) 906 Java_AwContents_invalidateOnFunctorDestroy(env, obj.obj()); 907 908 bool hardware_initialized = browser_view_renderer_.hardware_enabled(); 909 if (hardware_initialized) { 910 bool draw_functor_succeeded = RequestDrawGL(NULL, true); 911 if (!draw_functor_succeeded) { 912 LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?"; 913 // Calling release on wrong thread intentionally. 914 AwDrawGLInfo info; 915 info.mode = AwDrawGLInfo::kModeProcess; 916 DrawGL(&info); 917 } 918 browser_view_renderer_.ReleaseHardware(); 919 } 920 DCHECK(!hardware_renderer_); 921 922 GLViewRendererManager* manager = GLViewRendererManager::GetInstance(); 923 924 { 925 base::AutoLock lock(render_thread_lock_); 926 if (renderer_manager_key_ != manager->NullKey()) { 927 manager->Remove(renderer_manager_key_); 928 renderer_manager_key_ = manager->NullKey(); 929 } 930 } 931 932 if (hardware_initialized) { 933 // Flush any invoke functors that's caused by OnDetachedFromWindow. 934 RequestDrawGL(NULL, true); 935 } 936 } 937 938 base::android::ScopedJavaLocalRef<jbyteArray> 939 AwContents::GetOpaqueState(JNIEnv* env, jobject obj) { 940 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 941 // Required optimization in WebViewClassic to not save any state if 942 // there has been no navigations. 943 if (!web_contents_->GetController().GetEntryCount()) 944 return ScopedJavaLocalRef<jbyteArray>(); 945 946 Pickle pickle; 947 if (!WriteToPickle(*web_contents_, &pickle)) { 948 return ScopedJavaLocalRef<jbyteArray>(); 949 } else { 950 return base::android::ToJavaByteArray(env, 951 reinterpret_cast<const uint8*>(pickle.data()), pickle.size()); 952 } 953 } 954 955 jboolean AwContents::RestoreFromOpaqueState( 956 JNIEnv* env, jobject obj, jbyteArray state) { 957 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 958 // TODO(boliu): This copy can be optimized out if this is a performance 959 // problem. 960 std::vector<uint8> state_vector; 961 base::android::JavaByteArrayToByteVector(env, state, &state_vector); 962 963 Pickle pickle(reinterpret_cast<const char*>(state_vector.begin()), 964 state_vector.size()); 965 PickleIterator iterator(pickle); 966 967 return RestoreFromPickle(&iterator, web_contents_.get()); 968 } 969 970 bool AwContents::OnDraw(JNIEnv* env, 971 jobject obj, 972 jobject canvas, 973 jboolean is_hardware_accelerated, 974 jint scroll_x, 975 jint scroll_y, 976 jint visible_left, 977 jint visible_top, 978 jint visible_right, 979 jint visible_bottom) { 980 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 981 if (is_hardware_accelerated) 982 InitializeHardwareDrawIfNeeded(); 983 return browser_view_renderer_.OnDraw( 984 canvas, 985 is_hardware_accelerated, 986 gfx::Vector2d(scroll_x, scroll_y), 987 gfx::Rect(visible_left, 988 visible_top, 989 visible_right - visible_left, 990 visible_bottom - visible_top)); 991 } 992 993 void AwContents::SetPendingWebContentsForPopup( 994 scoped_ptr<content::WebContents> pending) { 995 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 996 if (pending_contents_.get()) { 997 // TODO(benm): Support holding multiple pop up window requests. 998 LOG(WARNING) << "Blocking popup window creation as an outstanding " 999 << "popup window is still pending."; 1000 base::MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release()); 1001 return; 1002 } 1003 pending_contents_.reset(new AwContents(pending.Pass())); 1004 } 1005 1006 void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) { 1007 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1008 web_contents_->FocusThroughTabTraversal(false); 1009 } 1010 1011 void AwContents::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) { 1012 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1013 render_view_host_ext_->SetBackgroundColor(color); 1014 } 1015 1016 jlong AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) { 1017 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1018 return reinterpret_cast<intptr_t>(pending_contents_.release()); 1019 } 1020 1021 gfx::Point AwContents::GetLocationOnScreen() { 1022 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1023 JNIEnv* env = AttachCurrentThread(); 1024 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1025 if (obj.is_null()) 1026 return gfx::Point(); 1027 std::vector<int> location; 1028 base::android::JavaIntArrayToIntVector( 1029 env, 1030 Java_AwContents_getLocationOnScreen(env, obj.obj()).obj(), 1031 &location); 1032 return gfx::Point(location[0], location[1]); 1033 } 1034 1035 void AwContents::ScrollContainerViewTo(gfx::Vector2d new_value) { 1036 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1037 JNIEnv* env = AttachCurrentThread(); 1038 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1039 if (obj.is_null()) 1040 return; 1041 Java_AwContents_scrollContainerViewTo( 1042 env, obj.obj(), new_value.x(), new_value.y()); 1043 } 1044 1045 bool AwContents::IsFlingActive() const { 1046 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1047 JNIEnv* env = AttachCurrentThread(); 1048 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1049 if (obj.is_null()) 1050 return false; 1051 return Java_AwContents_isFlingActive(env, obj.obj()); 1052 } 1053 1054 void AwContents::UpdateScrollState(gfx::Vector2d max_scroll_offset, 1055 gfx::SizeF contents_size_dip, 1056 float page_scale_factor, 1057 float min_page_scale_factor, 1058 float max_page_scale_factor) { 1059 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1060 JNIEnv* env = AttachCurrentThread(); 1061 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1062 if (obj.is_null()) 1063 return; 1064 Java_AwContents_updateScrollState(env, 1065 obj.obj(), 1066 max_scroll_offset.x(), 1067 max_scroll_offset.y(), 1068 contents_size_dip.width(), 1069 contents_size_dip.height(), 1070 page_scale_factor, 1071 min_page_scale_factor, 1072 max_page_scale_factor); 1073 } 1074 1075 void AwContents::DidOverscroll(gfx::Vector2d overscroll_delta) { 1076 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1077 JNIEnv* env = AttachCurrentThread(); 1078 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1079 if (obj.is_null()) 1080 return; 1081 Java_AwContents_didOverscroll( 1082 env, obj.obj(), overscroll_delta.x(), overscroll_delta.y()); 1083 } 1084 1085 const BrowserViewRenderer* AwContents::GetBrowserViewRenderer() const { 1086 return &browser_view_renderer_; 1087 } 1088 1089 void AwContents::SetDipScale(JNIEnv* env, jobject obj, jfloat dip_scale) { 1090 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1091 browser_view_renderer_.SetDipScale(dip_scale); 1092 } 1093 1094 void AwContents::ScrollTo(JNIEnv* env, jobject obj, jint x, jint y) { 1095 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1096 browser_view_renderer_.ScrollTo(gfx::Vector2d(x, y)); 1097 } 1098 1099 void AwContents::OnWebLayoutPageScaleFactorChanged(float page_scale_factor) { 1100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1101 JNIEnv* env = AttachCurrentThread(); 1102 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1103 if (obj.is_null()) 1104 return; 1105 Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj.obj(), 1106 page_scale_factor); 1107 } 1108 1109 void AwContents::OnWebLayoutContentsSizeChanged( 1110 const gfx::Size& contents_size) { 1111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1112 JNIEnv* env = AttachCurrentThread(); 1113 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1114 if (obj.is_null()) 1115 return; 1116 Java_AwContents_onWebLayoutContentsSizeChanged( 1117 env, obj.obj(), contents_size.width(), contents_size.height()); 1118 } 1119 1120 jlong AwContents::CapturePicture(JNIEnv* env, 1121 jobject obj, 1122 int width, 1123 int height) { 1124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1125 return reinterpret_cast<intptr_t>( 1126 new AwPicture(browser_view_renderer_.CapturePicture(width, height))); 1127 } 1128 1129 void AwContents::EnableOnNewPicture(JNIEnv* env, 1130 jobject obj, 1131 jboolean enabled) { 1132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1133 browser_view_renderer_.EnableOnNewPicture(enabled); 1134 } 1135 1136 void AwContents::ClearView(JNIEnv* env, jobject obj) { 1137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1138 browser_view_renderer_.ClearView(); 1139 } 1140 1141 void AwContents::SetExtraHeadersForUrl(JNIEnv* env, jobject obj, 1142 jstring url, jstring jextra_headers) { 1143 std::string extra_headers; 1144 if (jextra_headers) 1145 extra_headers = ConvertJavaStringToUTF8(env, jextra_headers); 1146 AwResourceContext* resource_context = static_cast<AwResourceContext*>( 1147 AwBrowserContext::FromWebContents(web_contents_.get())-> 1148 GetResourceContext()); 1149 resource_context->SetExtraHeaders(GURL(ConvertJavaStringToUTF8(env, url)), 1150 extra_headers); 1151 } 1152 1153 void AwContents::SetJsOnlineProperty(JNIEnv* env, 1154 jobject obj, 1155 jboolean network_up) { 1156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1157 render_view_host_ext_->SetJsOnlineProperty(network_up); 1158 } 1159 1160 void AwContents::TrimMemory(JNIEnv* env, 1161 jobject obj, 1162 jint level, 1163 jboolean visible) { 1164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1165 enum { 1166 TRIM_MEMORY_MODERATE = 60, 1167 }; 1168 if (level >= TRIM_MEMORY_MODERATE) { 1169 ReleaseHardwareDrawIfNeeded(); 1170 return; 1171 } 1172 1173 browser_view_renderer_.TrimMemory(level, visible); 1174 } 1175 1176 void SetShouldDownloadFavicons(JNIEnv* env, jclass jclazz) { 1177 g_should_download_favicons = true; 1178 } 1179 1180 } // namespace android_webview 1181