root/chrome/browser/android/recently_closed_tabs_bridge.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. AddTabToList
  2. AddTabsToList
  3. tab_restore_service_
  4. Destroy
  5. SetRecentlyClosedCallback
  6. GetRecentlyClosedTabs
  7. OpenRecentlyClosedTab
  8. ClearRecentlyClosedTabs
  9. TabRestoreServiceChanged
  10. TabRestoreServiceDestroyed
  11. EnsureTabRestoreService
  12. Init
  13. Register

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/recently_closed_tabs_bridge.h"

#include "base/android/jni_string.h"
#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_android.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sessions/tab_restore_service.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "content/public/browser/web_contents.h"
#include "jni/RecentlyClosedBridge_jni.h"

using base::android::AttachCurrentThread;
using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;

namespace {

void AddTabToList(JNIEnv* env,
                  TabRestoreService::Entry* entry,
                  jobject jtabs_list) {
  const TabRestoreService::Tab* tab =
      static_cast<TabRestoreService::Tab*>(entry);
  const sessions::SerializedNavigationEntry& current_navigation =
      tab->navigations.at(tab->current_navigation_index);
  Java_RecentlyClosedBridge_pushTab(
      env, jtabs_list, entry->id,
      ConvertUTF16ToJavaString(env, current_navigation.title()).Release(),
      ConvertUTF8ToJavaString(env, current_navigation.virtual_url().spec())
          .Release());
}

void AddTabsToList(JNIEnv* env,
                   const TabRestoreService::Entries& entries,
                   jobject jtabs_list,
                   int max_tab_count) {
  int added_count = 0;
  for (TabRestoreService::Entries::const_iterator it = entries.begin();
       it != entries.end() && added_count < max_tab_count; ++it) {
    TabRestoreService::Entry* entry = *it;
    DCHECK_EQ(entry->type, TabRestoreService::TAB);
    if (entry->type == TabRestoreService::TAB) {
      AddTabToList(env, entry, jtabs_list);
      ++added_count;
    }
  }
}

}  // namespace

RecentlyClosedTabsBridge::RecentlyClosedTabsBridge(Profile* profile)
    : profile_(profile),
      tab_restore_service_(NULL) {
}

RecentlyClosedTabsBridge::~RecentlyClosedTabsBridge() {
  if (tab_restore_service_)
    tab_restore_service_->RemoveObserver(this);
}

void RecentlyClosedTabsBridge::Destroy(JNIEnv* env, jobject obj) {
  delete this;
}

void RecentlyClosedTabsBridge::SetRecentlyClosedCallback(JNIEnv* env,
                                                         jobject obj,
                                                         jobject jcallback) {
  callback_.Reset(env, jcallback);
}

jboolean RecentlyClosedTabsBridge::GetRecentlyClosedTabs(JNIEnv* env,
                                                         jobject obj,
                                                         jobject jtabs_list,
                                                         jint max_tab_count) {
  EnsureTabRestoreService();
  if (!tab_restore_service_)
    return false;

  AddTabsToList(env, tab_restore_service_->entries(), jtabs_list,
                max_tab_count);
  return true;
}

jboolean RecentlyClosedTabsBridge::OpenRecentlyClosedTab(JNIEnv* env,
                                                         jobject obj,
                                                         jobject jtab,
                                                         jint recent_tab_id,
                                                         jint j_disposition) {
  if (!tab_restore_service_)
    return false;

  // Find and remove the corresponding tab entry from TabRestoreService.
  // We take ownership of the returned tab.
  scoped_ptr<TabRestoreService::Tab> tab_entry(
      tab_restore_service_->RemoveTabEntryById(recent_tab_id));
  if (!tab_entry)
    return false;

  TabAndroid* tab_android = TabAndroid::GetNativeTab(env, jtab);
  if (!tab_android)
    return false;
  content::WebContents* web_contents = tab_android->web_contents();
  if (!web_contents)
    return false;

  // RestoreForeignSessionTab needs a SessionTab.
  SessionTab session_tab;
  session_tab.current_navigation_index = tab_entry->current_navigation_index;
  session_tab.navigations = tab_entry->navigations;

  WindowOpenDisposition disposition =
      static_cast<WindowOpenDisposition>(j_disposition);
  SessionRestore::RestoreForeignSessionTab(web_contents,
                                           session_tab,
                                           disposition);
  return true;
}

void RecentlyClosedTabsBridge::ClearRecentlyClosedTabs(JNIEnv* env,
                                                       jobject obj) {
  EnsureTabRestoreService();
  if (tab_restore_service_)
    tab_restore_service_->ClearEntries();
}

void RecentlyClosedTabsBridge::TabRestoreServiceChanged(
    TabRestoreService* service) {
  if (callback_.is_null())
    return;
  JNIEnv* env = AttachCurrentThread();
  Java_RecentlyClosedCallback_onUpdated(env, callback_.obj());
}

void RecentlyClosedTabsBridge::TabRestoreServiceDestroyed(
    TabRestoreService* service) {
  tab_restore_service_ = NULL;
}

void RecentlyClosedTabsBridge::EnsureTabRestoreService() {
  if (tab_restore_service_)
    return;

  tab_restore_service_ = TabRestoreServiceFactory::GetForProfile(profile_);

  // TabRestoreServiceFactory::GetForProfile() can return NULL (e.g. in
  // incognito mode).
  if (tab_restore_service_) {
    // This does nothing if the tabs have already been loaded or they
    // shouldn't be loaded.
    tab_restore_service_->LoadTabsFromLastSession();
    tab_restore_service_->AddObserver(this);
  }
}

static jlong Init(JNIEnv* env, jobject obj, jobject jprofile) {
  RecentlyClosedTabsBridge* bridge = new RecentlyClosedTabsBridge(
      ProfileAndroid::FromProfileAndroid(jprofile));
  return reinterpret_cast<intptr_t>(bridge);
}

// static
bool RecentlyClosedTabsBridge::Register(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

/* [<][>][^][v][top][bottom][index][help] */