Implement window.print() on Android
[chromium-blink-merge.git] / chrome / browser / android / tab_android.cc
blobddc027b63fa4074d1ccbcd22ea89b545b02a354d
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;
69 namespace {
71 WebContents* CreateTargetContents(const chrome::NavigateParams& params,
72 const GURL& url) {
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) {
95 Profile* profile =
96 Profile::FromBrowserContext(params->target_contents->GetBrowserContext());
98 prerender::PrerenderManager* prerender_manager =
99 prerender::PrerenderManagerFactory::GetForProfile(profile);
100 if (!prerender_manager)
101 return false;
102 return prerender_manager->MaybeUsePrerenderedPage(url, params);
105 } // namespace
107 TabAndroid* TabAndroid::FromWebContents(content::WebContents* web_contents) {
108 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(web_contents);
109 if (!core_tab_helper)
110 return NULL;
112 CoreTabHelperDelegate* core_delegate = core_tab_helper->delegate();
113 if (!core_delegate)
114 return NULL;
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 {
173 if (!web_contents())
174 return NULL;
176 return content::ContentViewCore::FromWebContents(web_contents());
179 Profile* TabAndroid::GetProfile() const {
180 if (!web_contents())
181 return NULL;
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);
193 if (!web_contents())
194 return;
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(
219 load_url_params);
221 } else {
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(
226 load_url_params);
227 web_contents_delegate_->AddNewContents(params->source_contents,
228 params->target_contents,
229 params->disposition,
230 params->window_bounds,
231 params->user_gesture,
232 &was_blocked);
233 if (was_blocked)
234 params->target_contents = NULL;
240 bool TabAndroid::HasPrerenderedUrl(GURL gurl) {
241 prerender::PrerenderManager* prerender_manager = GetPrerenderManager();
242 if (!prerender_manager)
243 return false;
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()) {
253 return true;
256 return false;
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,
287 bool did_start_load,
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(
295 env,
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(
302 env,
303 weak_java_tab_.get(env).obj(),
304 reinterpret_cast<intptr_t>(new_contents),
305 did_start_load,
306 did_finish_load);
309 void TabAndroid::DefaultSearchProviderChanged() {
310 // TODO(kmadhusu): Move this function definition to a common place and update
311 // BrowserInstantController::DefaultSearchProviderChanged to use the same.
312 if (!web_contents())
313 return;
315 InstantService* instant_service =
316 InstantServiceFactory::GetForProfile(GetProfile());
317 if (!instant_service)
318 return;
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
325 // renderer.
326 if (!instant_service->IsInstantProcess(rph->GetID()))
327 return;
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) {
339 DCHECK(contents);
340 if (web_contents() != contents)
341 return;
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();
352 switch (type) {
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
359 // boundary.
360 int num_popups = 0;
361 PopupBlockerTabHelper* popup_blocker_helper =
362 PopupBlockerTabHelper::FromWebContents(web_contents());
363 if (popup_blocker_helper)
364 num_popups = popup_blocker_helper->GetBlockedPopupsCount();
366 if (num_popups > 0)
367 PopupBlockedInfoBarDelegate::Create(web_contents(), num_popups);
369 settings->SetBlockageHasBeenIndicated(CONTENT_SETTINGS_TYPE_POPUPS);
371 break;
373 case content::NOTIFICATION_NAV_ENTRY_CHANGED:
374 Java_Tab_onNavEntryChanged(env, weak_java_tab_.get(env).obj());
375 break;
376 default:
377 NOTREACHED() << "Unexpected notification " << type;
378 break;
382 void TabAndroid::OnFaviconAvailable(const gfx::Image& image) {
383 SkBitmap favicon = image.AsImageSkia().GetRepresentation(1.0f).sk_bitmap();
384 if (favicon.empty())
385 return;
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) {
393 delete this;
396 void TabAndroid::InitWebContents(JNIEnv* env,
397 jobject obj,
398 jboolean incognito,
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,
404 jcontent_view_core);
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(
428 this,
429 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
430 content::Source<content::WebContents>(web_contents()));
431 notification_registrar_.Add(
432 this,
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());
451 if (instant_service)
452 instant_service->AddObserver(this);
455 void TabAndroid::DestroyWebContents(JNIEnv* env,
456 jobject obj,
457 jboolean delete_native) {
458 DCHECK(web_contents());
460 notification_registrar_.Remove(
461 this,
462 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
463 content::Source<content::WebContents>(web_contents()));
464 notification_registrar_.Remove(
465 this,
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());
478 if (instant_service)
479 instant_service->RemoveObserver(this);
481 web_contents()->SetDelegate(NULL);
483 if (delete_native) {
484 web_contents_.reset();
485 synced_tab_delegate_->ResetWebContents();
486 } else {
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(
493 JNIEnv* env,
494 jobject obj) {
495 Profile* profile = GetProfile();
496 if (!profile)
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,
506 jobject obj,
507 jstring url,
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) {
514 if (!web_contents())
515 return PAGE_LOAD_FAILED;
517 GURL gurl(base::android::ConvertJavaStringToUTF8(env, url));
518 if (gurl.is_empty())
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());
532 if (prerenderer) {
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, &params))
541 return FULL_PRERENDERED_PAGE_LOAD;
543 prerenderer->Cancel();
545 if (prerender_manager->MaybeUsePrerenderedPage(gurl, &params)) {
546 return prefetched_page_loaded ?
547 FULL_PRERENDERED_PAGE_LOAD : PARTIAL_PRERENDERED_PAGE_LOAD;
551 GURL fixed_url(
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
562 // infobar.
563 if (google_util::IsGoogleSearchUrl(fixed_url) &&
564 (page_transition & ui::PAGE_TRANSITION_GENERATED)) {
565 GoogleURLTracker* tracker =
566 GoogleURLTrackerFactory::GetForProfile(GetProfile());
567 if (tracker)
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(
580 env,
581 j_extra_headers);
583 if (j_post_data) {
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,
615 jobject obj,
616 jstring jurl,
617 jstring jtitle) {
618 DCHECK(web_contents());
620 base::string16 title;
621 if (jtitle)
622 title = base::android::ConvertJavaStringToUTF16(env, jtitle);
624 std::string url;
625 if (jurl)
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) {
635 if (!web_contents())
636 return false;
638 printing::PrintViewManagerBasic::CreateForWebContents(web_contents());
639 printing::PrintViewManagerBasic* print_view_manager =
640 printing::PrintViewManagerBasic::FromWebContents(web_contents());
641 if (print_view_manager == NULL)
642 return false;
644 print_view_manager->PrintNow();
645 return true;
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,
654 jobject obj) {
655 ScopedJavaLocalRef<jobject> bitmap;
656 FaviconTabHelper* favicon_tab_helper =
657 FaviconTabHelper::FromWebContents(web_contents_.get());
659 if (!favicon_tab_helper)
660 return bitmap;
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) {
670 favicon =
671 skia::ImageOperations::Resize(favicon,
672 skia::ImageOperations::RESIZE_BEST,
673 target_size_dip,
674 target_size_dip);
677 bitmap = gfx::ConvertToJavaBitmap(&favicon);
679 return bitmap;
682 prerender::PrerenderManager* TabAndroid::GetPrerenderManager() const {
683 Profile* profile = GetProfile();
684 if (!profile)
685 return NULL;
686 return prerender::PrerenderManagerFactory::GetForProfile(profile);
689 // static
690 void TabAndroid::CreateHistoricalTabFromContents(WebContents* web_contents) {
691 DCHECK(web_contents);
693 TabRestoreService* service =
694 TabRestoreServiceFactory::GetForProfile(
695 Profile::FromBrowserContext(web_contents->GetBrowserContext()));
696 if (!service)
697 return;
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)) {
704 return;
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);
721 // static
722 bool TabAndroid::RegisterTabAndroid(JNIEnv* env) {
723 return RegisterNativesImpl(env);