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