1 // Copyright (c) 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.
5 #include "chrome/browser/android/tab_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/debug/trace_event.h"
11 #include "chrome/browser/android/chrome_web_contents_delegate_android.h"
12 #include "chrome/browser/browser_about_handler.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
15 #include "chrome/browser/favicon/favicon_tab_helper.h"
16 #include "chrome/browser/google/google_url_tracker_factory.h"
17 #include "chrome/browser/infobars/infobar_service.h"
18 #include "chrome/browser/prerender/prerender_contents.h"
19 #include "chrome/browser/prerender/prerender_manager.h"
20 #include "chrome/browser/prerender/prerender_manager_factory.h"
21 #include "chrome/browser/printing/print_view_manager_basic.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/profiles/profile_android.h"
24 #include "chrome/browser/search/instant_service.h"
25 #include "chrome/browser/search/instant_service_factory.h"
26 #include "chrome/browser/search/search.h"
27 #include "chrome/browser/sessions/session_tab_helper.h"
28 #include "chrome/browser/sessions/tab_restore_service.h"
29 #include "chrome/browser/sessions/tab_restore_service_factory.h"
30 #include "chrome/browser/sync/glue/synced_tab_delegate_android.h"
31 #include "chrome/browser/tab_contents/tab_util.h"
32 #include "chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.h"
33 #include "chrome/browser/ui/android/context_menu_helper.h"
34 #include "chrome/browser/ui/android/infobars/infobar_container_android.h"
35 #include "chrome/browser/ui/android/tab_model/tab_model.h"
36 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
37 #include "chrome/browser/ui/android/window_android_helper.h"
38 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
39 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
40 #include "chrome/browser/ui/search/search_tab_helper.h"
41 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
42 #include "chrome/browser/ui/tab_helpers.h"
43 #include "chrome/common/instant_types.h"
44 #include "chrome/common/url_constants.h"
45 #include "components/google/core/browser/google_url_tracker.h"
46 #include "components/google/core/browser/google_util.h"
47 #include "components/infobars/core/infobar_container.h"
48 #include "components/url_fixer/url_fixer.h"
49 #include "content/public/browser/android/content_view_core.h"
50 #include "content/public/browser/navigation_entry.h"
51 #include "content/public/browser/notification_service.h"
52 #include "content/public/browser/render_process_host.h"
53 #include "content/public/browser/user_metrics.h"
54 #include "content/public/browser/web_contents.h"
55 #include "jni/Tab_jni.h"
56 #include "skia/ext/image_operations.h"
57 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
58 #include "ui/base/resource/resource_bundle.h"
59 #include "ui/base/window_open_disposition.h"
60 #include "ui/gfx/android/device_display_info.h"
61 #include "ui/gfx/android/java_bitmap.h"
62 #include "ui/gfx/favicon_size.h"
63 #include "ui/gfx/image/image_skia.h"
65 using content::GlobalRequestID
;
66 using content::NavigationController
;
67 using content::WebContents
;
71 WebContents
* CreateTargetContents(const chrome::NavigateParams
& params
,
73 Profile
* profile
= params
.initiating_profile
;
75 if (profile
->IsOffTheRecord() || params
.disposition
== OFF_THE_RECORD
) {
76 profile
= profile
->GetOffTheRecordProfile();
78 WebContents::CreateParams
create_params(
79 profile
, tab_util::GetSiteInstanceForNewTab(profile
, url
));
80 if (params
.source_contents
) {
81 create_params
.initial_size
=
82 params
.source_contents
->GetContainerBounds().size();
83 if (params
.should_set_opener
)
84 create_params
.opener
= params
.source_contents
;
86 if (params
.disposition
== NEW_BACKGROUND_TAB
)
87 create_params
.initially_hidden
= true;
89 WebContents
* target_contents
= WebContents::Create(create_params
);
91 return target_contents
;
94 bool MaybeSwapWithPrerender(const GURL
& url
, chrome::NavigateParams
* params
) {
96 Profile::FromBrowserContext(params
->target_contents
->GetBrowserContext());
98 prerender::PrerenderManager
* prerender_manager
=
99 prerender::PrerenderManagerFactory::GetForProfile(profile
);
100 if (!prerender_manager
)
102 return prerender_manager
->MaybeUsePrerenderedPage(url
, params
);
107 TabAndroid
* TabAndroid::FromWebContents(content::WebContents
* web_contents
) {
108 CoreTabHelper
* core_tab_helper
= CoreTabHelper::FromWebContents(web_contents
);
109 if (!core_tab_helper
)
112 CoreTabHelperDelegate
* core_delegate
= core_tab_helper
->delegate();
116 return static_cast<TabAndroid
*>(core_delegate
);
119 TabAndroid
* TabAndroid::GetNativeTab(JNIEnv
* env
, jobject obj
) {
120 return reinterpret_cast<TabAndroid
*>(Java_Tab_getNativePtr(env
, obj
));
123 void TabAndroid::AttachTabHelpers(content::WebContents
* web_contents
) {
124 DCHECK(web_contents
);
126 TabHelpers::AttachTabHelpers(web_contents
);
129 TabAndroid::TabAndroid(JNIEnv
* env
, jobject obj
)
130 : weak_java_tab_(env
, obj
),
131 synced_tab_delegate_(new browser_sync::SyncedTabDelegateAndroid(this)) {
132 Java_Tab_setNativePtr(env
, obj
, reinterpret_cast<intptr_t>(this));
135 TabAndroid::~TabAndroid() {
136 JNIEnv
* env
= base::android::AttachCurrentThread();
137 Java_Tab_clearNativePtr(env
, weak_java_tab_
.get(env
).obj());
140 base::android::ScopedJavaLocalRef
<jobject
> TabAndroid::GetJavaObject() {
141 JNIEnv
* env
= base::android::AttachCurrentThread();
142 return weak_java_tab_
.get(env
);
145 int TabAndroid::GetAndroidId() const {
146 JNIEnv
* env
= base::android::AttachCurrentThread();
147 return Java_Tab_getId(env
, weak_java_tab_
.get(env
).obj());
150 int TabAndroid::GetSyncId() const {
151 JNIEnv
* env
= base::android::AttachCurrentThread();
152 return Java_Tab_getSyncId(env
, weak_java_tab_
.get(env
).obj());
155 base::string16
TabAndroid::GetTitle() const {
156 JNIEnv
* env
= base::android::AttachCurrentThread();
157 return base::android::ConvertJavaStringToUTF16(
158 Java_Tab_getTitle(env
, weak_java_tab_
.get(env
).obj()));
161 GURL
TabAndroid::GetURL() const {
162 JNIEnv
* env
= base::android::AttachCurrentThread();
163 return GURL(base::android::ConvertJavaStringToUTF8(
164 Java_Tab_getUrl(env
, weak_java_tab_
.get(env
).obj())));
167 bool TabAndroid::LoadIfNeeded() {
168 JNIEnv
* env
= base::android::AttachCurrentThread();
169 return Java_Tab_loadIfNeeded(env
, weak_java_tab_
.get(env
).obj());
172 content::ContentViewCore
* TabAndroid::GetContentViewCore() const {
176 return content::ContentViewCore::FromWebContents(web_contents());
179 Profile
* TabAndroid::GetProfile() const {
183 return Profile::FromBrowserContext(web_contents()->GetBrowserContext());
186 browser_sync::SyncedTabDelegate
* TabAndroid::GetSyncedTabDelegate() const {
187 return synced_tab_delegate_
.get();
190 void TabAndroid::SetWindowSessionID(SessionID::id_type window_id
) {
191 session_window_id_
.set_id(window_id
);
196 SessionTabHelper
* session_tab_helper
=
197 SessionTabHelper::FromWebContents(web_contents());
198 session_tab_helper
->SetWindowID(session_window_id_
);
201 void TabAndroid::SetSyncId(int sync_id
) {
202 JNIEnv
* env
= base::android::AttachCurrentThread();
203 Java_Tab_setSyncId(env
, weak_java_tab_
.get(env
).obj(), sync_id
);
206 void TabAndroid::HandlePopupNavigation(chrome::NavigateParams
* params
) {
207 if (params
->disposition
!= SUPPRESS_OPEN
&&
208 params
->disposition
!= SAVE_TO_DISK
&&
209 params
->disposition
!= IGNORE_ACTION
) {
210 if (!params
->url
.is_empty()) {
211 bool was_blocked
= false;
212 GURL
url(params
->url
);
213 if (params
->disposition
== CURRENT_TAB
) {
214 params
->target_contents
= web_contents_
.get();
215 if (!MaybeSwapWithPrerender(url
, params
)) {
216 NavigationController::LoadURLParams
load_url_params(url
);
217 MakeLoadURLParams(params
, &load_url_params
);
218 params
->target_contents
->GetController().LoadURLWithParams(
222 params
->target_contents
= CreateTargetContents(*params
, url
);
223 NavigationController::LoadURLParams
load_url_params(url
);
224 MakeLoadURLParams(params
, &load_url_params
);
225 params
->target_contents
->GetController().LoadURLWithParams(
227 web_contents_delegate_
->AddNewContents(params
->source_contents
,
228 params
->target_contents
,
230 params
->window_bounds
,
231 params
->user_gesture
,
234 params
->target_contents
= NULL
;
240 bool TabAndroid::HasPrerenderedUrl(GURL gurl
) {
241 prerender::PrerenderManager
* prerender_manager
= GetPrerenderManager();
242 if (!prerender_manager
)
245 std::vector
<content::WebContents
*> contents
=
246 prerender_manager
->GetAllPrerenderingContents();
247 prerender::PrerenderContents
* prerender_contents
;
248 for (size_t i
= 0; i
< contents
.size(); ++i
) {
249 prerender_contents
= prerender_manager
->
250 GetPrerenderContents(contents
.at(i
));
251 if (prerender_contents
->prerender_url() == gurl
&&
252 prerender_contents
->has_finished_loading()) {
259 void TabAndroid::MakeLoadURLParams(
260 chrome::NavigateParams
* params
,
261 NavigationController::LoadURLParams
* load_url_params
) {
262 load_url_params
->referrer
= params
->referrer
;
263 load_url_params
->frame_tree_node_id
= params
->frame_tree_node_id
;
264 load_url_params
->redirect_chain
= params
->redirect_chain
;
265 load_url_params
->transition_type
= params
->transition
;
266 load_url_params
->extra_headers
= params
->extra_headers
;
267 load_url_params
->should_replace_current_entry
=
268 params
->should_replace_current_entry
;
270 if (params
->transferred_global_request_id
!= GlobalRequestID()) {
271 load_url_params
->transferred_global_request_id
=
272 params
->transferred_global_request_id
;
274 load_url_params
->is_renderer_initiated
= params
->is_renderer_initiated
;
276 // Only allows the browser-initiated navigation to use POST.
277 if (params
->uses_post
&& !params
->is_renderer_initiated
) {
278 load_url_params
->load_type
=
279 NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST
;
280 load_url_params
->browser_initiated_post_data
=
281 params
->browser_initiated_post_data
;
285 void TabAndroid::SwapTabContents(content::WebContents
* old_contents
,
286 content::WebContents
* new_contents
,
288 bool did_finish_load
) {
289 JNIEnv
* env
= base::android::AttachCurrentThread();
291 // We need to notify the native InfobarContainer so infobars can be swapped.
292 InfoBarContainerAndroid
* infobar_container
=
293 reinterpret_cast<InfoBarContainerAndroid
*>(
294 Java_Tab_getNativeInfoBarContainer(
296 weak_java_tab_
.get(env
).obj()));
297 InfoBarService
* new_infobar_service
=
298 new_contents
? InfoBarService::FromWebContents(new_contents
) : NULL
;
299 infobar_container
->ChangeInfoBarManager(new_infobar_service
);
301 Java_Tab_swapWebContents(
303 weak_java_tab_
.get(env
).obj(),
304 reinterpret_cast<intptr_t>(new_contents
),
309 void TabAndroid::DefaultSearchProviderChanged() {
310 // TODO(kmadhusu): Move this function definition to a common place and update
311 // BrowserInstantController::DefaultSearchProviderChanged to use the same.
315 InstantService
* instant_service
=
316 InstantServiceFactory::GetForProfile(GetProfile());
317 if (!instant_service
)
320 // Send new search URLs to the renderer.
321 content::RenderProcessHost
* rph
= web_contents()->GetRenderProcessHost();
322 instant_service
->SendSearchURLsToRenderer(rph
);
324 // Reload the contents to ensure that it gets assigned to a non-previledged
326 if (!instant_service
->IsInstantProcess(rph
->GetID()))
328 web_contents()->GetController().Reload(false);
330 // As the reload was not triggered by the user we don't want to close any
331 // infobars. We have to tell the InfoBarService after the reload, otherwise it
332 // would ignore this call when
333 // WebContentsObserver::DidStartNavigationToPendingEntry is invoked.
334 InfoBarService::FromWebContents(web_contents())->set_ignore_next_reload();
337 void TabAndroid::OnWebContentsInstantSupportDisabled(
338 const content::WebContents
* contents
) {
340 if (web_contents() != contents
)
343 JNIEnv
* env
= base::android::AttachCurrentThread();
344 Java_Tab_onWebContentsInstantSupportDisabled(env
,
345 weak_java_tab_
.get(env
).obj());
348 void TabAndroid::Observe(int type
,
349 const content::NotificationSource
& source
,
350 const content::NotificationDetails
& details
) {
351 JNIEnv
* env
= base::android::AttachCurrentThread();
353 case chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
: {
354 TabSpecificContentSettings
* settings
=
355 TabSpecificContentSettings::FromWebContents(web_contents());
356 if (!settings
->IsBlockageIndicated(CONTENT_SETTINGS_TYPE_POPUPS
)) {
357 // TODO(dfalcantara): Create an InfoBarDelegate to keep the
358 // PopupBlockedInfoBar logic native-side instead of straddling the JNI
361 PopupBlockerTabHelper
* popup_blocker_helper
=
362 PopupBlockerTabHelper::FromWebContents(web_contents());
363 if (popup_blocker_helper
)
364 num_popups
= popup_blocker_helper
->GetBlockedPopupsCount();
367 PopupBlockedInfoBarDelegate::Create(web_contents(), num_popups
);
369 settings
->SetBlockageHasBeenIndicated(CONTENT_SETTINGS_TYPE_POPUPS
);
373 case content::NOTIFICATION_NAV_ENTRY_CHANGED
:
374 Java_Tab_onNavEntryChanged(env
, weak_java_tab_
.get(env
).obj());
377 NOTREACHED() << "Unexpected notification " << type
;
382 void TabAndroid::OnFaviconAvailable(const gfx::Image
& image
) {
383 SkBitmap favicon
= image
.AsImageSkia().GetRepresentation(1.0f
).sk_bitmap();
387 JNIEnv
*env
= base::android::AttachCurrentThread();
388 Java_Tab_onFaviconAvailable(env
, weak_java_tab_
.get(env
).obj(),
389 gfx::ConvertToJavaBitmap(&favicon
).obj());
392 void TabAndroid::Destroy(JNIEnv
* env
, jobject obj
) {
396 void TabAndroid::InitWebContents(JNIEnv
* env
,
399 jobject jcontent_view_core
,
400 jobject jweb_contents_delegate
,
401 jobject jcontext_menu_populator
) {
402 content::ContentViewCore
* content_view_core
=
403 content::ContentViewCore::GetNativeContentViewCore(env
,
405 DCHECK(content_view_core
);
406 DCHECK(content_view_core
->GetWebContents());
408 web_contents_
.reset(content_view_core
->GetWebContents());
409 AttachTabHelpers(web_contents_
.get());
411 SetWindowSessionID(session_window_id_
.id());
413 session_tab_id_
.set_id(
414 SessionTabHelper::FromWebContents(web_contents())->session_id().id());
415 ContextMenuHelper::FromWebContents(web_contents())->SetPopulator(
416 jcontext_menu_populator
);
417 WindowAndroidHelper::FromWebContents(web_contents())->
418 SetWindowAndroid(content_view_core
->GetWindowAndroid());
419 CoreTabHelper::FromWebContents(web_contents())->set_delegate(this);
420 SearchTabHelper::FromWebContents(web_contents())->set_delegate(this);
421 web_contents_delegate_
.reset(
422 new chrome::android::ChromeWebContentsDelegateAndroid(
423 env
, jweb_contents_delegate
));
424 web_contents_delegate_
->LoadProgressChanged(web_contents(), 0);
425 web_contents()->SetDelegate(web_contents_delegate_
.get());
427 notification_registrar_
.Add(
429 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
,
430 content::Source
<content::WebContents
>(web_contents()));
431 notification_registrar_
.Add(
433 content::NOTIFICATION_NAV_ENTRY_CHANGED
,
434 content::Source
<content::NavigationController
>(
435 &web_contents()->GetController()));
437 FaviconTabHelper
* favicon_tab_helper
=
438 FaviconTabHelper::FromWebContents(web_contents_
.get());
440 if (favicon_tab_helper
)
441 favicon_tab_helper
->AddObserver(this);
443 synced_tab_delegate_
->SetWebContents(web_contents());
445 // Verify that the WebContents this tab represents matches the expected
446 // off the record state.
447 CHECK_EQ(GetProfile()->IsOffTheRecord(), incognito
);
449 InstantService
* instant_service
=
450 InstantServiceFactory::GetForProfile(GetProfile());
452 instant_service
->AddObserver(this);
455 void TabAndroid::DestroyWebContents(JNIEnv
* env
,
457 jboolean delete_native
) {
458 DCHECK(web_contents());
460 notification_registrar_
.Remove(
462 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
,
463 content::Source
<content::WebContents
>(web_contents()));
464 notification_registrar_
.Remove(
466 content::NOTIFICATION_NAV_ENTRY_CHANGED
,
467 content::Source
<content::NavigationController
>(
468 &web_contents()->GetController()));
470 FaviconTabHelper
* favicon_tab_helper
=
471 FaviconTabHelper::FromWebContents(web_contents_
.get());
473 if (favicon_tab_helper
)
474 favicon_tab_helper
->RemoveObserver(this);
476 InstantService
* instant_service
=
477 InstantServiceFactory::GetForProfile(GetProfile());
479 instant_service
->RemoveObserver(this);
481 web_contents()->SetDelegate(NULL
);
484 web_contents_
.reset();
485 synced_tab_delegate_
->ResetWebContents();
487 // Release the WebContents so it does not get deleted by the scoped_ptr.
488 ignore_result(web_contents_
.release());
492 base::android::ScopedJavaLocalRef
<jobject
> TabAndroid::GetProfileAndroid(
495 Profile
* profile
= GetProfile();
497 return base::android::ScopedJavaLocalRef
<jobject
>();
498 ProfileAndroid
* profile_android
= ProfileAndroid::FromProfile(profile
);
499 if (!profile_android
)
500 return base::android::ScopedJavaLocalRef
<jobject
>();
502 return profile_android
->GetJavaObject();
505 TabAndroid::TabLoadStatus
TabAndroid::LoadUrl(JNIEnv
* env
,
508 jstring j_extra_headers
,
509 jbyteArray j_post_data
,
510 jint page_transition
,
511 jstring j_referrer_url
,
512 jint referrer_policy
,
513 jboolean is_renderer_initiated
) {
515 return PAGE_LOAD_FAILED
;
517 GURL
gurl(base::android::ConvertJavaStringToUTF8(env
, url
));
519 return PAGE_LOAD_FAILED
;
521 // If the page was prerendered, use it.
522 // Note in incognito mode, we don't have a PrerenderManager.
524 prerender::PrerenderManager
* prerender_manager
=
525 prerender::PrerenderManagerFactory::GetForProfile(GetProfile());
526 if (prerender_manager
) {
527 bool prefetched_page_loaded
= HasPrerenderedUrl(gurl
);
528 // Getting the load status before MaybeUsePrerenderedPage() b/c it resets.
529 chrome::NavigateParams
params(NULL
, web_contents());
530 InstantSearchPrerenderer
* prerenderer
=
531 InstantSearchPrerenderer::GetForProfile(GetProfile());
533 const base::string16
& search_terms
=
534 chrome::ExtractSearchTermsFromURL(GetProfile(), gurl
);
535 if (!search_terms
.empty() &&
536 prerenderer
->CanCommitQuery(web_contents_
.get(), search_terms
)) {
537 EmbeddedSearchRequestParams
request_params(gurl
);
538 prerenderer
->Commit(search_terms
, request_params
);
540 if (prerenderer
->UsePrerenderedPage(gurl
, ¶ms
))
541 return FULL_PRERENDERED_PAGE_LOAD
;
543 prerenderer
->Cancel();
545 if (prerender_manager
->MaybeUsePrerenderedPage(gurl
, ¶ms
)) {
546 return prefetched_page_loaded
?
547 FULL_PRERENDERED_PAGE_LOAD
: PARTIAL_PRERENDERED_PAGE_LOAD
;
552 url_fixer::FixupURL(gurl
.possibly_invalid_spec(), std::string()));
553 if (!fixed_url
.is_valid())
554 return PAGE_LOAD_FAILED
;
556 if (!HandleNonNavigationAboutURL(fixed_url
)) {
557 // Notify the GoogleURLTracker of searches, it might want to change the
558 // actual Google site used (for instance when in the UK, google.co.uk, when
559 // in the US google.com).
560 // Note that this needs to happen before we initiate the navigation as the
561 // GoogleURLTracker uses the navigation pending notification to trigger the
563 if (google_util::IsGoogleSearchUrl(fixed_url
) &&
564 (page_transition
& ui::PAGE_TRANSITION_GENERATED
)) {
565 GoogleURLTracker
* tracker
=
566 GoogleURLTrackerFactory::GetForProfile(GetProfile());
568 tracker
->SearchCommitted();
571 // Record UMA "ShowHistory" here. That way it'll pick up both user
572 // typing chrome://history as well as selecting from the drop down menu.
573 if (fixed_url
.spec() == chrome::kChromeUIHistoryURL
) {
574 content::RecordAction(base::UserMetricsAction("ShowHistory"));
577 content::NavigationController::LoadURLParams
load_params(fixed_url
);
578 if (j_extra_headers
) {
579 load_params
.extra_headers
= base::android::ConvertJavaStringToUTF8(
584 load_params
.load_type
=
585 content::NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST
;
586 std::vector
<uint8
> post_data
;
587 base::android::JavaByteArrayToByteVector(env
, j_post_data
, &post_data
);
588 load_params
.browser_initiated_post_data
=
589 base::RefCountedBytes::TakeVector(&post_data
);
591 load_params
.transition_type
=
592 ui::PageTransitionFromInt(page_transition
);
593 if (j_referrer_url
) {
594 load_params
.referrer
= content::Referrer(
595 GURL(base::android::ConvertJavaStringToUTF8(env
, j_referrer_url
)),
596 static_cast<blink::WebReferrerPolicy
>(referrer_policy
));
598 const base::string16 search_terms
=
599 chrome::ExtractSearchTermsFromURL(GetProfile(), gurl
);
600 SearchTabHelper
* search_tab_helper
=
601 SearchTabHelper::FromWebContents(web_contents_
.get());
602 if (!search_terms
.empty() && search_tab_helper
&&
603 search_tab_helper
->SupportsInstant()) {
604 EmbeddedSearchRequestParams
request_params(gurl
);
605 search_tab_helper
->Submit(search_terms
, request_params
);
606 return DEFAULT_PAGE_LOAD
;
608 load_params
.is_renderer_initiated
= is_renderer_initiated
;
609 web_contents()->GetController().LoadURLWithParams(load_params
);
611 return DEFAULT_PAGE_LOAD
;
614 void TabAndroid::SetActiveNavigationEntryTitleForUrl(JNIEnv
* env
,
618 DCHECK(web_contents());
620 base::string16 title
;
622 title
= base::android::ConvertJavaStringToUTF16(env
, jtitle
);
626 url
= base::android::ConvertJavaStringToUTF8(env
, jurl
);
628 content::NavigationEntry
* entry
=
629 web_contents()->GetController().GetVisibleEntry();
630 if (entry
&& url
== entry
->GetVirtualURL().spec())
631 entry
->SetTitle(title
);
634 bool TabAndroid::Print(JNIEnv
* env
, jobject obj
) {
638 printing::PrintViewManagerBasic::CreateForWebContents(web_contents());
639 printing::PrintViewManagerBasic
* print_view_manager
=
640 printing::PrintViewManagerBasic::FromWebContents(web_contents());
641 if (print_view_manager
== NULL
)
644 print_view_manager
->PrintNow();
648 void TabAndroid::SetPendingPrint() {
649 JNIEnv
* env
= base::android::AttachCurrentThread();
650 Java_Tab_setPendingPrint(env
, weak_java_tab_
.get(env
).obj());
653 ScopedJavaLocalRef
<jobject
> TabAndroid::GetDefaultFavicon(JNIEnv
* env
,
655 ScopedJavaLocalRef
<jobject
> bitmap
;
656 FaviconTabHelper
* favicon_tab_helper
=
657 FaviconTabHelper::FromWebContents(web_contents_
.get());
659 if (!favicon_tab_helper
)
662 // Always return the default favicon in Android.
663 SkBitmap favicon
= favicon_tab_helper
->GetFavicon().AsBitmap();
664 if (!favicon
.empty()) {
665 gfx::DeviceDisplayInfo device_info
;
666 const float device_scale_factor
= device_info
.GetDIPScale();
667 int target_size_dip
= device_scale_factor
* gfx::kFaviconSize
;
668 if (favicon
.width() != target_size_dip
||
669 favicon
.height() != target_size_dip
) {
671 skia::ImageOperations::Resize(favicon
,
672 skia::ImageOperations::RESIZE_BEST
,
677 bitmap
= gfx::ConvertToJavaBitmap(&favicon
);
682 prerender::PrerenderManager
* TabAndroid::GetPrerenderManager() const {
683 Profile
* profile
= GetProfile();
686 return prerender::PrerenderManagerFactory::GetForProfile(profile
);
690 void TabAndroid::CreateHistoricalTabFromContents(WebContents
* web_contents
) {
691 DCHECK(web_contents
);
693 TabRestoreService
* service
=
694 TabRestoreServiceFactory::GetForProfile(
695 Profile::FromBrowserContext(web_contents
->GetBrowserContext()));
699 // Exclude internal pages from being marked as recent when they are closed.
700 const GURL
& tab_url
= web_contents
->GetURL();
701 if (tab_url
.SchemeIs(content::kChromeUIScheme
) ||
702 tab_url
.SchemeIs(chrome::kChromeNativeScheme
) ||
703 tab_url
.SchemeIs(url::kAboutScheme
)) {
707 // TODO(jcivelli): is the index important?
708 service
->CreateHistoricalTab(web_contents
, -1);
711 void TabAndroid::CreateHistoricalTab(JNIEnv
* env
, jobject obj
) {
712 TabAndroid::CreateHistoricalTabFromContents(web_contents());
715 static void Init(JNIEnv
* env
, jobject obj
) {
716 TRACE_EVENT0("native", "TabAndroid::Init");
717 // This will automatically bind to the Java object and pass ownership there.
718 new TabAndroid(env
, obj
);
722 bool TabAndroid::RegisterTabAndroid(JNIEnv
* env
) {
723 return RegisterNativesImpl(env
);