aw_contents.cc revision 5db5c4ec98571177cc4dec6df1ad33269f632543
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, pdfExporter, browser_view_renderer_.get())); 324} 325// END: Printing fork b/10190508 326 327void AwContents::PerformLongClick() { 328 JNIEnv* env = AttachCurrentThread(); 329 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 330 if (obj.is_null()) 331 return; 332 333 Java_AwContents_performLongClick(env, obj.obj()); 334} 335 336bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler, 337 const std::string& host, 338 const std::string& realm) { 339 JNIEnv* env = AttachCurrentThread(); 340 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 341 if (obj.is_null()) 342 return false; 343 344 ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host); 345 ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm); 346 Java_AwContents_onReceivedHttpAuthRequest(env, obj.obj(), handler.obj(), 347 jhost.obj(), jrealm.obj()); 348 return true; 349} 350 351void AwContents::AddVisitedLinks(JNIEnv* env, 352 jobject obj, 353 jobjectArray jvisited_links) { 354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 355 std::vector<string16> visited_link_strings; 356 base::android::AppendJavaStringArrayToStringVector( 357 env, jvisited_links, &visited_link_strings); 358 359 std::vector<GURL> visited_link_gurls; 360 for (std::vector<string16>::const_iterator itr = visited_link_strings.begin(); 361 itr != visited_link_strings.end(); 362 ++itr) { 363 visited_link_gurls.push_back(GURL(*itr)); 364 } 365 366 AwBrowserContext::FromWebContents(web_contents_.get()) 367 ->AddVisitedURLs(visited_link_gurls); 368} 369 370bool RegisterAwContents(JNIEnv* env) { 371 return RegisterNativesImpl(env) >= 0; 372} 373 374namespace { 375 376void ShowGeolocationPromptHelperTask(const JavaObjectWeakGlobalRef& java_ref, 377 const GURL& origin) { 378 JNIEnv* env = AttachCurrentThread(); 379 ScopedJavaLocalRef<jobject> j_ref = java_ref.get(env); 380 if (j_ref.obj()) { 381 ScopedJavaLocalRef<jstring> j_origin( 382 ConvertUTF8ToJavaString(env, origin.spec())); 383 Java_AwContents_onGeolocationPermissionsShowPrompt(env, 384 j_ref.obj(), 385 j_origin.obj()); 386 } 387} 388 389void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref, 390 const GURL& origin) { 391 JNIEnv* env = AttachCurrentThread(); 392 if (java_ref.get(env).obj()) { 393 content::BrowserThread::PostTask( 394 content::BrowserThread::UI, 395 FROM_HERE, 396 base::Bind(&ShowGeolocationPromptHelperTask, 397 java_ref, 398 origin)); 399 } 400} 401 402} // anonymous namespace 403 404void AwContents::ShowGeolocationPrompt(const GURL& requesting_frame, 405 base::Callback<void(bool)> callback) { 406 GURL origin = requesting_frame.GetOrigin(); 407 bool show_prompt = pending_geolocation_prompts_.empty(); 408 pending_geolocation_prompts_.push_back(OriginCallback(origin, callback)); 409 if (show_prompt) { 410 ShowGeolocationPromptHelper(java_ref_, origin); 411 } 412} 413 414// Invoked from Java 415void AwContents::InvokeGeolocationCallback(JNIEnv* env, 416 jobject obj, 417 jboolean value, 418 jstring origin) { 419 GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin)); 420 if (callback_origin.GetOrigin() == 421 pending_geolocation_prompts_.front().first) { 422 pending_geolocation_prompts_.front().second.Run(value); 423 pending_geolocation_prompts_.pop_front(); 424 if (!pending_geolocation_prompts_.empty()) { 425 ShowGeolocationPromptHelper(java_ref_, 426 pending_geolocation_prompts_.front().first); 427 } 428 } 429} 430 431void AwContents::HideGeolocationPrompt(const GURL& origin) { 432 bool removed_current_outstanding_callback = false; 433 std::list<OriginCallback>::iterator it = pending_geolocation_prompts_.begin(); 434 while (it != pending_geolocation_prompts_.end()) { 435 if ((*it).first == origin.GetOrigin()) { 436 if (it == pending_geolocation_prompts_.begin()) { 437 removed_current_outstanding_callback = true; 438 } 439 it = pending_geolocation_prompts_.erase(it); 440 } else { 441 ++it; 442 } 443 } 444 445 if (removed_current_outstanding_callback) { 446 JNIEnv* env = AttachCurrentThread(); 447 ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env); 448 if (j_ref.obj()) { 449 Java_AwContents_onGeolocationPermissionsHidePrompt(env, j_ref.obj()); 450 } 451 if (!pending_geolocation_prompts_.empty()) { 452 ShowGeolocationPromptHelper(java_ref_, 453 pending_geolocation_prompts_.front().first); 454 } 455 } 456} 457 458void AwContents::FindAllAsync(JNIEnv* env, jobject obj, jstring search_string) { 459 GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string)); 460} 461 462void AwContents::FindNext(JNIEnv* env, jobject obj, jboolean forward) { 463 GetFindHelper()->FindNext(forward); 464} 465 466void AwContents::ClearMatches(JNIEnv* env, jobject obj) { 467 GetFindHelper()->ClearMatches(); 468} 469 470void AwContents::ClearCache( 471 JNIEnv* env, 472 jobject obj, 473 jboolean include_disk_files) { 474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 475 render_view_host_ext_->ClearCache(); 476 477 if (include_disk_files) { 478 RemoveHttpDiskCache(web_contents_->GetBrowserContext(), 479 web_contents_->GetRoutingID()); 480 } 481} 482 483FindHelper* AwContents::GetFindHelper() { 484 if (!find_helper_.get()) { 485 find_helper_.reset(new FindHelper(web_contents_.get())); 486 find_helper_->SetListener(this); 487 } 488 return find_helper_.get(); 489} 490 491void AwContents::OnFindResultReceived(int active_ordinal, 492 int match_count, 493 bool finished) { 494 JNIEnv* env = AttachCurrentThread(); 495 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 496 if (obj.is_null()) 497 return; 498 499 Java_AwContents_onFindResultReceived( 500 env, obj.obj(), active_ordinal, match_count, finished); 501} 502 503void AwContents::OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap) { 504 JNIEnv* env = AttachCurrentThread(); 505 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 506 if (obj.is_null()) 507 return; 508 509 content::NavigationEntry* entry = 510 web_contents_->GetController().GetActiveEntry(); 511 512 if (entry) { 513 entry->GetFavicon().valid = true; 514 entry->GetFavicon().url = icon_url; 515 entry->GetFavicon().image = gfx::Image::CreateFrom1xBitmap(bitmap); 516 } 517 518 Java_AwContents_onReceivedIcon( 519 env, obj.obj(), gfx::ConvertToJavaBitmap(&bitmap).obj()); 520} 521 522void AwContents::OnReceivedTouchIconUrl(const std::string& url, 523 bool precomposed) { 524 JNIEnv* env = AttachCurrentThread(); 525 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 526 if (obj.is_null()) 527 return; 528 529 Java_AwContents_onReceivedTouchIconUrl( 530 env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed); 531} 532 533bool AwContents::RequestDrawGL(jobject canvas) { 534 JNIEnv* env = AttachCurrentThread(); 535 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 536 if (obj.is_null()) 537 return false; 538 return Java_AwContents_requestDrawGL(env, obj.obj(), canvas); 539} 540 541void AwContents::PostInvalidate() { 542 JNIEnv* env = AttachCurrentThread(); 543 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 544 if (!obj.is_null()) 545 Java_AwContents_postInvalidateOnAnimation(env, obj.obj()); 546} 547 548void AwContents::UpdateGlobalVisibleRect() { 549 JNIEnv* env = AttachCurrentThread(); 550 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 551 if (!obj.is_null()) 552 Java_AwContents_updateGlobalVisibleRect(env, obj.obj()); 553} 554 555void AwContents::OnNewPicture() { 556 JNIEnv* env = AttachCurrentThread(); 557 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 558 if (!obj.is_null()) 559 Java_AwContents_onNewPicture(env, obj.obj()); 560} 561 562base::android::ScopedJavaLocalRef<jbyteArray> 563 AwContents::GetCertificate(JNIEnv* env, 564 jobject obj) { 565 content::NavigationEntry* entry = 566 web_contents_->GetController().GetActiveEntry(); 567 if (!entry) 568 return ScopedJavaLocalRef<jbyteArray>(); 569 // Get the certificate 570 int cert_id = entry->GetSSL().cert_id; 571 scoped_refptr<net::X509Certificate> cert; 572 bool ok = content::CertStore::GetInstance()->RetrieveCert(cert_id, &cert); 573 if (!ok) 574 return ScopedJavaLocalRef<jbyteArray>(); 575 576 // Convert the certificate and return it 577 std::string der_string; 578 net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_string); 579 return base::android::ToJavaByteArray(env, 580 reinterpret_cast<const uint8*>(der_string.data()), der_string.length()); 581} 582 583void AwContents::RequestNewHitTestDataAt(JNIEnv* env, jobject obj, 584 jint x, jint y) { 585 render_view_host_ext_->RequestNewHitTestDataAt(x, y); 586} 587 588void AwContents::UpdateLastHitTestData(JNIEnv* env, jobject obj) { 589 if (!render_view_host_ext_->HasNewHitTestData()) return; 590 591 const AwHitTestData& data = render_view_host_ext_->GetLastHitTestData(); 592 render_view_host_ext_->MarkHitTestDataRead(); 593 594 // Make sure to null the Java object if data is empty/invalid. 595 ScopedJavaLocalRef<jstring> extra_data_for_type; 596 if (data.extra_data_for_type.length()) 597 extra_data_for_type = ConvertUTF8ToJavaString( 598 env, data.extra_data_for_type); 599 600 ScopedJavaLocalRef<jstring> href; 601 if (data.href.length()) 602 href = ConvertUTF16ToJavaString(env, data.href); 603 604 ScopedJavaLocalRef<jstring> anchor_text; 605 if (data.anchor_text.length()) 606 anchor_text = ConvertUTF16ToJavaString(env, data.anchor_text); 607 608 ScopedJavaLocalRef<jstring> img_src; 609 if (data.img_src.is_valid()) 610 img_src = ConvertUTF8ToJavaString(env, data.img_src.spec()); 611 612 Java_AwContents_updateHitTestData(env, 613 obj, 614 data.type, 615 extra_data_for_type.obj(), 616 href.obj(), 617 anchor_text.obj(), 618 img_src.obj()); 619} 620 621void AwContents::OnSizeChanged(JNIEnv* env, jobject obj, 622 int w, int h, int ow, int oh) { 623 browser_view_renderer_->OnSizeChanged(w, h); 624} 625 626void AwContents::SetViewVisibility(JNIEnv* env, jobject obj, bool visible) { 627 browser_view_renderer_->SetViewVisibility(visible); 628} 629 630void AwContents::SetWindowVisibility(JNIEnv* env, jobject obj, bool visible) { 631 browser_view_renderer_->SetWindowVisibility(visible); 632} 633 634void AwContents::SetIsPaused(JNIEnv* env, jobject obj, bool paused) { 635 browser_view_renderer_->SetIsPaused(paused); 636} 637 638void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) { 639 browser_view_renderer_->OnAttachedToWindow(w, h); 640} 641 642void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) { 643 browser_view_renderer_->OnDetachedFromWindow(); 644} 645 646base::android::ScopedJavaLocalRef<jbyteArray> 647AwContents::GetOpaqueState(JNIEnv* env, jobject obj) { 648 // Required optimization in WebViewClassic to not save any state if 649 // there has been no navigations. 650 if (!web_contents_->GetController().GetEntryCount()) 651 return ScopedJavaLocalRef<jbyteArray>(); 652 653 Pickle pickle; 654 if (!WriteToPickle(*web_contents_, &pickle)) { 655 return ScopedJavaLocalRef<jbyteArray>(); 656 } else { 657 return base::android::ToJavaByteArray(env, 658 reinterpret_cast<const uint8*>(pickle.data()), pickle.size()); 659 } 660} 661 662jboolean AwContents::RestoreFromOpaqueState( 663 JNIEnv* env, jobject obj, jbyteArray state) { 664 // TODO(boliu): This copy can be optimized out if this is a performance 665 // problem. 666 std::vector<uint8> state_vector; 667 base::android::JavaByteArrayToByteVector(env, state, &state_vector); 668 669 Pickle pickle(reinterpret_cast<const char*>(state_vector.begin()), 670 state_vector.size()); 671 PickleIterator iterator(pickle); 672 673 return RestoreFromPickle(&iterator, web_contents_.get()); 674} 675 676bool AwContents::OnDraw(JNIEnv* env, 677 jobject obj, 678 jobject canvas, 679 jboolean is_hardware_accelerated, 680 jint scroll_x, 681 jint scroll_y, 682 jint clip_left, 683 jint clip_top, 684 jint clip_right, 685 jint clip_bottom) { 686 return browser_view_renderer_->OnDraw( 687 canvas, 688 is_hardware_accelerated, 689 gfx::Vector2d(scroll_x, scroll_y), 690 gfx::Rect( 691 clip_left, clip_top, clip_right - clip_left, clip_bottom - clip_top)); 692} 693 694void AwContents::SetGlobalVisibleRect(JNIEnv* env, 695 jobject obj, 696 jint visible_left, 697 jint visible_top, 698 jint visible_right, 699 jint visible_bottom) { 700 browser_view_renderer_->SetGlobalVisibleRect( 701 gfx::Rect(visible_left, 702 visible_top, 703 visible_right - visible_left, 704 visible_bottom - visible_top)); 705} 706 707void AwContents::SetPendingWebContentsForPopup( 708 scoped_ptr<content::WebContents> pending) { 709 if (pending_contents_.get()) { 710 // TODO(benm): Support holding multiple pop up window requests. 711 LOG(WARNING) << "Blocking popup window creation as an outstanding " 712 << "popup window is still pending."; 713 base::MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release()); 714 return; 715 } 716 pending_contents_.reset(new AwContents(pending.Pass())); 717} 718 719void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) { 720 web_contents_->FocusThroughTabTraversal(false); 721} 722 723void AwContents::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) { 724 render_view_host_ext_->SetBackgroundColor(color); 725} 726 727jint AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) { 728 return reinterpret_cast<jint>(pending_contents_.release()); 729} 730 731gfx::Point AwContents::GetLocationOnScreen() { 732 JNIEnv* env = AttachCurrentThread(); 733 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 734 if (obj.is_null()) 735 return gfx::Point(); 736 std::vector<int> location; 737 base::android::JavaIntArrayToIntVector( 738 env, 739 Java_AwContents_getLocationOnScreen(env, obj.obj()).obj(), 740 &location); 741 return gfx::Point(location[0], location[1]); 742} 743 744void AwContents::ScrollContainerViewTo(gfx::Vector2d new_value) { 745 JNIEnv* env = AttachCurrentThread(); 746 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 747 if (obj.is_null()) 748 return; 749 Java_AwContents_scrollContainerViewTo( 750 env, obj.obj(), new_value.x(), new_value.y()); 751} 752 753 754void AwContents::DidOverscroll(gfx::Vector2d overscroll_delta) { 755 JNIEnv* env = AttachCurrentThread(); 756 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 757 if (obj.is_null()) 758 return; 759 Java_AwContents_didOverscroll( 760 env, obj.obj(), overscroll_delta.x(), overscroll_delta.y()); 761} 762 763void AwContents::SetDipScale(JNIEnv* env, jobject obj, jfloat dipScale) { 764 browser_view_renderer_->SetDipScale(dipScale); 765} 766 767void AwContents::SetDisplayedPageScaleFactor(JNIEnv* env, 768 jobject obj, 769 jfloat pageScaleFactor) { 770 browser_view_renderer_->SetPageScaleFactor(pageScaleFactor); 771} 772 773void AwContents::ScrollTo(JNIEnv* env, jobject obj, jint xPix, jint yPix) { 774 browser_view_renderer_->ScrollTo(gfx::Vector2d(xPix, yPix)); 775} 776 777void AwContents::OnWebLayoutPageScaleFactorChanged(float page_scale_factor) { 778 JNIEnv* env = AttachCurrentThread(); 779 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 780 if (obj.is_null()) 781 return; 782 Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj.obj(), 783 page_scale_factor); 784} 785 786jint AwContents::CapturePicture(JNIEnv* env, 787 jobject obj, 788 int width, 789 int height) { 790 return reinterpret_cast<jint>(new AwPicture( 791 browser_view_renderer_->CapturePicture(width, height))); 792} 793 794void AwContents::EnableOnNewPicture(JNIEnv* env, 795 jobject obj, 796 jboolean enabled) { 797 browser_view_renderer_->EnableOnNewPicture(enabled); 798} 799 800void AwContents::SetJsOnlineProperty(JNIEnv* env, 801 jobject obj, 802 jboolean network_up) { 803 render_view_host_ext_->SetJsOnlineProperty(network_up); 804} 805 806} // namespace android_webview 807