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