| Index: chrome/browser/extensions/api/sessions/sessions_api.cc
|
| diff --git a/chrome/browser/extensions/api/session_restore/session_restore_api.cc b/chrome/browser/extensions/api/sessions/sessions_api.cc
|
| similarity index 19%
|
| rename from chrome/browser/extensions/api/session_restore/session_restore_api.cc
|
| rename to chrome/browser/extensions/api/sessions/sessions_api.cc
|
| index ed0042cb6efc7676a160159f8c400df72ba3630c..95514aab95bc867512e35105869ed3084e3c47f2 100644
|
| --- a/chrome/browser/extensions/api/session_restore/session_restore_api.cc
|
| +++ b/chrome/browser/extensions/api/sessions/sessions_api.cc
|
| @@ -1,18 +1,27 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 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/extensions/api/session_restore/session_restore_api.h"
|
| +#include "chrome/browser/extensions/api/sessions/sessions_api.h"
|
|
|
| #include <vector>
|
|
|
| #include "base/i18n/rtl.h"
|
| #include "base/lazy_instance.h"
|
| +#include "base/prefs/pref_service.h"
|
| #include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/stringprintf.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| +#include "base/time/time.h"
|
| +#include "chrome/browser/extensions/api/sessions/session_id.h"
|
| +#include "chrome/browser/extensions/api/tabs/windows_util.h"
|
| +#include "chrome/browser/extensions/extension_function_dispatcher.h"
|
| #include "chrome/browser/extensions/extension_function_registry.h"
|
| #include "chrome/browser/extensions/extension_tab_util.h"
|
| +#include "chrome/browser/extensions/window_controller.h"
|
| +#include "chrome/browser/extensions/window_controller_list.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/search/search.h"
|
| #include "chrome/browser/sessions/session_restore.h"
|
| #include "chrome/browser/sessions/tab_restore_service_delegate.h"
|
| #include "chrome/browser/sessions/tab_restore_service_factory.h"
|
| @@ -24,108 +33,176 @@
|
| #include "chrome/browser/ui/browser_finder.h"
|
| #include "chrome/browser/ui/host_desktop.h"
|
| #include "chrome/browser/ui/tabs/tab_strip_model.h"
|
| +#include "chrome/common/pref_names.cc"
|
| #include "content/public/browser/web_contents.h"
|
| +#include "extensions/common/error_utils.h"
|
| +#include "net/base/net_util.h"
|
| #include "ui/base/layout.h"
|
|
|
| +namespace extensions {
|
|
|
| -namespace {
|
| +namespace GetRecentlyClosed = api::sessions::GetRecentlyClosed;
|
| +namespace GetDevices = api::sessions::GetDevices;
|
| +namespace Restore = api::sessions::Restore;
|
| +namespace tabs = api::tabs;
|
| +namespace windows = api::windows;
|
|
|
| -const unsigned int kMaxRecentlyClosedSessionResults = 25;
|
| -const char kRecentlyClosedListEmpty[] =
|
| +const char kNoRecentlyClosedSessionsError[] =
|
| "There are no recently closed sessions.";
|
| -const char kInvalidSessionId[] = "Invalid session id.";
|
| +const char kInvalidSessionIdError[] = "Invalid session id: \"*\".";
|
| const char kNoBrowserToRestoreSession[] =
|
| "There are no browser windows to restore the session.";
|
| +const char kSessionSyncError[] = "Synced sessions are not available.";
|
|
|
| -} // namespace
|
| -
|
| -namespace extensions {
|
| +// Comparator function for use with std::sort that will sort sessions by
|
| +// descending modified_time (i.e., most recent first).
|
| +bool SortSessionsByRecency(const browser_sync::SyncedSession* s1,
|
| + const browser_sync::SyncedSession* s2) {
|
| + return s1->modified_time > s2->modified_time;
|
| +}
|
|
|
| -namespace GetRecentlyClosed = api::session_restore::GetRecentlyClosed;
|
| -namespace Restore = api::session_restore::Restore;
|
| -namespace tabs = api::tabs;
|
| -namespace windows = api::windows;
|
| -namespace session_restore = api::session_restore;
|
| +// Comparator function for use with std::sort that will sort tabs in a window
|
| +// by descending timestamp (i.e., most recent first).
|
| +bool SortTabsByRecency(const SessionTab* t1, const SessionTab* t2) {
|
| + return t1->timestamp > t2->timestamp;
|
| +}
|
|
|
| -scoped_ptr<tabs::Tab> SessionRestoreGetRecentlyClosedFunction::CreateTabModel(
|
| - const TabRestoreService::Tab& tab, int selected_index) {
|
| +scoped_ptr<tabs::Tab> CreateTabModelHelper(
|
| + Profile* profile,
|
| + const sessions::SerializedNavigationEntry& current_navigation,
|
| + const std::string& session_id,
|
| + int index,
|
| + bool pinned,
|
| + int selected_index,
|
| + const Extension* extension) {
|
| scoped_ptr<tabs::Tab> tab_struct(new tabs::Tab);
|
| - const sessions::SerializedNavigationEntry& current_navigation =
|
| - tab.navigations[tab.current_navigation_index];
|
| +
|
| GURL gurl = current_navigation.virtual_url();
|
| std::string title = UTF16ToUTF8(current_navigation.title());
|
|
|
| + tab_struct->session_id.reset(new std::string(session_id));
|
| tab_struct->url.reset(new std::string(gurl.spec()));
|
| - tab_struct->title.reset(new std::string(title.empty() ? gurl.spec() : title));
|
| - tab_struct->index = tab.tabstrip_index;
|
| - tab_struct->pinned = tab.pinned;
|
| - tab_struct->id = tab.id;
|
| - tab_struct->window_id = tab.browser_id;
|
| - tab_struct->index = tab.tabstrip_index;
|
| - tab_struct->pinned = tab.pinned;
|
| - tab_struct->selected = tab.tabstrip_index == selected_index;
|
| + if (!title.empty()) {
|
| + tab_struct->title.reset(new std::string(title));
|
| + } else {
|
| + const std::string languages =
|
| + profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
|
| + tab_struct->title.reset(new std::string(UTF16ToUTF8(
|
| + net::FormatUrl(gurl, languages))));
|
| + }
|
| + tab_struct->index = index;
|
| + tab_struct->pinned = pinned;
|
| + tab_struct->selected = index == selected_index;
|
| tab_struct->active = false;
|
| tab_struct->highlighted = false;
|
| tab_struct->incognito = false;
|
| - ExtensionTabUtil::ScrubTabForExtension(GetExtension(),
|
| - tab_struct.get());
|
| + ExtensionTabUtil::ScrubTabForExtension(extension, tab_struct.get());
|
| return tab_struct.Pass();
|
| }
|
|
|
| -scoped_ptr<windows::Window>
|
| - SessionRestoreGetRecentlyClosedFunction::CreateWindowModel(
|
| - const TabRestoreService::Window& window) {
|
| +scoped_ptr<windows::Window> CreateWindowModelHelper(
|
| + scoped_ptr<std::vector<linked_ptr<tabs::Tab> > > tabs,
|
| + const std::string& session_id,
|
| + const windows::Window::Type& type,
|
| + const windows::Window::State& state) {
|
| scoped_ptr<windows::Window> window_struct(new windows::Window);
|
| + window_struct->tabs = tabs.Pass();
|
| + window_struct->session_id.reset(new std::string(session_id));
|
| + window_struct->incognito = false;
|
| + window_struct->always_on_top = false;
|
| + window_struct->focused = false;
|
| + window_struct->type = type;
|
| + window_struct->state = state;
|
| + return window_struct.Pass();
|
| +}
|
| +
|
| +scoped_ptr<api::sessions::Session> CreateSessionModelHelper(
|
| + int last_modified,
|
| + scoped_ptr<tabs::Tab> tab,
|
| + scoped_ptr<windows::Window> window) {
|
| + scoped_ptr<api::sessions::Session> session_struct(new api::sessions::Session);
|
| + session_struct->last_modified = last_modified;
|
| + if (tab)
|
| + session_struct->tab = tab.Pass();
|
| + else if (window)
|
| + session_struct->window = window.Pass();
|
| + else
|
| + NOTREACHED();
|
| + return session_struct.Pass();
|
| +}
|
| +
|
| +bool is_tab_entry(const TabRestoreService::Entry* entry) {
|
| + return entry->type == TabRestoreService::TAB;
|
| +}
|
| +
|
| +bool is_window_entry(const TabRestoreService::Entry* entry) {
|
| + return entry->type == TabRestoreService::WINDOW;
|
| +}
|
| +
|
| +scoped_ptr<tabs::Tab> SessionsGetRecentlyClosedFunction::CreateTabModel(
|
| + const TabRestoreService::Tab& tab, int session_id, int selected_index) {
|
| + return CreateTabModelHelper(profile(),
|
| + tab.navigations[tab.current_navigation_index],
|
| + base::IntToString(session_id),
|
| + tab.tabstrip_index,
|
| + tab.pinned,
|
| + selected_index,
|
| + GetExtension());
|
| +}
|
| +
|
| +scoped_ptr<windows::Window>
|
| + SessionsGetRecentlyClosedFunction::CreateWindowModel(
|
| + const TabRestoreService::Window& window,
|
| + int session_id) {
|
| DCHECK(!window.tabs.empty());
|
|
|
| scoped_ptr<std::vector<linked_ptr<tabs::Tab> > > tabs(
|
| new std::vector<linked_ptr<tabs::Tab> >);
|
| for (size_t i = 0; i < window.tabs.size(); ++i) {
|
| - tabs->push_back(make_linked_ptr(CreateTabModel(window.tabs[i],
|
| - window.selected_tab_index).release()));
|
| + tabs->push_back(make_linked_ptr(
|
| + CreateTabModel(window.tabs[i], window.tabs[i].id,
|
| + window.selected_tab_index).release()));
|
| }
|
| - window_struct->tabs.reset(tabs.release());
|
| - window_struct->incognito = false;
|
| - window_struct->always_on_top = false;
|
| - window_struct->focused = false;
|
| - window_struct->type = windows::Window::TYPE_NORMAL;
|
| - window_struct->state = windows::Window::STATE_NORMAL;
|
| - return window_struct.Pass();
|
| +
|
| + return CreateWindowModelHelper(tabs.Pass(),
|
| + base::IntToString(session_id),
|
| + windows::Window::TYPE_NORMAL,
|
| + windows::Window::STATE_NORMAL);
|
| }
|
|
|
| -scoped_ptr<session_restore::ClosedEntry>
|
| - SessionRestoreGetRecentlyClosedFunction::CreateEntryModel(
|
| +scoped_ptr<api::sessions::Session>
|
| + SessionsGetRecentlyClosedFunction::CreateSessionModel(
|
| const TabRestoreService::Entry* entry) {
|
| - scoped_ptr<session_restore::ClosedEntry> entry_struct(
|
| - new session_restore::ClosedEntry);
|
| + scoped_ptr<tabs::Tab> tab;
|
| + scoped_ptr<windows::Window> window;
|
| switch (entry->type) {
|
| case TabRestoreService::TAB:
|
| - entry_struct->tab.reset(CreateTabModel(
|
| - *static_cast<const TabRestoreService::Tab*>(entry), -1).release());
|
| + tab = CreateTabModel(
|
| + *static_cast<const TabRestoreService::Tab*>(entry), entry->id, -1);
|
| break;
|
| case TabRestoreService::WINDOW:
|
| - entry_struct->window.reset(CreateWindowModel(
|
| - *static_cast<const TabRestoreService::Window*>(entry)).release());
|
| + window = CreateWindowModel(
|
| + *static_cast<const TabRestoreService::Window*>(entry), entry->id);
|
| break;
|
| default:
|
| NOTREACHED();
|
| }
|
| - entry_struct->timestamp = entry->timestamp.ToTimeT();
|
| - entry_struct->id = entry->id;
|
| - return entry_struct.Pass();
|
| + return CreateSessionModelHelper(entry->timestamp.ToTimeT(),
|
| + tab.Pass(),
|
| + window.Pass());
|
| }
|
|
|
| -bool SessionRestoreGetRecentlyClosedFunction::RunImpl() {
|
| +bool SessionsGetRecentlyClosedFunction::RunImpl() {
|
| scoped_ptr<GetRecentlyClosed::Params> params(
|
| GetRecentlyClosed::Params::Create(*args_));
|
| - EXTENSION_FUNCTION_VALIDATE(params.get());
|
| - unsigned int max_results = kMaxRecentlyClosedSessionResults;
|
| - if (params->options && params->options->max_results)
|
| - max_results = *params->options->max_results;
|
| + EXTENSION_FUNCTION_VALIDATE(params);
|
| + int max_results = api::sessions::MAX_SESSION_RESULTS;
|
| + if (params->filter && params->filter->max_results)
|
| + max_results = *params->filter->max_results;
|
| EXTENSION_FUNCTION_VALIDATE(max_results >= 0 &&
|
| - max_results <= kMaxRecentlyClosedSessionResults);
|
| + max_results <= api::sessions::MAX_SESSION_RESULTS);
|
|
|
| - std::vector<linked_ptr<session_restore::ClosedEntry> > result;
|
| + std::vector<linked_ptr<api::sessions::Session> > result;
|
| TabRestoreService* tab_restore_service =
|
| TabRestoreServiceFactory::GetForProfile(profile());
|
| DCHECK(tab_restore_service);
|
| @@ -135,104 +212,376 @@ bool SessionRestoreGetRecentlyClosedFunction::RunImpl() {
|
| // uninteresting entries.
|
| TabRestoreService::Entries entries = tab_restore_service->entries();
|
| for (TabRestoreService::Entries::const_iterator it = entries.begin();
|
| - it != entries.end() && result.size() < max_results; ++it) {
|
| + it != entries.end() && static_cast<int>(result.size()) < max_results;
|
| + ++it) {
|
| TabRestoreService::Entry* entry = *it;
|
| - if (!params->options || params->options->entry_type ==
|
| - GetRecentlyClosed::Params::Options::ENTRY_TYPE_NONE) {
|
| - // Include both tabs and windows if type is not defined.
|
| - result.push_back(make_linked_ptr(CreateEntryModel(entry).release()));
|
| - } else if (
|
| - (params->options->entry_type ==
|
| - GetRecentlyClosed::Params::Options::ENTRY_TYPE_TAB &&
|
| - entry->type == TabRestoreService::TAB) ||
|
| - (params->options->entry_type ==
|
| - GetRecentlyClosed::Params::Options::ENTRY_TYPE_WINDOW &&
|
| - entry->type == TabRestoreService::WINDOW)) {
|
| - result.push_back(make_linked_ptr(CreateEntryModel(entry).release()));
|
| - }
|
| + result.push_back(make_linked_ptr(CreateSessionModel(entry).release()));
|
| }
|
|
|
| results_ = GetRecentlyClosed::Results::Create(result);
|
| return true;
|
| }
|
|
|
| -bool SessionRestoreRestoreFunction::RunImpl() {
|
| - scoped_ptr<Restore::Params> params(Restore::Params::Create(*args_));
|
| - EXTENSION_FUNCTION_VALIDATE(params.get());
|
| +scoped_ptr<tabs::Tab> SessionsGetDevicesFunction::CreateTabModel(
|
| + const std::string& session_tag,
|
| + const SessionTab& tab,
|
| + int tab_index,
|
| + int selected_index) {
|
| + std::string session_id = SessionId(session_tag, tab.tab_id.id()).ToString();
|
| + return CreateTabModelHelper(profile(),
|
| + tab.navigations[tab.current_navigation_index],
|
| + session_id,
|
| + tab_index,
|
| + tab.pinned,
|
| + selected_index,
|
| + GetExtension());
|
| +}
|
|
|
| - Browser* browser =
|
| - chrome::FindBrowserWithProfile(profile(),
|
| - chrome::HOST_DESKTOP_TYPE_NATIVE);
|
| - if (!browser) {
|
| - error_ = kNoBrowserToRestoreSession;
|
| +scoped_ptr<windows::Window> SessionsGetDevicesFunction::CreateWindowModel(
|
| + const SessionWindow& window, const std::string& session_tag) {
|
| + DCHECK(!window.tabs.empty());
|
| +
|
| + // Prune tabs that are not syncable or are NewTabPage. Then, sort the tabs
|
| + // from most recent to least recent.
|
| + std::vector<const SessionTab*> tabs_in_window;
|
| + for (size_t i = 0; i < window.tabs.size(); ++i) {
|
| + const SessionTab* tab = window.tabs[i];
|
| + if (tab->navigations.empty())
|
| + continue;
|
| + const sessions::SerializedNavigationEntry& current_navigation =
|
| + tab->navigations.at(tab->normalized_navigation_index());
|
| + if (chrome::IsNTPURL(current_navigation.virtual_url(), profile())) {
|
| + continue;
|
| + }
|
| + tabs_in_window.push_back(tab);
|
| + }
|
| + if (tabs_in_window.empty())
|
| + return scoped_ptr<windows::Window>();
|
| + std::sort(tabs_in_window.begin(), tabs_in_window.end(), SortTabsByRecency);
|
| +
|
| + scoped_ptr<std::vector<linked_ptr<tabs::Tab> > > tabs(
|
| + new std::vector<linked_ptr<tabs::Tab> >);
|
| + for (size_t i = 0; i < window.tabs.size(); ++i) {
|
| + tabs->push_back(make_linked_ptr(
|
| + CreateTabModel(session_tag, *window.tabs[i], i,
|
| + window.selected_tab_index).release()));
|
| + }
|
| +
|
| + std::string session_id =
|
| + SessionId(session_tag, window.window_id.id()).ToString();
|
| +
|
| + windows::Window::Type type = windows::Window::TYPE_NONE;
|
| + switch (window.type) {
|
| + case Browser::TYPE_TABBED:
|
| + type = windows::Window::TYPE_NORMAL;
|
| + break;
|
| + case Browser::TYPE_POPUP:
|
| + type = windows::Window::TYPE_POPUP;
|
| + break;
|
| + }
|
| +
|
| + windows::Window::State state = windows::Window::STATE_NONE;
|
| + switch (window.show_state) {
|
| + case ui::SHOW_STATE_NORMAL:
|
| + state = windows::Window::STATE_NORMAL;
|
| + break;
|
| + case ui::SHOW_STATE_MINIMIZED:
|
| + state = windows::Window::STATE_MINIMIZED;
|
| + break;
|
| + case ui::SHOW_STATE_MAXIMIZED:
|
| + state = windows::Window::STATE_MAXIMIZED;
|
| + break;
|
| + case ui::SHOW_STATE_FULLSCREEN:
|
| + state = windows::Window::STATE_FULLSCREEN;
|
| + break;
|
| + case ui::SHOW_STATE_DEFAULT:
|
| + case ui::SHOW_STATE_INACTIVE:
|
| + case ui::SHOW_STATE_DETACHED:
|
| + case ui::SHOW_STATE_END:
|
| + break;
|
| + }
|
| +
|
| + scoped_ptr<windows::Window> window_struct(
|
| + CreateWindowModelHelper(tabs.Pass(), session_id, type, state));
|
| + // TODO(dwankri): Dig deeper to resolve bounds not being optional, so closed
|
| + // windows in GetRecentlyClosed can have set values in Window helper.
|
| + window_struct->left.reset(new int(window.bounds.x()));
|
| + window_struct->top.reset(new int(window.bounds.y()));
|
| + window_struct->width.reset(new int(window.bounds.width()));
|
| + window_struct->height.reset(new int(window.bounds.height()));
|
| +
|
| + return window_struct.Pass();
|
| +}
|
| +
|
| +scoped_ptr<api::sessions::Session>
|
| +SessionsGetDevicesFunction::CreateSessionModel(
|
| + const SessionWindow& window, const std::string& session_tag) {
|
| + scoped_ptr<windows::Window> window_model(
|
| + CreateWindowModel(window, session_tag));
|
| + // There is a chance that after pruning uninteresting tabs the window will be
|
| + // empty.
|
| + return !window_model ? scoped_ptr<api::sessions::Session>()
|
| + : CreateSessionModelHelper(window.timestamp.ToTimeT(),
|
| + scoped_ptr<tabs::Tab>(),
|
| + window_model.Pass());
|
| +}
|
| +
|
| +scoped_ptr<api::sessions::Device> SessionsGetDevicesFunction::CreateDeviceModel(
|
| + const browser_sync::SyncedSession* session) {
|
| + int max_results = api::sessions::MAX_SESSION_RESULTS;
|
| + scoped_ptr<GetDevices::Params> params(GetDevices::Params::Create(*args_));
|
| + EXTENSION_FUNCTION_VALIDATE(params);
|
| + if (params->filter && params->filter->max_results)
|
| + max_results = *params->filter->max_results;
|
| + EXTENSION_FUNCTION_VALIDATE(max_results >= 0 &&
|
| + max_results <= api::sessions::MAX_SESSION_RESULTS);
|
| +
|
| + scoped_ptr<api::sessions::Device> device_struct(new api::sessions::Device);
|
| + device_struct->info = session->session_name;
|
| +
|
| + for (browser_sync::SyncedSession::SyncedWindowMap::const_iterator it =
|
| + session->windows.begin(); it != session->windows.end() &&
|
| + static_cast<int>(device_struct->sessions.size()) < max_results; ++it) {
|
| + scoped_ptr<api::sessions::Session> session_model(CreateSessionModel(
|
| + *it->second, session->session_tag));
|
| + if (session_model)
|
| + device_struct->sessions.push_back(make_linked_ptr(
|
| + session_model.release()));
|
| + }
|
| + return device_struct.Pass();
|
| +}
|
| +
|
| +bool SessionsGetDevicesFunction::RunImpl() {
|
| + ProfileSyncService* service =
|
| + ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile());
|
| + if (!(service && service->GetPreferredDataTypes().Has(syncer::SESSIONS))) {
|
| + // Sync not enabled.
|
| + results_ = GetDevices::Results::Create(
|
| + std::vector<linked_ptr<api::sessions::Device> >());
|
| + return true;
|
| + }
|
| +
|
| + browser_sync::SessionModelAssociator* associator =
|
| + service->GetSessionModelAssociator();
|
| + std::vector<const browser_sync::SyncedSession*> sessions;
|
| + if (!(associator && associator->GetAllForeignSessions(&sessions))) {
|
| + results_ = GetDevices::Results::Create(
|
| + std::vector<linked_ptr<api::sessions::Device> >());
|
| + return true;
|
| + }
|
| +
|
| + std::vector<linked_ptr<api::sessions::Device> > result;
|
| + // Sort sessions from most recent to least recent.
|
| + std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency);
|
| + for (size_t i = 0; i < sessions.size(); ++i) {
|
| + result.push_back(make_linked_ptr(CreateDeviceModel(sessions[i]).release()));
|
| + }
|
| +
|
| + results_ = GetDevices::Results::Create(result);
|
| + return true;
|
| +}
|
| +
|
| +void SessionsRestoreFunction::SetInvalidIdError(const std::string& invalid_id) {
|
| + SetError(ErrorUtils::FormatErrorMessage(kInvalidSessionIdError, invalid_id));
|
| +}
|
| +
|
| +
|
| +void SessionsRestoreFunction::SetResultRestoredTab(
|
| + const content::WebContents* contents) {
|
| + scoped_ptr<tabs::Tab> tab(tabs::Tab::FromValue(
|
| + *ExtensionTabUtil::CreateTabValue(contents, GetExtension())));
|
| + scoped_ptr<api::sessions::Session> restored_session(CreateSessionModelHelper(
|
| + base::Time::Now().ToTimeT(),
|
| + tab.Pass(),
|
| + scoped_ptr<windows::Window>()));
|
| + results_ = Restore::Results::Create(*restored_session);
|
| +}
|
| +
|
| +bool SessionsRestoreFunction::SetResultRestoredWindow(int window_id) {
|
| + WindowController* controller = NULL;
|
| + if (!windows_util::GetWindowFromWindowID(this, window_id, &controller)) {
|
| + // error_ is set by GetWindowFromWindowId function call.
|
| return false;
|
| }
|
| + scoped_ptr<windows::Window> window(windows::Window::FromValue(
|
| + *controller->CreateWindowValueWithTabs(GetExtension())));
|
| + results_ = Restore::Results::Create(*CreateSessionModelHelper(
|
| + base::Time::Now().ToTimeT(),
|
| + scoped_ptr<tabs::Tab>(),
|
| + window.Pass()));
|
| + return true;
|
| +}
|
|
|
| +bool SessionsRestoreFunction::RestoreMostRecentlyClosed(Browser* browser) {
|
| TabRestoreService* tab_restore_service =
|
| TabRestoreServiceFactory::GetForProfile(profile());
|
| + chrome::HostDesktopType host_desktop_type = browser->host_desktop_type();
|
| + TabRestoreService::Entries entries = tab_restore_service->entries();
|
| +
|
| + if (entries.empty()) {
|
| + SetError(kNoRecentlyClosedSessionsError);
|
| + return false;
|
| + }
|
| +
|
| + bool is_window = is_window_entry(entries.front());
|
| TabRestoreServiceDelegate* delegate =
|
| TabRestoreServiceDelegate::FindDelegateForWebContents(
|
| browser->tab_strip_model()->GetActiveWebContents());
|
| - DCHECK(delegate);
|
| + std::vector<content::WebContents*> contents =
|
| + tab_restore_service->RestoreMostRecentEntry(delegate, host_desktop_type);
|
| + DCHECK(contents.size());
|
| +
|
| + if (is_window) {
|
| + return SetResultRestoredWindow(
|
| + ExtensionTabUtil::GetWindowIdOfTab(contents[0]));
|
| + }
|
| +
|
| + SetResultRestoredTab(contents[0]);
|
| + return true;
|
| +}
|
| +
|
| +bool SessionsRestoreFunction::RestoreLocalSession(const SessionId& session_id,
|
| + Browser* browser) {
|
| + TabRestoreService* tab_restore_service =
|
| + TabRestoreServiceFactory::GetForProfile(profile());
|
| chrome::HostDesktopType host_desktop_type = browser->host_desktop_type();
|
| TabRestoreService::Entries entries = tab_restore_service->entries();
|
|
|
| if (entries.empty()) {
|
| - error_ = kRecentlyClosedListEmpty;
|
| + SetInvalidIdError(session_id.ToString());
|
| return false;
|
| }
|
|
|
| - if (!params->id) {
|
| - tab_restore_service->RestoreMostRecentEntry(delegate, host_desktop_type);
|
| - return true;
|
| - }
|
| -
|
| // Check if the recently closed list contains an entry with the provided id.
|
| - bool is_valid_id = false;
|
| + bool is_window = false;
|
| for (TabRestoreService::Entries::iterator it = entries.begin();
|
| it != entries.end(); ++it) {
|
| - if ((*it)->id == *params->id) {
|
| - is_valid_id = true;
|
| + if ((*it)->id == session_id.id()) {
|
| + // The only time a full window is being restored is if the entry ID
|
| + // matches the provided ID and the entry type is Window.
|
| + is_window = is_window_entry(*it);
|
| break;
|
| }
|
| -
|
| - // For Window entries, see if the ID matches a tab. If so, report true for
|
| - // the window as the Entry.
|
| - if ((*it)->type == TabRestoreService::WINDOW) {
|
| - std::vector<TabRestoreService::Tab>& tabs =
|
| - static_cast<TabRestoreService::Window*>(*it)->tabs;
|
| - for (std::vector<TabRestoreService::Tab>::iterator tab_it = tabs.begin();
|
| - tab_it != tabs.end(); ++tab_it) {
|
| - if ((*tab_it).id == *params->id) {
|
| - is_valid_id = true;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| }
|
|
|
| - if (!is_valid_id) {
|
| - error_ = kInvalidSessionId;
|
| + TabRestoreServiceDelegate* delegate =
|
| + TabRestoreServiceDelegate::FindDelegateForWebContents(
|
| + browser->tab_strip_model()->GetActiveWebContents());
|
| + std::vector<content::WebContents*> contents =
|
| + tab_restore_service->RestoreEntryById(delegate,
|
| + session_id.id(),
|
| + host_desktop_type,
|
| + UNKNOWN);
|
| + // If the ID is invalid, contents will be empty.
|
| + if (!contents.size()) {
|
| + SetInvalidIdError(session_id.ToString());
|
| return false;
|
| }
|
|
|
| - tab_restore_service->RestoreEntryById(delegate, *params->id,
|
| - host_desktop_type, UNKNOWN);
|
| + // Retrieve the window through any of the tabs in contents.
|
| + if (is_window) {
|
| + return SetResultRestoredWindow(
|
| + ExtensionTabUtil::GetWindowIdOfTab(contents[0]));
|
| + }
|
| +
|
| + SetResultRestoredTab(contents[0]);
|
| return true;
|
| }
|
|
|
| -SessionRestoreAPI::SessionRestoreAPI(Profile* profile) {
|
| +bool SessionsRestoreFunction::RestoreForeignSession(const SessionId& session_id,
|
| + Browser* browser) {
|
| + ProfileSyncService* service =
|
| + ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile());
|
| + if (!(service && service->GetPreferredDataTypes().Has(syncer::SESSIONS))) {
|
| + SetError(kSessionSyncError);
|
| + return false;
|
| + }
|
| + browser_sync::SessionModelAssociator* associator =
|
| + service->GetSessionModelAssociator();
|
| + if (!associator) {
|
| + SetError(kSessionSyncError);
|
| + return false;
|
| + }
|
| +
|
| + const SessionTab* tab = NULL;
|
| + if (associator->GetForeignTab(session_id.session_tag(),
|
| + session_id.id(),
|
| + &tab)) {
|
| + TabStripModel* tab_strip = browser->tab_strip_model();
|
| + content::WebContents* contents = tab_strip->GetActiveWebContents();
|
| +
|
| + content::WebContents* tab_contents =
|
| + SessionRestore::RestoreForeignSessionTab(contents, *tab,
|
| + NEW_FOREGROUND_TAB);
|
| + SetResultRestoredTab(tab_contents);
|
| + return true;
|
| + }
|
| +
|
| + // Restoring a full window.
|
| + std::vector<const SessionWindow*> windows;
|
| + if (!associator->GetForeignSession(session_id.session_tag(), &windows)) {
|
| + SetInvalidIdError(session_id.ToString());
|
| + return false;
|
| + }
|
| +
|
| + std::vector<const SessionWindow*>::const_iterator window = windows.begin();
|
| + while (window != windows.end()
|
| + && (*window)->window_id.id() != session_id.id()) {
|
| + ++window;
|
| + }
|
| + if (window == windows.end()) {
|
| + SetInvalidIdError(session_id.ToString());
|
| + return false;
|
| + }
|
| +
|
| + chrome::HostDesktopType host_desktop_type = browser->host_desktop_type();
|
| + // Only restore one window at a time.
|
| + std::vector<Browser*> browsers =
|
| + SessionRestore::RestoreForeignSessionWindows(profile(), host_desktop_type,
|
| + window, window + 1);
|
| + // Will always create one browser because we only restore one window per call.
|
| + DCHECK_EQ(1u, browsers.size());
|
| + return SetResultRestoredWindow(ExtensionTabUtil::GetWindowId(browsers[0]));
|
| +}
|
| +
|
| +bool SessionsRestoreFunction::RunImpl() {
|
| + scoped_ptr<Restore::Params> params(Restore::Params::Create(*args_));
|
| + EXTENSION_FUNCTION_VALIDATE(params);
|
| +
|
| + Browser* browser =
|
| + chrome::FindBrowserWithProfile(profile(),
|
| + chrome::HOST_DESKTOP_TYPE_NATIVE);
|
| + if (!browser) {
|
| + SetError(kNoBrowserToRestoreSession);
|
| + return false;
|
| + }
|
| +
|
| + if (!params->session_id)
|
| + return RestoreMostRecentlyClosed(browser);
|
| +
|
| + scoped_ptr<SessionId> session_id(SessionId::Parse(*params->session_id));
|
| + if (!session_id) {
|
| + SetInvalidIdError(*params->session_id);
|
| + return false;
|
| + }
|
| +
|
| + return session_id->IsForeign() ?
|
| + RestoreForeignSession(*session_id, browser)
|
| + : RestoreLocalSession(*session_id, browser);
|
| +}
|
| +
|
| +SessionsAPI::SessionsAPI(Profile* profile) {
|
| }
|
|
|
| -SessionRestoreAPI::~SessionRestoreAPI() {
|
| +SessionsAPI::~SessionsAPI() {
|
| }
|
|
|
| -static base::LazyInstance<ProfileKeyedAPIFactory<SessionRestoreAPI> >
|
| +static base::LazyInstance<ProfileKeyedAPIFactory<SessionsAPI> >
|
| g_factory = LAZY_INSTANCE_INITIALIZER;
|
|
|
| // static
|
| -ProfileKeyedAPIFactory<SessionRestoreAPI>*
|
| - SessionRestoreAPI::GetFactoryInstance() {
|
| +ProfileKeyedAPIFactory<SessionsAPI>*
|
| + SessionsAPI::GetFactoryInstance() {
|
| return &g_factory.Get();
|
| }
|
|
|
|
|