Home | History | Annotate | Download | only in tab_model
      1 // Copyright 2014 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 "chrome/browser/ui/android/tab_model/tab_model_base.h"
      6 
      7 #include "base/android/jni_android.h"
      8 #include "base/android/jni_string.h"
      9 #include "base/android/jni_weak_ref.h"
     10 #include "base/metrics/histogram.h"
     11 #include "base/time/time.h"
     12 #include "chrome/browser/android/tab_android.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/profiles/profile_android.h"
     16 #include "chrome/browser/profiles/profile_manager.h"
     17 #include "chrome/browser/ui/android/tab_model/tab_model.h"
     18 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
     19 #include "chrome/browser/ui/toolbar/toolbar_model.h"
     20 #include "content/public/browser/web_contents.h"
     21 #include "jni/TabModelBase_jni.h"
     22 
     23 using base::android::AttachCurrentThread;
     24 using base::android::CheckException;
     25 using base::android::ConvertUTF8ToJavaString;
     26 using base::android::ConvertUTF16ToJavaString;
     27 using base::android::ScopedJavaLocalRef;
     28 
     29 TabModelBase::TabModelBase(JNIEnv* env, jobject obj, Profile* profile)
     30     : TabModel(profile),
     31       java_object_(env, env->NewWeakGlobalRef(obj)) {
     32 }
     33 
     34 void TabModelBase::Destroy(JNIEnv* env, jobject obj) {
     35   TabModelList::RemoveTabModel(this);
     36   delete this;
     37 }
     38 
     39 ScopedJavaLocalRef<jobject> TabModelBase::GetProfileAndroid(JNIEnv* env,
     40                                                             jobject obj) {
     41   ProfileAndroid* profile_android = ProfileAndroid::FromProfile(GetProfile());
     42   if (!profile_android)
     43     return ScopedJavaLocalRef<jobject>();
     44 
     45   return profile_android->GetJavaObject();
     46 }
     47 
     48 void TabModelBase::TabAddedToModel(JNIEnv* env, jobject obj, jobject jtab) {
     49   TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
     50 
     51   // Tab#initialize() should have been called by now otherwise we can't push
     52   // the window id.
     53   DCHECK(tab);
     54 
     55   tab->SetWindowSessionID(GetSessionId());
     56 }
     57 
     58 int TabModelBase::GetTabCount() const {
     59   JNIEnv* env = AttachCurrentThread();
     60   jint count = Java_TabModelBase_getCount(
     61       env, java_object_.get(env).obj());
     62   return count;
     63 }
     64 
     65 int TabModelBase::GetActiveIndex() const {
     66   JNIEnv* env = AttachCurrentThread();
     67   jint index = Java_TabModelBase_index(
     68       env, java_object_.get(env).obj());
     69   return index;
     70 }
     71 
     72 content::WebContents* TabModelBase::GetWebContentsAt(
     73     int index) const {
     74   TabAndroid* tab = GetTabAt(index);
     75   return tab == NULL ? NULL : tab->web_contents();
     76 }
     77 
     78 TabAndroid* TabModelBase::GetTabAt(int index) const {
     79   JNIEnv* env = AttachCurrentThread();
     80   ScopedJavaLocalRef<jobject> jtab =
     81       Java_TabModelBase_getTabAt(env,
     82                                  java_object_.get(env).obj(),
     83                                  index);
     84   DCHECK(!jtab.is_null());
     85 
     86   return TabAndroid::GetNativeTab(env, jtab.obj());
     87 }
     88 
     89 void TabModelBase::SetActiveIndex(int index) {
     90   JNIEnv* env = AttachCurrentThread();
     91   Java_TabModelBase_setIndex(
     92       env,
     93       java_object_.get(env).obj(),
     94       index);
     95 }
     96 
     97 void TabModelBase::CloseTabAt(int index) {
     98   JNIEnv* env = AttachCurrentThread();
     99   ScopedJavaLocalRef<jobject> jtab =
    100       Java_TabModelBase_getTabAt(env,
    101                                  java_object_.get(env).obj(),
    102                                  index);
    103   if (!jtab.is_null()) {
    104     Java_TabModelBase_closeTab(env,
    105                                java_object_.get(env).obj(),
    106                                jtab.obj());
    107   }
    108 }
    109 
    110 void TabModelBase::CreateTab(content::WebContents* web_contents,
    111                              int parent_tab_id) {
    112   JNIEnv* env = AttachCurrentThread();
    113   Java_TabModelBase_createTabWithNativeContents(
    114       env, java_object_.get(env).obj(),
    115       web_contents->GetBrowserContext()->IsOffTheRecord(),
    116       reinterpret_cast<intptr_t>(web_contents), parent_tab_id);
    117 }
    118 
    119 content::WebContents* TabModelBase::CreateNewTabForDevTools(const GURL& url) {
    120   JNIEnv* env = AttachCurrentThread();
    121   ScopedJavaLocalRef<jstring> jurl = ConvertUTF8ToJavaString(env, url.spec());
    122   ScopedJavaLocalRef<jobject> obj =
    123       Java_TabModelBase_createNewTabForDevTools(
    124           env,
    125           java_object_.get(env).obj(),
    126           jurl.obj());
    127   if (obj.is_null()) {
    128     VLOG(0) << "Failed to create java tab";
    129     return NULL;
    130   }
    131   TabAndroid* tab = TabAndroid::GetNativeTab(env, obj.obj());
    132   if (!tab) {
    133     VLOG(0) << "Failed to create java tab";
    134     return NULL;
    135   }
    136   return tab->web_contents();
    137 }
    138 
    139 bool TabModelBase::IsSessionRestoreInProgress() const {
    140   JNIEnv* env = AttachCurrentThread();
    141   return Java_TabModelBase_isSessionRestoreInProgress(
    142       env, java_object_.get(env).obj());
    143 }
    144 
    145 void TabModelBase::BroadcastSessionRestoreComplete(JNIEnv* env,
    146                                                    jobject obj) {
    147   TabModel::BroadcastSessionRestoreComplete();
    148 }
    149 
    150 TabModelBase::~TabModelBase() {
    151 }
    152 
    153 namespace {
    154 
    155 static Profile* FindProfile(jboolean is_incognito) {
    156   if (g_browser_process == NULL ||
    157       g_browser_process->profile_manager() == NULL) {
    158     LOG(ERROR) << "Browser process or profile manager not initialized";
    159     return NULL;
    160   }
    161   Profile* profile = ProfileManager::GetActiveUserProfile();
    162   if (is_incognito) {
    163     return profile->GetOffTheRecordProfile();
    164   }
    165   return profile;
    166 }
    167 
    168 }  // namespace
    169 
    170 // ----------------------------------------------------------------------------
    171 // Native JNI methods
    172 // ----------------------------------------------------------------------------
    173 
    174 static jlong Init(JNIEnv* env, jobject obj, jboolean is_incognito) {
    175   Profile* profile = FindProfile(is_incognito);
    176   TabModel* tab_model = new TabModelBase(env, obj, profile);
    177   TabModelList::AddTabModel(tab_model);
    178   return reinterpret_cast<intptr_t>(tab_model);
    179 }
    180 
    181 inline static base::TimeDelta GetTimeDelta(jlong ms) {
    182   return base::TimeDelta::FromMilliseconds(static_cast<int64>(ms));
    183 }
    184 
    185 void LogFromCloseMetric(JNIEnv* env,
    186                         jclass jcaller,
    187                         jlong ms,
    188                         jboolean perceived) {
    189   if (perceived) {
    190     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromCloseLatency_Perceived",
    191                         GetTimeDelta(ms));
    192   } else {
    193     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromCloseLatency_Actual",
    194                         GetTimeDelta(ms));
    195   }
    196 }
    197 
    198 void LogFromExitMetric(JNIEnv* env,
    199                        jclass jcaller,
    200                        jlong ms,
    201                        jboolean perceived) {
    202   if (perceived) {
    203     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromExitLatency_Perceived",
    204                         GetTimeDelta(ms));
    205   } else {
    206     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromExitLatency_Actual",
    207                         GetTimeDelta(ms));
    208   }
    209 }
    210 
    211 void LogFromNewMetric(JNIEnv* env,
    212                       jclass jcaller,
    213                       jlong ms,
    214                       jboolean perceived) {
    215   if (perceived) {
    216     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromNewLatency_Perceived",
    217                         GetTimeDelta(ms));
    218   } else {
    219     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromNewLatency_Actual",
    220                         GetTimeDelta(ms));
    221   }
    222 }
    223 
    224 void LogFromUserMetric(JNIEnv* env,
    225                        jclass jcaller,
    226                        jlong ms,
    227                        jboolean perceived) {
    228   if (perceived) {
    229     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromUserLatency_Perceived",
    230                         GetTimeDelta(ms));
    231   } else {
    232     UMA_HISTOGRAM_TIMES("Tabs.SwitchFromUserLatency_Actual",
    233                         GetTimeDelta(ms));
    234   }
    235 }
    236 
    237 // Register native methods
    238 
    239 bool RegisterTabModelBase(JNIEnv* env) {
    240   return RegisterNativesImpl(env);
    241 }
    242