Home | History | Annotate | Download | only in session_restore
      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.
      4 
      5 #include "chrome/browser/extensions/api/session_restore/session_restore_api.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/i18n/rtl.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/strings/string_number_conversions.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "chrome/browser/extensions/extension_function_registry.h"
     14 #include "chrome/browser/extensions/extension_tab_util.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/browser/sessions/session_restore.h"
     17 #include "chrome/browser/sessions/tab_restore_service_delegate.h"
     18 #include "chrome/browser/sessions/tab_restore_service_factory.h"
     19 #include "chrome/browser/sync/glue/session_model_associator.h"
     20 #include "chrome/browser/sync/glue/synced_session.h"
     21 #include "chrome/browser/sync/profile_sync_service.h"
     22 #include "chrome/browser/sync/profile_sync_service_factory.h"
     23 #include "chrome/browser/ui/browser.h"
     24 #include "chrome/browser/ui/browser_finder.h"
     25 #include "chrome/browser/ui/host_desktop.h"
     26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     27 #include "content/public/browser/web_contents.h"
     28 #include "ui/base/layout.h"
     29 
     30 
     31 namespace {
     32 
     33 const unsigned int kMaxRecentlyClosedSessionResults = 25;
     34 const char kRecentlyClosedListEmpty[] =
     35     "There are no recently closed sessions.";
     36 const char kInvalidSessionId[] = "Invalid session id.";
     37 const char kNoBrowserToRestoreSession[] =
     38     "There are no browser windows to restore the session.";
     39 
     40 }  // namespace
     41 
     42 namespace extensions {
     43 
     44 namespace GetRecentlyClosed = api::session_restore::GetRecentlyClosed;
     45 namespace Restore = api::session_restore::Restore;
     46 namespace tabs = api::tabs;
     47 namespace windows = api::windows;
     48 namespace session_restore = api::session_restore;
     49 
     50 scoped_ptr<tabs::Tab> SessionRestoreGetRecentlyClosedFunction::CreateTabModel(
     51     const TabRestoreService::Tab& tab, int selected_index) {
     52   scoped_ptr<tabs::Tab> tab_struct(new tabs::Tab);
     53   const sessions::SerializedNavigationEntry& current_navigation =
     54       tab.navigations[tab.current_navigation_index];
     55   GURL gurl = current_navigation.virtual_url();
     56   std::string title = UTF16ToUTF8(current_navigation.title());
     57 
     58   tab_struct->url.reset(new std::string(gurl.spec()));
     59   tab_struct->title.reset(new std::string(title.empty() ? gurl.spec() : title));
     60   tab_struct->index = tab.tabstrip_index;
     61   tab_struct->pinned = tab.pinned;
     62   tab_struct->id = tab.id;
     63   tab_struct->window_id = tab.browser_id;
     64   tab_struct->index = tab.tabstrip_index;
     65   tab_struct->pinned = tab.pinned;
     66   tab_struct->selected = tab.tabstrip_index == selected_index;
     67   tab_struct->active = false;
     68   tab_struct->highlighted = false;
     69   tab_struct->incognito = false;
     70   ExtensionTabUtil::ScrubTabForExtension(GetExtension(),
     71                                          tab_struct.get());
     72   return tab_struct.Pass();
     73 }
     74 
     75 scoped_ptr<windows::Window>
     76     SessionRestoreGetRecentlyClosedFunction::CreateWindowModel(
     77         const TabRestoreService::Window& window) {
     78   scoped_ptr<windows::Window> window_struct(new windows::Window);
     79   DCHECK(!window.tabs.empty());
     80 
     81   scoped_ptr<std::vector<linked_ptr<tabs::Tab> > > tabs(
     82       new std::vector<linked_ptr<tabs::Tab> >);
     83   for (size_t i = 0; i < window.tabs.size(); ++i) {
     84     tabs->push_back(make_linked_ptr(CreateTabModel(window.tabs[i],
     85         window.selected_tab_index).release()));
     86   }
     87   window_struct->tabs.reset(tabs.release());
     88   window_struct->incognito = false;
     89   window_struct->always_on_top = false;
     90   window_struct->focused = false;
     91   window_struct->type = windows::Window::TYPE_NORMAL;
     92   window_struct->state = windows::Window::STATE_NORMAL;
     93   return window_struct.Pass();
     94 }
     95 
     96 scoped_ptr<session_restore::ClosedEntry>
     97     SessionRestoreGetRecentlyClosedFunction::CreateEntryModel(
     98         const TabRestoreService::Entry* entry) {
     99   scoped_ptr<session_restore::ClosedEntry> entry_struct(
    100       new session_restore::ClosedEntry);
    101   switch (entry->type) {
    102     case TabRestoreService::TAB:
    103       entry_struct->tab.reset(CreateTabModel(
    104           *static_cast<const TabRestoreService::Tab*>(entry), -1).release());
    105       break;
    106     case TabRestoreService::WINDOW:
    107       entry_struct->window.reset(CreateWindowModel(
    108           *static_cast<const TabRestoreService::Window*>(entry)).release());
    109       break;
    110     default:
    111       NOTREACHED();
    112   }
    113   entry_struct->timestamp = entry->timestamp.ToTimeT();
    114   entry_struct->id = entry->id;
    115   return entry_struct.Pass();
    116 }
    117 
    118 bool SessionRestoreGetRecentlyClosedFunction::RunImpl() {
    119   scoped_ptr<GetRecentlyClosed::Params> params(
    120       GetRecentlyClosed::Params::Create(*args_));
    121   EXTENSION_FUNCTION_VALIDATE(params.get());
    122   unsigned int max_results = kMaxRecentlyClosedSessionResults;
    123   if (params->options && params->options->max_results)
    124     max_results = *params->options->max_results;
    125   EXTENSION_FUNCTION_VALIDATE(max_results >= 0 &&
    126                               max_results <= kMaxRecentlyClosedSessionResults);
    127 
    128   std::vector<linked_ptr<session_restore::ClosedEntry> > result;
    129   TabRestoreService* tab_restore_service =
    130       TabRestoreServiceFactory::GetForProfile(profile());
    131   DCHECK(tab_restore_service);
    132 
    133   // List of entries. They are ordered from most to least recent.
    134   // We prune the list to contain max 25 entries at any time and removes
    135   // uninteresting entries.
    136   TabRestoreService::Entries entries = tab_restore_service->entries();
    137   for (TabRestoreService::Entries::const_iterator it = entries.begin();
    138        it != entries.end() && result.size() < max_results; ++it) {
    139     TabRestoreService::Entry* entry = *it;
    140     if (!params->options || params->options->entry_type ==
    141         GetRecentlyClosed::Params::Options::ENTRY_TYPE_NONE) {
    142       // Include both tabs and windows if type is not defined.
    143       result.push_back(make_linked_ptr(CreateEntryModel(entry).release()));
    144     } else if (
    145         (params->options->entry_type ==
    146             GetRecentlyClosed::Params::Options::ENTRY_TYPE_TAB &&
    147                 entry->type == TabRestoreService::TAB) ||
    148         (params->options->entry_type ==
    149             GetRecentlyClosed::Params::Options::ENTRY_TYPE_WINDOW &&
    150                 entry->type == TabRestoreService::WINDOW)) {
    151       result.push_back(make_linked_ptr(CreateEntryModel(entry).release()));
    152     }
    153   }
    154 
    155   results_ = GetRecentlyClosed::Results::Create(result);
    156   return true;
    157 }
    158 
    159 bool SessionRestoreRestoreFunction::RunImpl() {
    160   scoped_ptr<Restore::Params> params(Restore::Params::Create(*args_));
    161   EXTENSION_FUNCTION_VALIDATE(params.get());
    162 
    163   Browser* browser =
    164       chrome::FindBrowserWithProfile(profile(),
    165                                      chrome::HOST_DESKTOP_TYPE_NATIVE);
    166   if (!browser) {
    167     error_ = kNoBrowserToRestoreSession;
    168     return false;
    169   }
    170 
    171   TabRestoreService* tab_restore_service =
    172       TabRestoreServiceFactory::GetForProfile(profile());
    173   TabRestoreServiceDelegate* delegate =
    174       TabRestoreServiceDelegate::FindDelegateForWebContents(
    175           browser->tab_strip_model()->GetActiveWebContents());
    176   DCHECK(delegate);
    177   chrome::HostDesktopType host_desktop_type = browser->host_desktop_type();
    178   TabRestoreService::Entries entries = tab_restore_service->entries();
    179 
    180   if (entries.empty()) {
    181     error_ = kRecentlyClosedListEmpty;
    182     return false;
    183   }
    184 
    185   if (!params->id) {
    186     tab_restore_service->RestoreMostRecentEntry(delegate, host_desktop_type);
    187     return true;
    188   }
    189 
    190   // Check if the recently closed list contains an entry with the provided id.
    191   bool is_valid_id = false;
    192   for (TabRestoreService::Entries::iterator it = entries.begin();
    193        it != entries.end(); ++it) {
    194     if ((*it)->id == *params->id) {
    195       is_valid_id = true;
    196       break;
    197     }
    198 
    199     // For Window entries, see if the ID matches a tab. If so, report true for
    200     // the window as the Entry.
    201     if ((*it)->type == TabRestoreService::WINDOW) {
    202       std::vector<TabRestoreService::Tab>& tabs =
    203           static_cast<TabRestoreService::Window*>(*it)->tabs;
    204       for (std::vector<TabRestoreService::Tab>::iterator tab_it = tabs.begin();
    205            tab_it != tabs.end(); ++tab_it) {
    206         if ((*tab_it).id == *params->id) {
    207           is_valid_id = true;
    208           break;
    209         }
    210       }
    211     }
    212   }
    213 
    214   if (!is_valid_id) {
    215     error_ = kInvalidSessionId;
    216     return false;
    217   }
    218 
    219   tab_restore_service->RestoreEntryById(delegate, *params->id,
    220       host_desktop_type, UNKNOWN);
    221   return true;
    222 }
    223 
    224 SessionRestoreAPI::SessionRestoreAPI(Profile* profile) {
    225 }
    226 
    227 SessionRestoreAPI::~SessionRestoreAPI() {
    228 }
    229 
    230 static base::LazyInstance<ProfileKeyedAPIFactory<SessionRestoreAPI> >
    231     g_factory = LAZY_INSTANCE_INITIALIZER;
    232 
    233 // static
    234 ProfileKeyedAPIFactory<SessionRestoreAPI>*
    235     SessionRestoreAPI::GetFactoryInstance() {
    236   return &g_factory.Get();
    237 }
    238 
    239 }  // namespace extensions
    240