aw_contents.cc revision bb535fb2ef23e55737a27cd974d4304a1e2e1f7a
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/gpu_memory_buffer_factory_impl.h" 12#include "android_webview/browser/in_process_view_renderer.h" 13#include "android_webview/browser/net_disk_cache_remover.h" 14#include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h" 15#include "android_webview/common/aw_hit_test_data.h" 16#include "android_webview/native/aw_autofill_manager_delegate.h" 17#include "android_webview/native/aw_browser_dependency_factory.h" 18#include "android_webview/native/aw_contents_client_bridge.h" 19#include "android_webview/native/aw_contents_io_thread_client_impl.h" 20// START: Printing fork b/10190508 21#include "android_webview/native/aw_pdf_exporter.h" 22// END: Printing fork b/10190508 23#include "android_webview/native/aw_picture.h" 24#include "android_webview/native/aw_web_contents_delegate.h" 25#include "android_webview/native/java_browser_view_renderer_helper.h" 26#include "android_webview/native/state_serializer.h" 27#include "android_webview/public/browser/draw_gl.h" 28#include "base/android/jni_android.h" 29#include "base/android/jni_array.h" 30#include "base/android/jni_string.h" 31#include "base/android/scoped_java_ref.h" 32#include "base/atomicops.h" 33#include "base/bind.h" 34#include "base/callback.h" 35#include "base/memory/memory_pressure_listener.h" 36#include "base/message_loop/message_loop.h" 37#include "base/pickle.h" 38#include "base/strings/string16.h" 39#include "base/supports_user_data.h" 40#include "components/autofill/content/browser/autofill_driver_impl.h" 41#include "components/autofill/core/browser/autofill_manager.h" 42#include "components/autofill/core/browser/webdata/autofill_webdata_service.h" 43#include "components/navigation_interception/intercept_navigation_delegate.h" 44#include "content/public/browser/android/content_view_core.h" 45#include "content/public/browser/browser_thread.h" 46#include "content/public/browser/cert_store.h" 47#include "content/public/browser/favicon_status.h" 48#include "content/public/browser/navigation_entry.h" 49#include "content/public/browser/render_process_host.h" 50#include "content/public/browser/render_view_host.h" 51#include "content/public/browser/web_contents.h" 52#include "content/public/common/renderer_preferences.h" 53#include "content/public/common/ssl_status.h" 54#include "jni/AwContents_jni.h" 55#include "net/cert/x509_certificate.h" 56#include "third_party/skia/include/core/SkPicture.h" 57#include "ui/base/l10n/l10n_util_android.h" 58#include "ui/gfx/android/java_bitmap.h" 59#include "ui/gfx/font_render_params_linux.h" 60#include "ui/gfx/image/image.h" 61#include "ui/gfx/size.h" 62 63struct AwDrawSWFunctionTable; 64struct AwDrawGLFunctionTable; 65 66using autofill::AutofillDriverImpl; 67using autofill::AutofillManager; 68using base::android::AttachCurrentThread; 69using base::android::ConvertJavaStringToUTF16; 70using base::android::ConvertJavaStringToUTF8; 71using base::android::ConvertUTF16ToJavaString; 72using base::android::ConvertUTF8ToJavaString; 73using base::android::JavaRef; 74using base::android::ScopedJavaGlobalRef; 75using base::android::ScopedJavaLocalRef; 76using navigation_interception::InterceptNavigationDelegate; 77using content::BrowserThread; 78using content::ContentViewCore; 79using content::WebContents; 80 81extern "C" { 82static AwDrawGLFunction DrawGLFunction; 83static void DrawGLFunction(int view_context, 84 AwDrawGLInfo* draw_info, 85 void* spare) { 86 // |view_context| is the value that was returned from the java 87 // AwContents.onPrepareDrawGL; this cast must match the code there. 88 reinterpret_cast<android_webview::BrowserViewRenderer*>(view_context)->DrawGL( 89 draw_info); 90} 91} 92 93namespace android_webview { 94 95namespace { 96 97bool g_should_download_favicons = false; 98 99JavaBrowserViewRendererHelper* java_renderer_helper() { 100 return JavaBrowserViewRendererHelper::GetInstance(); 101} 102 103const void* kAwContentsUserDataKey = &kAwContentsUserDataKey; 104 105class AwContentsUserData : public base::SupportsUserData::Data { 106 public: 107 AwContentsUserData(AwContents* ptr) : contents_(ptr) {} 108 109 static AwContents* GetContents(WebContents* web_contents) { 110 if (!web_contents) 111 return NULL; 112 AwContentsUserData* data = reinterpret_cast<AwContentsUserData*>( 113 web_contents->GetUserData(kAwContentsUserDataKey)); 114 return data ? data->contents_ : NULL; 115 } 116 117 private: 118 AwContents* contents_; 119}; 120 121base::subtle::Atomic32 g_instance_count = 0; 122 123// TODO(boliu): Deduplicate with chrome/ code. 124content::RendererPreferencesHintingEnum GetRendererPreferencesHintingEnum( 125 gfx::FontRenderParams::Hinting hinting) { 126 switch (hinting) { 127 case gfx::FontRenderParams::HINTING_NONE: 128 return content::RENDERER_PREFERENCES_HINTING_NONE; 129 case gfx::FontRenderParams::HINTING_SLIGHT: 130 return content::RENDERER_PREFERENCES_HINTING_SLIGHT; 131 case gfx::FontRenderParams::HINTING_MEDIUM: 132 return content::RENDERER_PREFERENCES_HINTING_MEDIUM; 133 case gfx::FontRenderParams::HINTING_FULL: 134 return content::RENDERER_PREFERENCES_HINTING_FULL; 135 default: 136 NOTREACHED() << "Unhandled hinting style " << hinting; 137 return content::RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT; 138 } 139} 140 141// TODO(boliu): Deduplicate with chrome/ code. 142content::RendererPreferencesSubpixelRenderingEnum 143GetRendererPreferencesSubpixelRenderingEnum( 144 gfx::FontRenderParams::SubpixelRendering subpixel_rendering) { 145 switch (subpixel_rendering) { 146 case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE: 147 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE; 148 case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB: 149 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB; 150 case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR: 151 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR; 152 case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB: 153 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB; 154 case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR: 155 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR; 156 default: 157 NOTREACHED() << "Unhandled subpixel rendering style " 158 << subpixel_rendering; 159 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT; 160 } 161} 162 163} // namespace 164 165// static 166AwContents* AwContents::FromWebContents(WebContents* web_contents) { 167 return AwContentsUserData::GetContents(web_contents); 168} 169 170// static 171AwContents* AwContents::FromID(int render_process_id, int render_view_id) { 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 173 const content::RenderViewHost* rvh = 174 content::RenderViewHost::FromID(render_process_id, render_view_id); 175 if (!rvh) return NULL; 176 content::WebContents* web_contents = 177 content::WebContents::FromRenderViewHost(rvh); 178 if (!web_contents) return NULL; 179 return FromWebContents(web_contents); 180} 181 182AwContents::AwContents(scoped_ptr<WebContents> web_contents) 183 : web_contents_(web_contents.Pass()), 184 browser_view_renderer_( 185 new InProcessViewRenderer(this, java_renderer_helper(), 186 web_contents_.get())) { 187 base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1); 188 icon_helper_.reset(new IconHelper(web_contents_.get())); 189 icon_helper_->SetListener(this); 190 web_contents_->SetUserData(kAwContentsUserDataKey, 191 new AwContentsUserData(this)); 192 render_view_host_ext_.reset( 193 new AwRenderViewHostExt(this, web_contents_.get())); 194 AwContentsIoThreadClientImpl::RegisterPendingContents(web_contents_.get()); 195 196 AwAutofillManagerDelegate* autofill_manager_delegate = 197 AwAutofillManagerDelegate::FromWebContents(web_contents_.get()); 198 if (autofill_manager_delegate) 199 InitAutofillIfNecessary(autofill_manager_delegate->GetSaveFormData()); 200 201 SetAndroidWebViewRendererPrefs(); 202} 203 204void AwContents::SetJavaPeers(JNIEnv* env, 205 jobject obj, 206 jobject aw_contents, 207 jobject web_contents_delegate, 208 jobject contents_client_bridge, 209 jobject io_thread_client, 210 jobject intercept_navigation_delegate) { 211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 212 // The |aw_content| param is technically spurious as it duplicates |obj| but 213 // is passed over anyway to make the binding more explicit. 214 java_ref_ = JavaObjectWeakGlobalRef(env, aw_contents); 215 216 web_contents_delegate_.reset( 217 new AwWebContentsDelegate(env, web_contents_delegate)); 218 web_contents_->SetDelegate(web_contents_delegate_.get()); 219 220 contents_client_bridge_.reset( 221 new AwContentsClientBridge(env, contents_client_bridge)); 222 AwContentsClientBridgeBase::Associate(web_contents_.get(), 223 contents_client_bridge_.get()); 224 225 AwContentsIoThreadClientImpl::Associate( 226 web_contents_.get(), ScopedJavaLocalRef<jobject>(env, io_thread_client)); 227 int child_id = web_contents_->GetRenderProcessHost()->GetID(); 228 int route_id = web_contents_->GetRoutingID(); 229 AwResourceDispatcherHostDelegate::OnIoThreadClientReady(child_id, route_id); 230 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 232 InterceptNavigationDelegate::Associate( 233 web_contents_.get(), 234 make_scoped_ptr(new InterceptNavigationDelegate( 235 env, intercept_navigation_delegate))); 236} 237 238void AwContents::SetSaveFormData(bool enabled) { 239 InitAutofillIfNecessary(enabled); 240 // We need to check for the existence, since autofill_manager_delegate 241 // may not be created when the setting is false. 242 if (AutofillDriverImpl::FromWebContents(web_contents_.get())) { 243 AwAutofillManagerDelegate::FromWebContents(web_contents_.get())-> 244 SetSaveFormData(enabled); 245 } 246} 247 248void AwContents::InitAutofillIfNecessary(bool enabled) { 249 // Do not initialize if the feature is not enabled. 250 if (!enabled) 251 return; 252 // Check if the autofill driver already exists. 253 content::WebContents* web_contents = web_contents_.get(); 254 if (AutofillDriverImpl::FromWebContents(web_contents)) 255 return; 256 257 AwBrowserContext::FromWebContents(web_contents)-> 258 CreateUserPrefServiceIfNecessary(); 259 AwAutofillManagerDelegate::CreateForWebContents(web_contents); 260 AutofillDriverImpl::CreateForWebContentsAndDelegate( 261 web_contents, 262 AwAutofillManagerDelegate::FromWebContents(web_contents), 263 l10n_util::GetDefaultLocale(), 264 AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER); 265} 266 267void AwContents::SetAndroidWebViewRendererPrefs() { 268 content::RendererPreferences* prefs = 269 web_contents_->GetMutableRendererPrefs(); 270 prefs->tap_multiple_targets_strategy = 271 content::TAP_MULTIPLE_TARGETS_STRATEGY_NONE; 272 273 // TODO(boliu): Deduplicate with chrome/ code. 274 const gfx::FontRenderParams& params = gfx::GetDefaultWebKitFontRenderParams(); 275 prefs->should_antialias_text = params.antialiasing; 276 prefs->use_subpixel_positioning = params.subpixel_positioning; 277 prefs->hinting = GetRendererPreferencesHintingEnum(params.hinting); 278 prefs->use_autohinter = params.autohinter; 279 prefs->use_bitmaps = params.use_bitmaps; 280 prefs->subpixel_rendering = 281 GetRendererPreferencesSubpixelRenderingEnum(params.subpixel_rendering); 282 283 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); 284 if (host) 285 host->SyncRendererPrefs(); 286} 287 288void AwContents::SetAwAutofillManagerDelegate(jobject delegate) { 289 JNIEnv* env = AttachCurrentThread(); 290 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 291 if (obj.is_null()) 292 return; 293 Java_AwContents_setAwAutofillManagerDelegate(env, obj.obj(), delegate); 294} 295 296AwContents::~AwContents() { 297 DCHECK(AwContents::FromWebContents(web_contents_.get()) == this); 298 web_contents_->RemoveUserData(kAwContentsUserDataKey); 299 if (find_helper_.get()) 300 find_helper_->SetListener(NULL); 301 if (icon_helper_.get()) 302 icon_helper_->SetListener(NULL); 303 base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, -1); 304} 305 306jint AwContents::GetWebContents(JNIEnv* env, jobject obj) { 307 DCHECK(web_contents_); 308 return reinterpret_cast<jint>(web_contents_.get()); 309} 310 311void AwContents::Destroy(JNIEnv* env, jobject obj) { 312 java_ref_.reset(); 313 // We do not delete AwContents immediately. Some applications try to delete 314 // Webview in ShouldOverrideUrlLoading callback, which is a sync IPC from 315 // Webkit. 316 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); 317 // When the last WebView is destroyed free all discardable memory allocated by 318 // Chromium, because the app process may continue to run for a long time 319 // without ever using another WebView. 320 if (base::subtle::NoBarrier_Load(&g_instance_count) == 0) { 321 base::MemoryPressureListener::NotifyMemoryPressure( 322 base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); 323 } 324} 325 326static jint Init(JNIEnv* env, jclass, jobject browser_context) { 327 // TODO(joth): Use |browser_context| to get the native BrowserContext, rather 328 // than hard-code the default instance lookup here. 329 scoped_ptr<WebContents> web_contents(content::WebContents::Create( 330 content::WebContents::CreateParams(AwBrowserContext::GetDefault()))); 331 // Return an 'uninitialized' instance; most work is deferred until the 332 // subsequent SetJavaPeers() call. 333 return reinterpret_cast<jint>(new AwContents(web_contents.Pass())); 334} 335 336static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) { 337 BrowserViewRenderer::SetAwDrawSWFunctionTable( 338 reinterpret_cast<AwDrawSWFunctionTable*>(function_table)); 339} 340 341static void SetAwDrawGLFunctionTable(JNIEnv* env, jclass, jint function_table) { 342 GpuMemoryBufferFactoryImpl::SetAwDrawGLFunctionTable( 343 reinterpret_cast<AwDrawGLFunctionTable*>(function_table)); 344} 345 346static jint GetAwDrawGLFunction(JNIEnv* env, jclass) { 347 return reinterpret_cast<jint>(&DrawGLFunction); 348} 349 350// static 351jint GetNativeInstanceCount(JNIEnv* env, jclass) { 352 return base::subtle::NoBarrier_Load(&g_instance_count); 353} 354 355jint AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) { 356 return reinterpret_cast<jint>(browser_view_renderer_.get()); 357} 358 359namespace { 360void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message, 361 bool has_images) { 362 Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(), 363 has_images, 364 message.obj()); 365} 366} // namespace 367 368void AwContents::DocumentHasImages(JNIEnv* env, jobject obj, jobject message) { 369 ScopedJavaGlobalRef<jobject> j_message; 370 j_message.Reset(env, message); 371 render_view_host_ext_->DocumentHasImages( 372 base::Bind(&DocumentHasImagesCallback, j_message)); 373} 374 375namespace { 376void GenerateMHTMLCallback(ScopedJavaGlobalRef<jobject>* callback, 377 const base::FilePath& path, int64 size) { 378 JNIEnv* env = AttachCurrentThread(); 379 // Android files are UTF8, so the path conversion below is safe. 380 Java_AwContents_generateMHTMLCallback( 381 env, 382 ConvertUTF8ToJavaString(env, path.AsUTF8Unsafe()).obj(), 383 size, callback->obj()); 384} 385} // namespace 386 387void AwContents::GenerateMHTML(JNIEnv* env, jobject obj, 388 jstring jpath, jobject callback) { 389 ScopedJavaGlobalRef<jobject>* j_callback = new ScopedJavaGlobalRef<jobject>(); 390 j_callback->Reset(env, callback); 391 web_contents_->GenerateMHTML( 392 base::FilePath(ConvertJavaStringToUTF8(env, jpath)), 393 base::Bind(&GenerateMHTMLCallback, base::Owned(j_callback))); 394} 395 396// START: Printing fork b/10190508 397void AwContents::CreatePdfExporter(JNIEnv* env, 398 jobject obj, 399 jobject pdfExporter) { 400 401 pdf_exporter_.reset( 402 new AwPdfExporter(env, 403 pdfExporter, 404 browser_view_renderer_.get(), 405 web_contents_.get())); 406} 407// END: Printing fork b/10190508 408 409bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler, 410 const std::string& host, 411 const std::string& realm) { 412 JNIEnv* env = AttachCurrentThread(); 413 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 414 if (obj.is_null()) 415 return false; 416 417 ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host); 418 ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm); 419 Java_AwContents_onReceivedHttpAuthRequest(env, obj.obj(), handler.obj(), 420 jhost.obj(), jrealm.obj()); 421 return true; 422} 423 424void AwContents::AddVisitedLinks(JNIEnv* env, 425 jobject obj, 426 jobjectArray jvisited_links) { 427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 428 std::vector<string16> visited_link_strings; 429 base::android::AppendJavaStringArrayToStringVector( 430 env, jvisited_links, &visited_link_strings); 431 432 std::vector<GURL> visited_link_gurls; 433 for (std::vector<string16>::const_iterator itr = visited_link_strings.begin(); 434 itr != visited_link_strings.end(); 435 ++itr) { 436 visited_link_gurls.push_back(GURL(*itr)); 437 } 438 439 AwBrowserContext::FromWebContents(web_contents_.get()) 440 ->AddVisitedURLs(visited_link_gurls); 441} 442 443bool RegisterAwContents(JNIEnv* env) { 444 return RegisterNativesImpl(env) >= 0; 445} 446 447namespace { 448 449void ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef& java_ref, 450 const GURL& origin) { 451 JNIEnv* env = AttachCurrentThread(); 452 ScopedJavaLocalRef<jobject> j_ref = java_ref.get(env); 453 if (j_ref.obj()) { 454 ScopedJavaLocalRef<jstring> j_origin( 455 ConvertUTF8ToJavaString(env, origin.spec())); 456 Java_AwContents_onGeolocationPermissionsShowPrompt(env, 457 j_ref.obj(), 458 j_origin.obj()); 459 } 460} 461 462void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref, 463 const GURL& origin) { 464 JNIEnv* env = AttachCurrentThread(); 465 if (java_ref.get(env).obj()) { 466 content::BrowserThread::PostTask( 467 content::BrowserThread::UI, 468 FROM_HERE, 469 base::Bind(&ShowGeolocationPromptHelperTask, 470 java_ref, 471 origin)); 472 } 473} 474 475} // anonymous namespace 476 477void AwContents::ShowGeolocationPrompt(const GURL& requesting_frame, 478 base::Callback<void(bool)> callback) { 479 GURL origin = requesting_frame.GetOrigin(); 480 bool show_prompt = pending_geolocation_prompts_.empty(); 481 pending_geolocation_prompts_.push_back(OriginCallback(origin, callback)); 482 if (show_prompt) { 483 ShowGeolocationPromptHelper(java_ref_, origin); 484 } 485} 486 487// Invoked from Java 488void AwContents::InvokeGeolocationCallback(JNIEnv* env, 489 jobject obj, 490 jboolean value, 491 jstring origin) { 492 GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin)); 493 if (callback_origin.GetOrigin() == 494 pending_geolocation_prompts_.front().first) { 495 pending_geolocation_prompts_.front().second.Run(value); 496 pending_geolocation_prompts_.pop_front(); 497 if (!pending_geolocation_prompts_.empty()) { 498 ShowGeolocationPromptHelper(java_ref_, 499 pending_geolocation_prompts_.front().first); 500 } 501 } 502} 503 504void AwContents::HideGeolocationPrompt(const GURL& origin) { 505 bool removed_current_outstanding_callback = false; 506 std::list<OriginCallback>::iterator it = pending_geolocation_prompts_.begin(); 507 while (it != pending_geolocation_prompts_.end()) { 508 if ((*it).first == origin.GetOrigin()) { 509 if (it == pending_geolocation_prompts_.begin()) { 510 removed_current_outstanding_callback = true; 511 } 512 it = pending_geolocation_prompts_.erase(it); 513 } else { 514 ++it; 515 } 516 } 517 518 if (removed_current_outstanding_callback) { 519 JNIEnv* env = AttachCurrentThread(); 520 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); 521 if (j_ref.obj()) { 522 Java_AwContents_onGeolocationPermissionsHidePrompt(env, j_ref.obj()); 523 } 524 if (!pending_geolocation_prompts_.empty()) { 525 ShowGeolocationPromptHelper(java_ref_, 526 pending_geolocation_prompts_.front().first); 527 } 528 } 529} 530 531void AwContents::FindAllAsync(JNIEnv* env, jobject obj, jstring search_string) { 532 GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string)); 533} 534 535void AwContents::FindNext(JNIEnv* env, jobject obj, jboolean forward) { 536 GetFindHelper()->FindNext(forward); 537} 538 539void AwContents::ClearMatches(JNIEnv* env, jobject obj) { 540 GetFindHelper()->ClearMatches(); 541} 542 543void AwContents::ClearCache( 544 JNIEnv* env, 545 jobject obj, 546 jboolean include_disk_files) { 547 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 548 render_view_host_ext_->ClearCache(); 549 550 if (include_disk_files) { 551 RemoveHttpDiskCache(web_contents_->GetBrowserContext(), 552 web_contents_->GetRoutingID()); 553 } 554} 555 556FindHelper* AwContents::GetFindHelper() { 557 if (!find_helper_.get()) { 558 find_helper_.reset(new FindHelper(web_contents_.get())); 559 find_helper_->SetListener(this); 560 } 561 return find_helper_.get(); 562} 563 564void AwContents::OnFindResultReceived(int active_ordinal, 565 int match_count, 566 bool finished) { 567 JNIEnv* env = AttachCurrentThread(); 568 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 569 if (obj.is_null()) 570 return; 571 572 Java_AwContents_onFindResultReceived( 573 env, obj.obj(), active_ordinal, match_count, finished); 574} 575 576bool AwContents::ShouldDownloadFavicon(const GURL& icon_url) { 577 return g_should_download_favicons; 578} 579 580void AwContents::OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap) { 581 JNIEnv* env = AttachCurrentThread(); 582 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 583 if (obj.is_null()) 584 return; 585 586 content::NavigationEntry* entry = 587 web_contents_->GetController().GetActiveEntry(); 588 589 if (entry) { 590 entry->GetFavicon().valid = true; 591 entry->GetFavicon().url = icon_url; 592 entry->GetFavicon().image = gfx::Image::CreateFrom1xBitmap(bitmap); 593 } 594 595 Java_AwContents_onReceivedIcon( 596 env, obj.obj(), gfx::ConvertToJavaBitmap(&bitmap).obj()); 597} 598 599void AwContents::OnReceivedTouchIconUrl(const std::string& url, 600 bool precomposed) { 601 JNIEnv* env = AttachCurrentThread(); 602 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 603 if (obj.is_null()) 604 return; 605 606 Java_AwContents_onReceivedTouchIconUrl( 607 env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed); 608} 609 610bool AwContents::RequestDrawGL(jobject canvas) { 611 JNIEnv* env = AttachCurrentThread(); 612 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 613 if (obj.is_null()) 614 return false; 615 return Java_AwContents_requestDrawGL(env, obj.obj(), canvas); 616} 617 618void AwContents::PostInvalidate() { 619 JNIEnv* env = AttachCurrentThread(); 620 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 621 if (!obj.is_null()) 622 Java_AwContents_postInvalidateOnAnimation(env, obj.obj()); 623} 624 625void AwContents::UpdateGlobalVisibleRect() { 626 JNIEnv* env = AttachCurrentThread(); 627 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 628 if (!obj.is_null()) 629 Java_AwContents_updateGlobalVisibleRect(env, obj.obj()); 630} 631 632void AwContents::OnNewPicture() { 633 JNIEnv* env = AttachCurrentThread(); 634 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 635 if (!obj.is_null()) 636 Java_AwContents_onNewPicture(env, obj.obj()); 637} 638 639base::android::ScopedJavaLocalRef<jbyteArray> 640 AwContents::GetCertificate(JNIEnv* env, 641 jobject obj) { 642 content::NavigationEntry* entry = 643 web_contents_->GetController().GetActiveEntry(); 644 if (!entry) 645 return ScopedJavaLocalRef<jbyteArray>(); 646 // Get the certificate 647 int cert_id = entry->GetSSL().cert_id; 648 scoped_refptr<net::X509Certificate> cert; 649 bool ok = content::CertStore::GetInstance()->RetrieveCert(cert_id, &cert); 650 if (!ok) 651 return ScopedJavaLocalRef<jbyteArray>(); 652 653 // Convert the certificate and return it 654 std::string der_string; 655 net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_string); 656 return base::android::ToJavaByteArray(env, 657 reinterpret_cast<const uint8*>(der_string.data()), der_string.length()); 658} 659 660void AwContents::RequestNewHitTestDataAt(JNIEnv* env, jobject obj, 661 jint x, jint y) { 662 render_view_host_ext_->RequestNewHitTestDataAt(x, y); 663} 664 665void AwContents::UpdateLastHitTestData(JNIEnv* env, jobject obj) { 666 if (!render_view_host_ext_->HasNewHitTestData()) return; 667 668 const AwHitTestData& data = render_view_host_ext_->GetLastHitTestData(); 669 render_view_host_ext_->MarkHitTestDataRead(); 670 671 // Make sure to null the Java object if data is empty/invalid. 672 ScopedJavaLocalRef<jstring> extra_data_for_type; 673 if (data.extra_data_for_type.length()) 674 extra_data_for_type = ConvertUTF8ToJavaString( 675 env, data.extra_data_for_type); 676 677 ScopedJavaLocalRef<jstring> href; 678 if (data.href.length()) 679 href = ConvertUTF16ToJavaString(env, data.href); 680 681 ScopedJavaLocalRef<jstring> anchor_text; 682 if (data.anchor_text.length()) 683 anchor_text = ConvertUTF16ToJavaString(env, data.anchor_text); 684 685 ScopedJavaLocalRef<jstring> img_src; 686 if (data.img_src.is_valid()) 687 img_src = ConvertUTF8ToJavaString(env, data.img_src.spec()); 688 689 Java_AwContents_updateHitTestData(env, 690 obj, 691 data.type, 692 extra_data_for_type.obj(), 693 href.obj(), 694 anchor_text.obj(), 695 img_src.obj()); 696} 697 698void AwContents::OnSizeChanged(JNIEnv* env, jobject obj, 699 int w, int h, int ow, int oh) { 700 browser_view_renderer_->OnSizeChanged(w, h); 701} 702 703void AwContents::SetViewVisibility(JNIEnv* env, jobject obj, bool visible) { 704 browser_view_renderer_->SetViewVisibility(visible); 705} 706 707void AwContents::SetWindowVisibility(JNIEnv* env, jobject obj, bool visible) { 708 browser_view_renderer_->SetWindowVisibility(visible); 709} 710 711void AwContents::SetIsPaused(JNIEnv* env, jobject obj, bool paused) { 712 browser_view_renderer_->SetIsPaused(paused); 713 if (paused) { 714 ContentViewCore* cvc = 715 ContentViewCore::FromWebContents(web_contents_.get()); 716 if (cvc) 717 cvc->PauseVideo(); 718 } 719} 720 721void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) { 722 browser_view_renderer_->OnAttachedToWindow(w, h); 723} 724 725void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) { 726 browser_view_renderer_->OnDetachedFromWindow(); 727} 728 729base::android::ScopedJavaLocalRef<jbyteArray> 730AwContents::GetOpaqueState(JNIEnv* env, jobject obj) { 731 // Required optimization in WebViewClassic to not save any state if 732 // there has been no navigations. 733 if (!web_contents_->GetController().GetEntryCount()) 734 return ScopedJavaLocalRef<jbyteArray>(); 735 736 Pickle pickle; 737 if (!WriteToPickle(*web_contents_, &pickle)) { 738 return ScopedJavaLocalRef<jbyteArray>(); 739 } else { 740 return base::android::ToJavaByteArray(env, 741 reinterpret_cast<const uint8*>(pickle.data()), pickle.size()); 742 } 743} 744 745jboolean AwContents::RestoreFromOpaqueState( 746 JNIEnv* env, jobject obj, jbyteArray state) { 747 // TODO(boliu): This copy can be optimized out if this is a performance 748 // problem. 749 std::vector<uint8> state_vector; 750 base::android::JavaByteArrayToByteVector(env, state, &state_vector); 751 752 Pickle pickle(reinterpret_cast<const char*>(state_vector.begin()), 753 state_vector.size()); 754 PickleIterator iterator(pickle); 755 756 return RestoreFromPickle(&iterator, web_contents_.get()); 757} 758 759bool AwContents::OnDraw(JNIEnv* env, 760 jobject obj, 761 jobject canvas, 762 jboolean is_hardware_accelerated, 763 jint scroll_x, 764 jint scroll_y, 765 jint clip_left, 766 jint clip_top, 767 jint clip_right, 768 jint clip_bottom) { 769 return browser_view_renderer_->OnDraw( 770 canvas, 771 is_hardware_accelerated, 772 gfx::Vector2d(scroll_x, scroll_y), 773 gfx::Rect( 774 clip_left, clip_top, clip_right - clip_left, clip_bottom - clip_top)); 775} 776 777void AwContents::SetGlobalVisibleRect(JNIEnv* env, 778 jobject obj, 779 jint visible_left, 780 jint visible_top, 781 jint visible_right, 782 jint visible_bottom) { 783 browser_view_renderer_->SetGlobalVisibleRect( 784 gfx::Rect(visible_left, 785 visible_top, 786 visible_right - visible_left, 787 visible_bottom - visible_top)); 788} 789 790void AwContents::SetPendingWebContentsForPopup( 791 scoped_ptr<content::WebContents> pending) { 792 if (pending_contents_.get()) { 793 // TODO(benm): Support holding multiple pop up window requests. 794 LOG(WARNING) << "Blocking popup window creation as an outstanding " 795 << "popup window is still pending."; 796 base::MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release()); 797 return; 798 } 799 pending_contents_.reset(new AwContents(pending.Pass())); 800} 801 802void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) { 803 web_contents_->FocusThroughTabTraversal(false); 804} 805 806void AwContents::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) { 807 render_view_host_ext_->SetBackgroundColor(color); 808} 809 810jint AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) { 811 return reinterpret_cast<jint>(pending_contents_.release()); 812} 813 814gfx::Point AwContents::GetLocationOnScreen() { 815 JNIEnv* env = AttachCurrentThread(); 816 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 817 if (obj.is_null()) 818 return gfx::Point(); 819 std::vector<int> location; 820 base::android::JavaIntArrayToIntVector( 821 env, 822 Java_AwContents_getLocationOnScreen(env, obj.obj()).obj(), 823 &location); 824 return gfx::Point(location[0], location[1]); 825} 826 827void AwContents::SetMaxContainerViewScrollOffset(gfx::Vector2d new_value) { 828 JNIEnv* env = AttachCurrentThread(); 829 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 830 if (obj.is_null()) 831 return; 832 Java_AwContents_setMaxContainerViewScrollOffset( 833 env, obj.obj(), new_value.x(), new_value.y()); 834} 835 836void AwContents::ScrollContainerViewTo(gfx::Vector2d new_value) { 837 JNIEnv* env = AttachCurrentThread(); 838 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 839 if (obj.is_null()) 840 return; 841 Java_AwContents_scrollContainerViewTo( 842 env, obj.obj(), new_value.x(), new_value.y()); 843} 844 845bool AwContents::IsFlingActive() const { 846 JNIEnv* env = AttachCurrentThread(); 847 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 848 if (obj.is_null()) 849 return false; 850 return Java_AwContents_isFlingActive(env, obj.obj()); 851} 852 853void AwContents::SetPageScaleFactor(float page_scale_factor) { 854 JNIEnv* env = AttachCurrentThread(); 855 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 856 if (obj.is_null()) 857 return; 858 Java_AwContents_setPageScaleFactor(env, obj.obj(), page_scale_factor); 859} 860 861void AwContents::SetContentsSize(gfx::SizeF contents_size_dip) { 862 JNIEnv* env = AttachCurrentThread(); 863 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 864 if (obj.is_null()) 865 return; 866 Java_AwContents_setContentsSize( 867 env, obj.obj(), contents_size_dip.width(), contents_size_dip.height()); 868} 869 870void AwContents::DidOverscroll(gfx::Vector2d overscroll_delta) { 871 JNIEnv* env = AttachCurrentThread(); 872 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 873 if (obj.is_null()) 874 return; 875 Java_AwContents_didOverscroll( 876 env, obj.obj(), overscroll_delta.x(), overscroll_delta.y()); 877} 878 879void AwContents::SetDipScale(JNIEnv* env, jobject obj, jfloat dip_scale) { 880 browser_view_renderer_->SetDipScale(dip_scale); 881} 882 883void AwContents::SetFixedLayoutSize(JNIEnv* env, 884 jobject obj, 885 jint width_dip, 886 jint height_dip) { 887 render_view_host_ext_->SetFixedLayoutSize(gfx::Size(width_dip, height_dip)); 888} 889 890void AwContents::ScrollTo(JNIEnv* env, jobject obj, jint x, jint y) { 891 browser_view_renderer_->ScrollTo(gfx::Vector2d(x, y)); 892} 893 894void AwContents::OnWebLayoutPageScaleFactorChanged(float page_scale_factor) { 895 JNIEnv* env = AttachCurrentThread(); 896 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 897 if (obj.is_null()) 898 return; 899 Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj.obj(), 900 page_scale_factor); 901} 902 903void AwContents::OnWebLayoutContentsSizeChanged( 904 const gfx::Size& contents_size) { 905 JNIEnv* env = AttachCurrentThread(); 906 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 907 if (obj.is_null()) 908 return; 909 Java_AwContents_onWebLayoutContentsSizeChanged( 910 env, obj.obj(), contents_size.width(), contents_size.height()); 911} 912 913jint AwContents::CapturePicture(JNIEnv* env, 914 jobject obj, 915 int width, 916 int height) { 917 return reinterpret_cast<jint>(new AwPicture( 918 browser_view_renderer_->CapturePicture(width, height))); 919} 920 921void AwContents::EnableOnNewPicture(JNIEnv* env, 922 jobject obj, 923 jboolean enabled) { 924 browser_view_renderer_->EnableOnNewPicture(enabled); 925} 926 927void AwContents::SetJsOnlineProperty(JNIEnv* env, 928 jobject obj, 929 jboolean network_up) { 930 render_view_host_ext_->SetJsOnlineProperty(network_up); 931} 932 933void AwContents::TrimMemory(JNIEnv* env, jobject obj, jint level) { 934 browser_view_renderer_->TrimMemory(level); 935} 936 937void SetShouldDownloadFavicons(JNIEnv* env, jclass jclazz) { 938 g_should_download_favicons = true; 939} 940 941} // namespace android_webview 942