Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / android / tab_android.cc
blob9bafe7746a5c25e51b2f278e2e5c870b152e2941
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/search.h"
25 #include "chrome/browser/sessions/session_tab_helper.h"
26 #include "chrome/browser/sync/glue/synced_tab_delegate_android.h"
27 #include "chrome/browser/tab_contents/tab_util.h"
28 #include "chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.h"
29 #include "chrome/browser/ui/android/context_menu_helper.h"
30 #include "chrome/browser/ui/android/infobars/infobar_container_android.h"
31 #include "chrome/browser/ui/android/tab_model/tab_model.h"
32 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
33 #include "chrome/browser/ui/android/window_android_helper.h"
34 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
35 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
36 #include "chrome/browser/ui/search/search_tab_helper.h"
37 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
38 #include "chrome/browser/ui/tab_helpers.h"
39 #include "chrome/common/url_constants.h"
40 #include "components/google/core/browser/google_url_tracker.h"
41 #include "components/google/core/browser/google_util.h"
42 #include "components/infobars/core/infobar_container.h"
43 #include "components/url_fixer/url_fixer.h"
44 #include "content/public/browser/android/content_view_core.h"
45 #include "content/public/browser/navigation_entry.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/user_metrics.h"
48 #include "content/public/browser/web_contents.h"
49 #include "jni/Tab_jni.h"
50 #include "skia/ext/image_operations.h"
51 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
52 #include "ui/base/resource/resource_bundle.h"
53 #include "ui/base/window_open_disposition.h"
54 #include "ui/gfx/android/device_display_info.h"
55 #include "ui/gfx/android/java_bitmap.h"
56 #include "ui/gfx/favicon_size.h"
57 #include "ui/gfx/image/image_skia.h"
59 using content::GlobalRequestID;
60 using content::NavigationController;
61 using content::WebContents;
63 namespace {
65 WebContents* CreateTargetContents(const chrome::NavigateParams& params,
66 const GURL& url) {
67 Profile* profile = params.initiating_profile;
69 if (profile->IsOffTheRecord() || params.disposition == OFF_THE_RECORD) {
70 profile = profile->GetOffTheRecordProfile();
72 WebContents::CreateParams create_params(
73 profile, tab_util::GetSiteInstanceForNewTab(profile, url));
74 if (params.source_contents) {
75 create_params.initial_size =
76 params.source_contents->GetContainerBounds().size();
77 if (params.should_set_opener)
78 create_params.opener = params.source_contents;
80 if (params.disposition == NEW_BACKGROUND_TAB)
81 create_params.initially_hidden = true;
83 WebContents* target_contents = WebContents::Create(create_params);
85 return target_contents;
88 bool MaybeSwapWithPrerender(const GURL& url, chrome::NavigateParams* params) {
89 Profile* profile =
90 Profile::FromBrowserContext(params->target_contents->GetBrowserContext());
92 prerender::PrerenderManager* prerender_manager =
93 prerender::PrerenderManagerFactory::GetForProfile(profile);
94 if (!prerender_manager)
95 return false;
96 return prerender_manager->MaybeUsePrerenderedPage(url, params);
99 } // namespace
101 TabAndroid* TabAndroid::FromWebContents(content::WebContents* web_contents) {
102 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(web_contents);
103 if (!core_tab_helper)
104 return NULL;
106 CoreTabHelperDelegate* core_delegate = core_tab_helper->delegate();
107 if (!core_delegate)
108 return NULL;
110 return static_cast<TabAndroid*>(core_delegate);
113 TabAndroid* TabAndroid::GetNativeTab(JNIEnv* env, jobject obj) {
114 return reinterpret_cast<TabAndroid*>(Java_Tab_getNativePtr(env, obj));
117 void TabAndroid::AttachTabHelpers(content::WebContents* web_contents) {
118 DCHECK(web_contents);
120 TabHelpers::AttachTabHelpers(web_contents);
123 TabAndroid::TabAndroid(JNIEnv* env, jobject obj)
124 : weak_java_tab_(env, obj),
125 synced_tab_delegate_(new browser_sync::SyncedTabDelegateAndroid(this)) {
126 Java_Tab_setNativePtr(env, obj, reinterpret_cast<intptr_t>(this));
129 TabAndroid::~TabAndroid() {
130 JNIEnv* env = base::android::AttachCurrentThread();
131 Java_Tab_clearNativePtr(env, weak_java_tab_.get(env).obj());
134 base::android::ScopedJavaLocalRef<jobject> TabAndroid::GetJavaObject() {
135 JNIEnv* env = base::android::AttachCurrentThread();
136 return weak_java_tab_.get(env);
139 int TabAndroid::GetAndroidId() const {
140 JNIEnv* env = base::android::AttachCurrentThread();
141 return Java_Tab_getId(env, weak_java_tab_.get(env).obj());
144 int TabAndroid::GetSyncId() const {
145 JNIEnv* env = base::android::AttachCurrentThread();
146 return Java_Tab_getSyncId(env, weak_java_tab_.get(env).obj());
149 base::string16 TabAndroid::GetTitle() const {
150 JNIEnv* env = base::android::AttachCurrentThread();
151 return base::android::ConvertJavaStringToUTF16(
152 Java_Tab_getTitle(env, weak_java_tab_.get(env).obj()));
155 GURL TabAndroid::GetURL() const {
156 JNIEnv* env = base::android::AttachCurrentThread();
157 return GURL(base::android::ConvertJavaStringToUTF8(
158 Java_Tab_getUrl(env, weak_java_tab_.get(env).obj())));
161 bool TabAndroid::LoadIfNeeded() {
162 JNIEnv* env = base::android::AttachCurrentThread();
163 return Java_Tab_loadIfNeeded(env, weak_java_tab_.get(env).obj());
166 content::ContentViewCore* TabAndroid::GetContentViewCore() const {
167 if (!web_contents())
168 return NULL;
170 return content::ContentViewCore::FromWebContents(web_contents());
173 Profile* TabAndroid::GetProfile() const {
174 if (!web_contents())
175 return NULL;
177 return Profile::FromBrowserContext(web_contents()->GetBrowserContext());
180 browser_sync::SyncedTabDelegate* TabAndroid::GetSyncedTabDelegate() const {
181 return synced_tab_delegate_.get();
184 void TabAndroid::SetWindowSessionID(SessionID::id_type window_id) {
185 session_window_id_.set_id(window_id);
187 if (!web_contents())
188 return;
190 SessionTabHelper* session_tab_helper =
191 SessionTabHelper::FromWebContents(web_contents());
192 session_tab_helper->SetWindowID(session_window_id_);
195 void TabAndroid::SetSyncId(int sync_id) {
196 JNIEnv* env = base::android::AttachCurrentThread();
197 Java_Tab_setSyncId(env, weak_java_tab_.get(env).obj(), sync_id);
200 void TabAndroid::HandlePopupNavigation(chrome::NavigateParams* params) {
201 if (params->disposition != SUPPRESS_OPEN &&
202 params->disposition != SAVE_TO_DISK &&
203 params->disposition != IGNORE_ACTION) {
204 if (!params->url.is_empty()) {
205 bool was_blocked = false;
206 GURL url(params->url);
207 if (params->disposition == CURRENT_TAB) {
208 params->target_contents = web_contents_.get();
209 if (!MaybeSwapWithPrerender(url, params)) {
210 NavigationController::LoadURLParams load_url_params(url);
211 MakeLoadURLParams(params, &load_url_params);
212 params->target_contents->GetController().LoadURLWithParams(
213 load_url_params);
215 } else {
216 params->target_contents = CreateTargetContents(*params, url);
217 NavigationController::LoadURLParams load_url_params(url);
218 MakeLoadURLParams(params, &load_url_params);
219 params->target_contents->GetController().LoadURLWithParams(
220 load_url_params);
221 web_contents_delegate_->AddNewContents(params->source_contents,
222 params->target_contents,
223 params->disposition,
224 params->window_bounds,
225 params->user_gesture,
226 &was_blocked);
227 if (was_blocked)
228 params->target_contents = NULL;
234 bool TabAndroid::HasPrerenderedUrl(GURL gurl) {
235 prerender::PrerenderManager* prerender_manager = GetPrerenderManager();
236 if (!prerender_manager)
237 return false;
239 std::vector<content::WebContents*> contents =
240 prerender_manager->GetAllPrerenderingContents();
241 prerender::PrerenderContents* prerender_contents;
242 for (size_t i = 0; i < contents.size(); ++i) {
243 prerender_contents = prerender_manager->
244 GetPrerenderContents(contents.at(i));
245 if (prerender_contents->prerender_url() == gurl &&
246 prerender_contents->has_finished_loading()) {
247 return true;
250 return false;
253 void TabAndroid::MakeLoadURLParams(
254 chrome::NavigateParams* params,
255 NavigationController::LoadURLParams* load_url_params) {
256 load_url_params->referrer = params->referrer;
257 load_url_params->frame_tree_node_id = params->frame_tree_node_id;
258 load_url_params->redirect_chain = params->redirect_chain;
259 load_url_params->transition_type = params->transition;
260 load_url_params->extra_headers = params->extra_headers;
261 load_url_params->should_replace_current_entry =
262 params->should_replace_current_entry;
264 if (params->transferred_global_request_id != GlobalRequestID()) {
265 load_url_params->transferred_global_request_id =
266 params->transferred_global_request_id;
268 load_url_params->is_renderer_initiated = params->is_renderer_initiated;
270 // Only allows the browser-initiated navigation to use POST.
271 if (params->uses_post && !params->is_renderer_initiated) {
272 load_url_params->load_type =
273 NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST;
274 load_url_params->browser_initiated_post_data =
275 params->browser_initiated_post_data;
279 void TabAndroid::SwapTabContents(content::WebContents* old_contents,
280 content::WebContents* new_contents,
281 bool did_start_load,
282 bool did_finish_load) {
283 JNIEnv* env = base::android::AttachCurrentThread();
285 // We need to notify the native InfobarContainer so infobars can be swapped.
286 InfoBarContainerAndroid* infobar_container =
287 reinterpret_cast<InfoBarContainerAndroid*>(
288 Java_Tab_getNativeInfoBarContainer(
289 env,
290 weak_java_tab_.get(env).obj()));
291 InfoBarService* new_infobar_service =
292 new_contents ? InfoBarService::FromWebContents(new_contents) : NULL;
293 infobar_container->ChangeInfoBarManager(new_infobar_service);
295 Java_Tab_swapWebContents(
296 env,
297 weak_java_tab_.get(env).obj(),
298 reinterpret_cast<intptr_t>(new_contents),
299 did_start_load,
300 did_finish_load);
303 void TabAndroid::OnWebContentsInstantSupportDisabled(
304 const content::WebContents* contents) {
305 DCHECK(contents);
306 if (web_contents() != contents)
307 return;
309 JNIEnv* env = base::android::AttachCurrentThread();
310 Java_Tab_onWebContentsInstantSupportDisabled(env,
311 weak_java_tab_.get(env).obj());
314 void TabAndroid::Observe(int type,
315 const content::NotificationSource& source,
316 const content::NotificationDetails& details) {
317 JNIEnv* env = base::android::AttachCurrentThread();
318 switch (type) {
319 case chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED: {
320 TabSpecificContentSettings* settings =
321 TabSpecificContentSettings::FromWebContents(web_contents());
322 if (!settings->IsBlockageIndicated(CONTENT_SETTINGS_TYPE_POPUPS)) {
323 // TODO(dfalcantara): Create an InfoBarDelegate to keep the
324 // PopupBlockedInfoBar logic native-side instead of straddling the JNI
325 // boundary.
326 int num_popups = 0;
327 PopupBlockerTabHelper* popup_blocker_helper =
328 PopupBlockerTabHelper::FromWebContents(web_contents());
329 if (popup_blocker_helper)
330 num_popups = popup_blocker_helper->GetBlockedPopupsCount();
332 if (num_popups > 0)
333 PopupBlockedInfoBarDelegate::Create(web_contents(), num_popups);
335 settings->SetBlockageHasBeenIndicated(CONTENT_SETTINGS_TYPE_POPUPS);
337 break;
339 case chrome::NOTIFICATION_FAVICON_UPDATED:
340 Java_Tab_onFaviconUpdated(env, weak_java_tab_.get(env).obj());
341 break;
342 case content::NOTIFICATION_NAV_ENTRY_CHANGED:
343 Java_Tab_onNavEntryChanged(env, weak_java_tab_.get(env).obj());
344 break;
345 default:
346 NOTREACHED() << "Unexpected notification " << type;
347 break;
351 void TabAndroid::Destroy(JNIEnv* env, jobject obj) {
352 delete this;
355 void TabAndroid::InitWebContents(JNIEnv* env,
356 jobject obj,
357 jboolean incognito,
358 jobject jcontent_view_core,
359 jobject jweb_contents_delegate,
360 jobject jcontext_menu_populator) {
361 content::ContentViewCore* content_view_core =
362 content::ContentViewCore::GetNativeContentViewCore(env,
363 jcontent_view_core);
364 DCHECK(content_view_core);
365 DCHECK(content_view_core->GetWebContents());
367 web_contents_.reset(content_view_core->GetWebContents());
368 AttachTabHelpers(web_contents_.get());
370 SetWindowSessionID(session_window_id_.id());
372 session_tab_id_.set_id(
373 SessionTabHelper::FromWebContents(web_contents())->session_id().id());
374 ContextMenuHelper::FromWebContents(web_contents())->SetPopulator(
375 jcontext_menu_populator);
376 WindowAndroidHelper::FromWebContents(web_contents())->
377 SetWindowAndroid(content_view_core->GetWindowAndroid());
378 CoreTabHelper::FromWebContents(web_contents())->set_delegate(this);
379 SearchTabHelper::FromWebContents(web_contents())->set_delegate(this);
380 web_contents_delegate_.reset(
381 new chrome::android::ChromeWebContentsDelegateAndroid(
382 env, jweb_contents_delegate));
383 web_contents_delegate_->LoadProgressChanged(web_contents(), 0);
384 web_contents()->SetDelegate(web_contents_delegate_.get());
386 notification_registrar_.Add(
387 this,
388 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
389 content::Source<content::WebContents>(web_contents()));
390 notification_registrar_.Add(
391 this,
392 chrome::NOTIFICATION_FAVICON_UPDATED,
393 content::Source<content::WebContents>(web_contents()));
394 notification_registrar_.Add(
395 this,
396 content::NOTIFICATION_NAV_ENTRY_CHANGED,
397 content::Source<content::NavigationController>(
398 &web_contents()->GetController()));
400 synced_tab_delegate_->SetWebContents(web_contents());
402 // Verify that the WebContents this tab represents matches the expected
403 // off the record state.
404 CHECK_EQ(GetProfile()->IsOffTheRecord(), incognito);
407 void TabAndroid::DestroyWebContents(JNIEnv* env,
408 jobject obj,
409 jboolean delete_native) {
410 DCHECK(web_contents());
412 notification_registrar_.Remove(
413 this,
414 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
415 content::Source<content::WebContents>(web_contents()));
416 notification_registrar_.Remove(
417 this,
418 chrome::NOTIFICATION_FAVICON_UPDATED,
419 content::Source<content::WebContents>(web_contents()));
420 notification_registrar_.Remove(
421 this,
422 content::NOTIFICATION_NAV_ENTRY_CHANGED,
423 content::Source<content::NavigationController>(
424 &web_contents()->GetController()));
426 web_contents()->SetDelegate(NULL);
428 if (delete_native) {
429 web_contents_.reset();
430 synced_tab_delegate_->ResetWebContents();
431 } else {
432 // Release the WebContents so it does not get deleted by the scoped_ptr.
433 ignore_result(web_contents_.release());
437 base::android::ScopedJavaLocalRef<jobject> TabAndroid::GetProfileAndroid(
438 JNIEnv* env,
439 jobject obj) {
440 Profile* profile = GetProfile();
441 if (!profile)
442 return base::android::ScopedJavaLocalRef<jobject>();
443 ProfileAndroid* profile_android = ProfileAndroid::FromProfile(profile);
444 if (!profile_android)
445 return base::android::ScopedJavaLocalRef<jobject>();
447 return profile_android->GetJavaObject();
450 TabAndroid::TabLoadStatus TabAndroid::LoadUrl(JNIEnv* env,
451 jobject obj,
452 jstring url,
453 jstring j_extra_headers,
454 jbyteArray j_post_data,
455 jint page_transition,
456 jstring j_referrer_url,
457 jint referrer_policy,
458 jboolean is_renderer_initiated) {
459 if (!web_contents())
460 return PAGE_LOAD_FAILED;
462 GURL gurl(base::android::ConvertJavaStringToUTF8(env, url));
463 if (gurl.is_empty())
464 return PAGE_LOAD_FAILED;
466 // If the page was prerendered, use it.
467 // Note in incognito mode, we don't have a PrerenderManager.
469 prerender::PrerenderManager* prerender_manager =
470 prerender::PrerenderManagerFactory::GetForProfile(GetProfile());
471 if (prerender_manager) {
472 bool prefetched_page_loaded = HasPrerenderedUrl(gurl);
473 // Getting the load status before MaybeUsePrerenderedPage() b/c it resets.
474 chrome::NavigateParams params(NULL, web_contents());
475 InstantSearchPrerenderer* prerenderer =
476 InstantSearchPrerenderer::GetForProfile(GetProfile());
477 if (prerenderer) {
478 const base::string16& search_terms =
479 chrome::ExtractSearchTermsFromURL(GetProfile(), gurl);
480 if (!search_terms.empty() &&
481 prerenderer->CanCommitQuery(web_contents_.get(), search_terms)) {
482 prerenderer->Commit(search_terms);
484 if (prerenderer->UsePrerenderedPage(gurl, &params))
485 return FULL_PRERENDERED_PAGE_LOAD;
487 prerenderer->Cancel();
489 if (prerender_manager->MaybeUsePrerenderedPage(gurl, &params)) {
490 return prefetched_page_loaded ?
491 FULL_PRERENDERED_PAGE_LOAD : PARTIAL_PRERENDERED_PAGE_LOAD;
495 GURL fixed_url(
496 url_fixer::FixupURL(gurl.possibly_invalid_spec(), std::string()));
497 if (!fixed_url.is_valid())
498 return PAGE_LOAD_FAILED;
500 if (!HandleNonNavigationAboutURL(fixed_url)) {
501 // Notify the GoogleURLTracker of searches, it might want to change the
502 // actual Google site used (for instance when in the UK, google.co.uk, when
503 // in the US google.com).
504 // Note that this needs to happen before we initiate the navigation as the
505 // GoogleURLTracker uses the navigation pending notification to trigger the
506 // infobar.
507 if (google_util::IsGoogleSearchUrl(fixed_url) &&
508 (page_transition & ui::PAGE_TRANSITION_GENERATED)) {
509 GoogleURLTracker* tracker =
510 GoogleURLTrackerFactory::GetForProfile(GetProfile());
511 if (tracker)
512 tracker->SearchCommitted();
515 // Record UMA "ShowHistory" here. That way it'll pick up both user
516 // typing chrome://history as well as selecting from the drop down menu.
517 if (fixed_url.spec() == chrome::kChromeUIHistoryURL) {
518 content::RecordAction(base::UserMetricsAction("ShowHistory"));
521 content::NavigationController::LoadURLParams load_params(fixed_url);
522 if (j_extra_headers) {
523 load_params.extra_headers = base::android::ConvertJavaStringToUTF8(
524 env,
525 j_extra_headers);
527 if (j_post_data) {
528 load_params.load_type =
529 content::NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST;
530 std::vector<uint8> post_data;
531 base::android::JavaByteArrayToByteVector(env, j_post_data, &post_data);
532 load_params.browser_initiated_post_data =
533 base::RefCountedBytes::TakeVector(&post_data);
535 load_params.transition_type =
536 ui::PageTransitionFromInt(page_transition);
537 if (j_referrer_url) {
538 load_params.referrer = content::Referrer(
539 GURL(base::android::ConvertJavaStringToUTF8(env, j_referrer_url)),
540 static_cast<blink::WebReferrerPolicy>(referrer_policy));
542 const base::string16 search_terms =
543 chrome::ExtractSearchTermsFromURL(GetProfile(), gurl);
544 SearchTabHelper* search_tab_helper =
545 SearchTabHelper::FromWebContents(web_contents_.get());
546 if (!search_terms.empty() && search_tab_helper &&
547 search_tab_helper->SupportsInstant()) {
548 search_tab_helper->Submit(search_terms);
549 return DEFAULT_PAGE_LOAD;
551 load_params.is_renderer_initiated = is_renderer_initiated;
552 web_contents()->GetController().LoadURLWithParams(load_params);
554 return DEFAULT_PAGE_LOAD;
557 void TabAndroid::SetActiveNavigationEntryTitleForUrl(JNIEnv* env,
558 jobject obj,
559 jstring jurl,
560 jstring jtitle) {
561 DCHECK(web_contents());
563 base::string16 title;
564 if (jtitle)
565 title = base::android::ConvertJavaStringToUTF16(env, jtitle);
567 std::string url;
568 if (jurl)
569 url = base::android::ConvertJavaStringToUTF8(env, jurl);
571 content::NavigationEntry* entry =
572 web_contents()->GetController().GetVisibleEntry();
573 if (entry && url == entry->GetVirtualURL().spec())
574 entry->SetTitle(title);
577 bool TabAndroid::Print(JNIEnv* env, jobject obj) {
578 if (!web_contents())
579 return false;
581 printing::PrintViewManagerBasic::CreateForWebContents(web_contents());
582 printing::PrintViewManagerBasic* print_view_manager =
583 printing::PrintViewManagerBasic::FromWebContents(web_contents());
584 if (print_view_manager == NULL)
585 return false;
587 print_view_manager->PrintNow();
588 return true;
591 ScopedJavaLocalRef<jobject> TabAndroid::GetFavicon(JNIEnv* env, jobject obj) {
592 ScopedJavaLocalRef<jobject> bitmap;
593 FaviconTabHelper* favicon_tab_helper =
594 FaviconTabHelper::FromWebContents(web_contents_.get());
596 if (!favicon_tab_helper)
597 return bitmap;
599 // If the favicon isn't valid, it will return a default bitmap.
601 SkBitmap favicon =
602 favicon_tab_helper->GetFavicon()
603 .AsImageSkia()
604 .GetRepresentation(
605 ResourceBundle::GetSharedInstance().GetMaxScaleFactor())
606 .sk_bitmap();
608 if (favicon.empty()) {
609 favicon = favicon_tab_helper->GetFavicon().AsBitmap();
612 if (!favicon.empty()) {
613 gfx::DeviceDisplayInfo device_info;
614 const float device_scale_factor = device_info.GetDIPScale();
615 int target_size_dip = device_scale_factor * gfx::kFaviconSize;
616 if (favicon.width() != target_size_dip ||
617 favicon.height() != target_size_dip) {
618 favicon =
619 skia::ImageOperations::Resize(favicon,
620 skia::ImageOperations::RESIZE_BEST,
621 target_size_dip,
622 target_size_dip);
625 bitmap = gfx::ConvertToJavaBitmap(&favicon);
627 return bitmap;
630 jboolean TabAndroid::IsFaviconValid(JNIEnv* env, jobject jobj) {
631 return web_contents() &&
632 FaviconTabHelper::FromWebContents(web_contents())->FaviconIsValid();
635 prerender::PrerenderManager* TabAndroid::GetPrerenderManager() const {
636 Profile* profile = GetProfile();
637 if (!profile)
638 return NULL;
639 return prerender::PrerenderManagerFactory::GetForProfile(profile);
642 static void Init(JNIEnv* env, jobject obj) {
643 TRACE_EVENT0("native", "TabAndroid::Init");
644 // This will automatically bind to the Java object and pass ownership there.
645 new TabAndroid(env, obj);
648 bool TabAndroid::RegisterTabAndroid(JNIEnv* env) {
649 return RegisterNativesImpl(env);