[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 1 | // Copyright 2013 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/sessions/sessions_api.h" |
| 6 | |
avi | a2f4804a | 2015-12-24 23:11:13 | [diff] [blame] | 7 | #include <stddef.h> |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 8 | |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 9 | #include <utility> |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 10 | #include <vector> |
| 11 | |
| 12 | #include "base/i18n/rtl.h" |
| 13 | #include "base/lazy_instance.h" |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 14 | #include "base/memory/ptr_util.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 15 | #include "base/strings/string_number_conversions.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 16 | #include "base/strings/utf_string_conversions.h" |
| 17 | #include "base/time/time.h" |
| 18 | #include "chrome/browser/extensions/api/sessions/session_id.h" |
| 19 | #include "chrome/browser/extensions/api/tabs/windows_util.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 20 | #include "chrome/browser/extensions/extension_tab_util.h" |
| 21 | #include "chrome/browser/extensions/window_controller.h" |
| 22 | #include "chrome/browser/extensions/window_controller_list.h" |
| 23 | #include "chrome/browser/profiles/profile.h" |
| 24 | #include "chrome/browser/search/search.h" |
| 25 | #include "chrome/browser/sessions/session_restore.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 26 | #include "chrome/browser/sessions/tab_restore_service_factory.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 27 | #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 28 | #include "chrome/browser/ui/browser.h" |
| 29 | #include "chrome/browser/ui/browser_finder.h" |
blundell | bde024d | 2015-09-30 13:47:07 | [diff] [blame] | 30 | #include "chrome/browser/ui/browser_live_tab_context.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 31 | #include "chrome/browser/ui/tabs/tab_strip_model.h" |
maxbogue | 26f4022 | 2016-09-16 20:22:18 | [diff] [blame] | 32 | #include "components/browser_sync/profile_sync_service.h" |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 33 | #include "components/sessions/content/content_live_tab.h" |
maxbogue | 8ef2508 | 2015-11-16 19:09:58 | [diff] [blame] | 34 | #include "components/sync_sessions/open_tabs_ui_delegate.h" |
| 35 | #include "components/sync_sessions/synced_session.h" |
rsleevi | 24f64dc2 | 2015-08-07 21:39:21 | [diff] [blame] | 36 | #include "components/url_formatter/url_formatter.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 37 | #include "content/public/browser/web_contents.h" |
[email protected] | 0b9de03 | 2014-03-15 05:47:01 | [diff] [blame] | 38 | #include "extensions/browser/extension_function_dispatcher.h" |
[email protected] | 21c6c43 | 2014-03-05 18:47:31 | [diff] [blame] | 39 | #include "extensions/browser/extension_function_registry.h" |
[email protected] | 38f9258 | 2014-03-30 20:48:55 | [diff] [blame] | 40 | #include "extensions/browser/extension_system.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 41 | #include "extensions/common/error_utils.h" |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 42 | #include "ui/base/layout.h" |
| 43 | |
| 44 | namespace extensions { |
| 45 | |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 46 | namespace { |
| 47 | |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 48 | namespace GetRecentlyClosed = api::sessions::GetRecentlyClosed; |
| 49 | namespace GetDevices = api::sessions::GetDevices; |
| 50 | namespace Restore = api::sessions::Restore; |
| 51 | namespace tabs = api::tabs; |
| 52 | namespace windows = api::windows; |
| 53 | |
| 54 | const char kNoRecentlyClosedSessionsError[] = |
| 55 | "There are no recently closed sessions."; |
| 56 | const char kInvalidSessionIdError[] = "Invalid session id: \"*\"."; |
| 57 | const char kNoBrowserToRestoreSession[] = |
| 58 | "There are no browser windows to restore the session."; |
| 59 | const char kSessionSyncError[] = "Synced sessions are not available."; |
[email protected] | ecf51988 | 2014-03-21 15:49:52 | [diff] [blame] | 60 | const char kRestoreInIncognitoError[] = |
| 61 | "Can not restore sessions in incognito mode."; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 62 | |
| 63 | // Comparator function for use with std::sort that will sort sessions by |
| 64 | // descending modified_time (i.e., most recent first). |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 65 | bool SortSessionsByRecency(const sync_sessions::SyncedSession* s1, |
| 66 | const sync_sessions::SyncedSession* s2) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 67 | return s1->modified_time > s2->modified_time; |
| 68 | } |
| 69 | |
| 70 | // Comparator function for use with std::sort that will sort tabs in a window |
| 71 | // by descending timestamp (i.e., most recent first). |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 72 | bool SortTabsByRecency(const sessions::SessionTab* t1, |
| 73 | const sessions::SessionTab* t2) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 74 | return t1->timestamp > t2->timestamp; |
| 75 | } |
| 76 | |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 77 | tabs::Tab CreateTabModelHelper( |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 78 | const sessions::SerializedNavigationEntry& current_navigation, |
| 79 | const std::string& session_id, |
| 80 | int index, |
| 81 | bool pinned, |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 82 | bool active, |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 83 | const Extension* extension) { |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 84 | tabs::Tab tab_struct; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 85 | |
kalman | 4399163f | 2014-10-23 20:34:58 | [diff] [blame] | 86 | const GURL& url = current_navigation.virtual_url(); |
[email protected] | 0433872 | 2013-12-24 23:18:05 | [diff] [blame] | 87 | std::string title = base::UTF16ToUTF8(current_navigation.title()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 88 | |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 89 | tab_struct.session_id.reset(new std::string(session_id)); |
| 90 | tab_struct.url.reset(new std::string(url.spec())); |
| 91 | tab_struct.fav_icon_url.reset( |
kalman | 4399163f | 2014-10-23 20:34:58 | [diff] [blame] | 92 | new std::string(current_navigation.favicon_url().spec())); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 93 | if (!title.empty()) { |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 94 | tab_struct.title.reset(new std::string(title)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 95 | } else { |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 96 | tab_struct.title.reset(new std::string( |
jshin | 1fb7646 | 2016-04-05 22:13:03 | [diff] [blame] | 97 | base::UTF16ToUTF8(url_formatter::FormatUrl(url)))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 98 | } |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 99 | tab_struct.index = index; |
| 100 | tab_struct.pinned = pinned; |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 101 | tab_struct.active = active; |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 102 | ExtensionTabUtil::ScrubTabForExtension(extension, nullptr, &tab_struct); |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 103 | return tab_struct; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 104 | } |
| 105 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 106 | std::unique_ptr<windows::Window> CreateWindowModelHelper( |
| 107 | std::unique_ptr<std::vector<tabs::Tab>> tabs, |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 108 | const std::string& session_id, |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 109 | const windows::WindowType& type, |
| 110 | const windows::WindowState& state) { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 111 | std::unique_ptr<windows::Window> window_struct(new windows::Window); |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 112 | window_struct->tabs = std::move(tabs); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 113 | window_struct->session_id.reset(new std::string(session_id)); |
| 114 | window_struct->incognito = false; |
| 115 | window_struct->always_on_top = false; |
| 116 | window_struct->focused = false; |
| 117 | window_struct->type = type; |
| 118 | window_struct->state = state; |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 119 | return window_struct; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 120 | } |
| 121 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 122 | std::unique_ptr<api::sessions::Session> CreateSessionModelHelper( |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 123 | int last_modified, |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 124 | std::unique_ptr<tabs::Tab> tab, |
| 125 | std::unique_ptr<windows::Window> window) { |
| 126 | std::unique_ptr<api::sessions::Session> session_struct( |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 127 | new api::sessions::Session()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 128 | session_struct->last_modified = last_modified; |
| 129 | if (tab) |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 130 | session_struct->tab = std::move(tab); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 131 | else if (window) |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 132 | session_struct->window = std::move(window); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 133 | else |
| 134 | NOTREACHED(); |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 135 | return session_struct; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 136 | } |
| 137 | |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 138 | bool is_window_entry(const sessions::TabRestoreService::Entry& entry) { |
| 139 | return entry.type == sessions::TabRestoreService::WINDOW; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 140 | } |
| 141 | |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 142 | } // namespace |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 143 | |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 144 | tabs::Tab SessionsGetRecentlyClosedFunction::CreateTabModel( |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 145 | const sessions::TabRestoreService::Tab& tab, |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 146 | bool active) { |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 147 | return CreateTabModelHelper(tab.navigations[tab.current_navigation_index], |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 148 | base::IntToString(tab.id), tab.tabstrip_index, |
| 149 | tab.pinned, active, extension()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 150 | } |
| 151 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 152 | std::unique_ptr<windows::Window> |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 153 | SessionsGetRecentlyClosedFunction::CreateWindowModel( |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 154 | const sessions::TabRestoreService::Window& window) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 155 | DCHECK(!window.tabs.empty()); |
| 156 | |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 157 | auto tabs = base::MakeUnique<std::vector<tabs::Tab>>(); |
| 158 | for (const auto& tab : window.tabs) |
| 159 | tabs->push_back( |
| 160 | CreateTabModel(*tab, tab->tabstrip_index == window.selected_tab_index)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 161 | |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 162 | return CreateWindowModelHelper(std::move(tabs), base::IntToString(window.id), |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 163 | windows::WINDOW_TYPE_NORMAL, |
| 164 | windows::WINDOW_STATE_NORMAL); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 165 | } |
| 166 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 167 | std::unique_ptr<api::sessions::Session> |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 168 | SessionsGetRecentlyClosedFunction::CreateSessionModel( |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 169 | const sessions::TabRestoreService::Entry& entry) { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 170 | std::unique_ptr<tabs::Tab> tab; |
| 171 | std::unique_ptr<windows::Window> window; |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 172 | switch (entry.type) { |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 173 | case sessions::TabRestoreService::TAB: |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 174 | tab.reset(new tabs::Tab(CreateTabModel( |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 175 | static_cast<const sessions::TabRestoreService::Tab&>(entry), false))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 176 | break; |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 177 | case sessions::TabRestoreService::WINDOW: |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 178 | window = CreateWindowModel( |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 179 | static_cast<const sessions::TabRestoreService::Window&>(entry)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 180 | break; |
| 181 | default: |
| 182 | NOTREACHED(); |
| 183 | } |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 184 | return CreateSessionModelHelper(entry.timestamp.ToTimeT(), std::move(tab), |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 185 | std::move(window)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 186 | } |
| 187 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 188 | ExtensionFunction::ResponseAction SessionsGetRecentlyClosedFunction::Run() { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 189 | std::unique_ptr<GetRecentlyClosed::Params> params( |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 190 | GetRecentlyClosed::Params::Create(*args_)); |
| 191 | EXTENSION_FUNCTION_VALIDATE(params); |
| 192 | int max_results = api::sessions::MAX_SESSION_RESULTS; |
| 193 | if (params->filter && params->filter->max_results) |
| 194 | max_results = *params->filter->max_results; |
| 195 | EXTENSION_FUNCTION_VALIDATE(max_results >= 0 && |
| 196 | max_results <= api::sessions::MAX_SESSION_RESULTS); |
| 197 | |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 198 | std::vector<api::sessions::Session> result; |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 199 | sessions::TabRestoreService* tab_restore_service = |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 200 | TabRestoreServiceFactory::GetForProfile( |
| 201 | Profile::FromBrowserContext(browser_context())); |
[email protected] | b3e0f85c | 2014-03-22 04:58:00 | [diff] [blame] | 202 | |
| 203 | // TabRestoreServiceFactory::GetForProfile() can return NULL (i.e., when in |
| 204 | // incognito mode) |
| 205 | if (!tab_restore_service) { |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 206 | DCHECK(browser_context()->IsOffTheRecord()) |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 207 | << "sessions::TabRestoreService expected for normal profiles"; |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 208 | return RespondNow(ArgumentList(GetRecentlyClosed::Results::Create(result))); |
[email protected] | b3e0f85c | 2014-03-22 04:58:00 | [diff] [blame] | 209 | } |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 210 | |
| 211 | // List of entries. They are ordered from most to least recent. |
| 212 | // We prune the list to contain max 25 entries at any time and removes |
| 213 | // uninteresting entries. |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 214 | for (const auto& entry : tab_restore_service->entries()) { |
| 215 | result.push_back(std::move(*CreateSessionModel(*entry))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 216 | } |
| 217 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 218 | return RespondNow(ArgumentList(GetRecentlyClosed::Results::Create(result))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 219 | } |
| 220 | |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 221 | tabs::Tab SessionsGetDevicesFunction::CreateTabModel( |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 222 | const std::string& session_tag, |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 223 | const sessions::SessionTab& tab, |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 224 | int tab_index, |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 225 | bool active) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 226 | std::string session_id = SessionId(session_tag, tab.tab_id.id()).ToString(); |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 227 | return CreateTabModelHelper( |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 228 | tab.navigations[tab.normalized_navigation_index()], session_id, tab_index, |
| 229 | tab.pinned, active, extension()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 230 | } |
| 231 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 232 | std::unique_ptr<windows::Window> SessionsGetDevicesFunction::CreateWindowModel( |
| 233 | const sessions::SessionWindow& window, |
| 234 | const std::string& session_tag) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 235 | DCHECK(!window.tabs.empty()); |
| 236 | |
| 237 | // Prune tabs that are not syncable or are NewTabPage. Then, sort the tabs |
| 238 | // from most recent to least recent. |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 239 | std::vector<const sessions::SessionTab*> tabs_in_window; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 240 | for (size_t i = 0; i < window.tabs.size(); ++i) { |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 241 | const sessions::SessionTab* tab = window.tabs[i].get(); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 242 | if (tab->navigations.empty()) |
| 243 | continue; |
| 244 | const sessions::SerializedNavigationEntry& current_navigation = |
| 245 | tab->navigations.at(tab->normalized_navigation_index()); |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 246 | if (search::IsNTPURL(current_navigation.virtual_url(), |
| 247 | Profile::FromBrowserContext(browser_context()))) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 248 | continue; |
| 249 | } |
| 250 | tabs_in_window.push_back(tab); |
| 251 | } |
| 252 | if (tabs_in_window.empty()) |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 253 | return std::unique_ptr<windows::Window>(); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 254 | std::sort(tabs_in_window.begin(), tabs_in_window.end(), SortTabsByRecency); |
| 255 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 256 | std::unique_ptr<std::vector<tabs::Tab>> tabs(new std::vector<tabs::Tab>()); |
[email protected] | ddd5435 | 2014-04-05 07:43:30 | [diff] [blame] | 257 | for (size_t i = 0; i < tabs_in_window.size(); ++i) { |
rdevlin.cronin | 372cf1d5 | 2016-03-30 22:46:17 | [diff] [blame] | 258 | tabs->push_back(CreateTabModel(session_tag, *tabs_in_window[i], i, |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 259 | window.selected_tab_index == (int)i)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | std::string session_id = |
| 263 | SessionId(session_tag, window.window_id.id()).ToString(); |
| 264 | |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 265 | windows::WindowType type = windows::WINDOW_TYPE_NONE; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 266 | switch (window.type) { |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 267 | case sessions::SessionWindow::TYPE_TABBED: |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 268 | type = windows::WINDOW_TYPE_NORMAL; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 269 | break; |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 270 | case sessions::SessionWindow::TYPE_POPUP: |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 271 | type = windows::WINDOW_TYPE_POPUP; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 272 | break; |
| 273 | } |
| 274 | |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 275 | windows::WindowState state = windows::WINDOW_STATE_NONE; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 276 | switch (window.show_state) { |
| 277 | case ui::SHOW_STATE_NORMAL: |
afakhry | 25a6b95 | 2017-01-27 20:36:50 | [diff] [blame] | 278 | |
| 279 | // TODO(afakhry): Remove Docked Windows in M58. |
varkha | 74014e0e | 2015-05-05 18:12:31 | [diff] [blame] | 280 | case ui::SHOW_STATE_DOCKED: |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 281 | state = windows::WINDOW_STATE_NORMAL; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 282 | break; |
| 283 | case ui::SHOW_STATE_MINIMIZED: |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 284 | state = windows::WINDOW_STATE_MINIMIZED; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 285 | break; |
| 286 | case ui::SHOW_STATE_MAXIMIZED: |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 287 | state = windows::WINDOW_STATE_MAXIMIZED; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 288 | break; |
| 289 | case ui::SHOW_STATE_FULLSCREEN: |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame] | 290 | state = windows::WINDOW_STATE_FULLSCREEN; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 291 | break; |
| 292 | case ui::SHOW_STATE_DEFAULT: |
| 293 | case ui::SHOW_STATE_INACTIVE: |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 294 | case ui::SHOW_STATE_END: |
| 295 | break; |
| 296 | } |
| 297 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 298 | std::unique_ptr<windows::Window> window_struct( |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 299 | CreateWindowModelHelper(std::move(tabs), session_id, type, state)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 300 | // TODO(dwankri): Dig deeper to resolve bounds not being optional, so closed |
| 301 | // windows in GetRecentlyClosed can have set values in Window helper. |
| 302 | window_struct->left.reset(new int(window.bounds.x())); |
| 303 | window_struct->top.reset(new int(window.bounds.y())); |
| 304 | window_struct->width.reset(new int(window.bounds.width())); |
| 305 | window_struct->height.reset(new int(window.bounds.height())); |
| 306 | |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 307 | return window_struct; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 308 | } |
| 309 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 310 | std::unique_ptr<api::sessions::Session> |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 311 | SessionsGetDevicesFunction::CreateSessionModel( |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 312 | const sessions::SessionWindow& window, |
| 313 | const std::string& session_tag) { |
| 314 | std::unique_ptr<windows::Window> window_model( |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 315 | CreateWindowModel(window, session_tag)); |
| 316 | // There is a chance that after pruning uninteresting tabs the window will be |
| 317 | // empty. |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 318 | return !window_model ? std::unique_ptr<api::sessions::Session>() |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 319 | : CreateSessionModelHelper(window.timestamp.ToTimeT(), |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 320 | std::unique_ptr<tabs::Tab>(), |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 321 | std::move(window_model)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 322 | } |
| 323 | |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 324 | api::sessions::Device SessionsGetDevicesFunction::CreateDeviceModel( |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 325 | const sync_sessions::SyncedSession* session) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 326 | int max_results = api::sessions::MAX_SESSION_RESULTS; |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 327 | // Already validated in RunAsync(). |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 328 | std::unique_ptr<GetDevices::Params> params( |
| 329 | GetDevices::Params::Create(*args_)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 330 | if (params->filter && params->filter->max_results) |
| 331 | max_results = *params->filter->max_results; |
| 332 | |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 333 | api::sessions::Device device_struct; |
| 334 | device_struct.info = session->session_name; |
| 335 | device_struct.device_name = session->session_name; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 336 | |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 337 | for (auto it = session->windows.begin(); |
droger | 6a11863 | 2015-06-23 17:59:45 | [diff] [blame] | 338 | it != session->windows.end() && |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 339 | static_cast<int>(device_struct.sessions.size()) < max_results; |
droger | 6a11863 | 2015-06-23 17:59:45 | [diff] [blame] | 340 | ++it) { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 341 | std::unique_ptr<api::sessions::Session> session_model( |
| 342 | CreateSessionModel(*it->second, session->session_tag)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 343 | if (session_model) |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 344 | device_struct.sessions.push_back(std::move(*session_model)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 345 | } |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 346 | return device_struct; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 347 | } |
| 348 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 349 | ExtensionFunction::ResponseAction SessionsGetDevicesFunction::Run() { |
maxbogue | 0a37945 | 2016-09-22 21:35:05 | [diff] [blame] | 350 | browser_sync::ProfileSyncService* service = |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 351 | ProfileSyncServiceFactory::GetInstance()->GetForProfile( |
| 352 | Profile::FromBrowserContext(browser_context())); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 353 | if (!(service && service->GetPreferredDataTypes().Has(syncer::SESSIONS))) { |
| 354 | // Sync not enabled. |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 355 | return RespondNow(ArgumentList( |
| 356 | GetDevices::Results::Create(std::vector<api::sessions::Device>()))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 357 | } |
| 358 | |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 359 | sync_sessions::OpenTabsUIDelegate* open_tabs = |
| 360 | service->GetOpenTabsUIDelegate(); |
| 361 | std::vector<const sync_sessions::SyncedSession*> sessions; |
[email protected] | a9f5662 | 2013-11-21 19:37:06 | [diff] [blame] | 362 | if (!(open_tabs && open_tabs->GetAllForeignSessions(&sessions))) { |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 363 | return RespondNow(ArgumentList( |
| 364 | GetDevices::Results::Create(std::vector<api::sessions::Device>()))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 365 | } |
| 366 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 367 | std::unique_ptr<GetDevices::Params> params( |
| 368 | GetDevices::Params::Create(*args_)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 369 | EXTENSION_FUNCTION_VALIDATE(params); |
| 370 | if (params->filter && params->filter->max_results) { |
| 371 | EXTENSION_FUNCTION_VALIDATE(*params->filter->max_results >= 0 && |
| 372 | *params->filter->max_results <= api::sessions::MAX_SESSION_RESULTS); |
| 373 | } |
| 374 | |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 375 | std::vector<api::sessions::Device> result; |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 376 | // Sort sessions from most recent to least recent. |
| 377 | std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency); |
rdevlin.cronin | 2e624f8 | 2016-03-29 00:15:03 | [diff] [blame] | 378 | for (size_t i = 0; i < sessions.size(); ++i) |
| 379 | result.push_back(CreateDeviceModel(sessions[i])); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 380 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 381 | return RespondNow(ArgumentList(GetDevices::Results::Create(result))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 382 | } |
| 383 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 384 | ExtensionFunction::ResponseValue SessionsRestoreFunction::GetRestoredTabResult( |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 385 | content::WebContents* contents) { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 386 | std::unique_ptr<tabs::Tab> tab( |
limasdf | 6dcdc44 | 2016-02-26 04:58:26 | [diff] [blame] | 387 | ExtensionTabUtil::CreateTabObject(contents, extension())); |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 388 | std::unique_ptr<api::sessions::Session> restored_session( |
dcheng | 1fc00f1 | 2015-12-26 22:18:03 | [diff] [blame] | 389 | CreateSessionModelHelper(base::Time::Now().ToTimeT(), std::move(tab), |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 390 | std::unique_ptr<windows::Window>())); |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 391 | return ArgumentList(Restore::Results::Create(*restored_session)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 392 | } |
| 393 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 394 | ExtensionFunction::ResponseValue |
| 395 | SessionsRestoreFunction::GetRestoredWindowResult(int window_id) { |
[email protected] | d6da113 | 2013-11-07 17:56:21 | [diff] [blame] | 396 | WindowController* controller = NULL; |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 397 | std::string error; |
rdevlin.cronin | fd7bb62 | 2016-10-03 23:14:46 | [diff] [blame] | 398 | if (!windows_util::GetWindowFromWindowID(this, window_id, 0, &controller, |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 399 | &error)) { |
| 400 | return Error(error); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 401 | } |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 402 | std::unique_ptr<base::DictionaryValue> window_value( |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 403 | controller->CreateWindowValueWithTabs(extension())); |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 404 | std::unique_ptr<windows::Window> window( |
| 405 | windows::Window::FromValue(*window_value)); |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 406 | return ArgumentList(Restore::Results::Create(*CreateSessionModelHelper( |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 407 | base::Time::Now().ToTimeT(), std::unique_ptr<tabs::Tab>(), |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 408 | std::move(window)))); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 409 | } |
| 410 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 411 | ExtensionFunction::ResponseValue |
| 412 | SessionsRestoreFunction::RestoreMostRecentlyClosed(Browser* browser) { |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 413 | sessions::TabRestoreService* tab_restore_service = |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 414 | TabRestoreServiceFactory::GetForProfile( |
| 415 | Profile::FromBrowserContext(browser_context())); |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 416 | const sessions::TabRestoreService::Entries& entries = |
| 417 | tab_restore_service->entries(); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 418 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 419 | if (entries.empty()) |
| 420 | return Error(kNoRecentlyClosedSessionsError); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 421 | |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 422 | bool is_window = is_window_entry(*entries.front()); |
blundell | bde024d | 2015-09-30 13:47:07 | [diff] [blame] | 423 | sessions::LiveTabContext* context = |
| 424 | BrowserLiveTabContext::FindContextForWebContents( |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 425 | browser->tab_strip_model()->GetActiveWebContents()); |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 426 | std::vector<sessions::LiveTab*> restored_tabs = |
scottmg | d161e6c | 2016-02-17 02:08:01 | [diff] [blame] | 427 | tab_restore_service->RestoreMostRecentEntry(context); |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 428 | DCHECK(restored_tabs.size()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 429 | |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 430 | sessions::ContentLiveTab* first_tab = |
| 431 | static_cast<sessions::ContentLiveTab*>(restored_tabs[0]); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 432 | if (is_window) { |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 433 | return GetRestoredWindowResult( |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 434 | ExtensionTabUtil::GetWindowIdOfTab(first_tab->web_contents())); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 435 | } |
| 436 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 437 | return GetRestoredTabResult(first_tab->web_contents()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 438 | } |
| 439 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 440 | ExtensionFunction::ResponseValue SessionsRestoreFunction::RestoreLocalSession( |
| 441 | const SessionId& session_id, |
| 442 | Browser* browser) { |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 443 | sessions::TabRestoreService* tab_restore_service = |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 444 | TabRestoreServiceFactory::GetForProfile( |
| 445 | Profile::FromBrowserContext(browser_context())); |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 446 | const sessions::TabRestoreService::Entries& entries = |
| 447 | tab_restore_service->entries(); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 448 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 449 | if (entries.empty()) |
| 450 | return Error(kInvalidSessionIdError, session_id.ToString()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 451 | |
| 452 | // Check if the recently closed list contains an entry with the provided id. |
| 453 | bool is_window = false; |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 454 | for (const auto& entry : entries) { |
| 455 | if (entry->id == session_id.id()) { |
| 456 | // A full window is being restored only if the entry ID |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 457 | // matches the provided ID and the entry type is Window. |
sdy | 7710d22c | 2016-08-09 14:04:34 | [diff] [blame] | 458 | is_window = is_window_entry(*entry); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 459 | break; |
| 460 | } |
| 461 | } |
| 462 | |
blundell | bde024d | 2015-09-30 13:47:07 | [diff] [blame] | 463 | sessions::LiveTabContext* context = |
| 464 | BrowserLiveTabContext::FindContextForWebContents( |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 465 | browser->tab_strip_model()->GetActiveWebContents()); |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 466 | std::vector<sessions::LiveTab*> restored_tabs = |
nick | 3b04f32 | 2016-08-31 19:29:19 | [diff] [blame] | 467 | tab_restore_service->RestoreEntryById(context, session_id.id(), |
| 468 | WindowOpenDisposition::UNKNOWN); |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 469 | // If the ID is invalid, restored_tabs will be empty. |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 470 | if (restored_tabs.empty()) |
| 471 | return Error(kInvalidSessionIdError, session_id.ToString()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 472 | |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 473 | sessions::ContentLiveTab* first_tab = |
| 474 | static_cast<sessions::ContentLiveTab*>(restored_tabs[0]); |
| 475 | |
| 476 | // Retrieve the window through any of the tabs in restored_tabs. |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 477 | if (is_window) { |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 478 | return GetRestoredWindowResult( |
blundell | 80c5b2a0 | 2015-09-17 18:22:12 | [diff] [blame] | 479 | ExtensionTabUtil::GetWindowIdOfTab(first_tab->web_contents())); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 480 | } |
| 481 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 482 | return GetRestoredTabResult(first_tab->web_contents()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 483 | } |
| 484 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 485 | ExtensionFunction::ResponseValue SessionsRestoreFunction::RestoreForeignSession( |
| 486 | const SessionId& session_id, |
| 487 | Browser* browser) { |
| 488 | Profile* profile = Profile::FromBrowserContext(browser_context()); |
maxbogue | 0a37945 | 2016-09-22 21:35:05 | [diff] [blame] | 489 | browser_sync::ProfileSyncService* service = |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 490 | ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); |
| 491 | if (!(service && service->GetPreferredDataTypes().Has(syncer::SESSIONS))) |
| 492 | return Error(kSessionSyncError); |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 493 | sync_sessions::OpenTabsUIDelegate* open_tabs = |
| 494 | service->GetOpenTabsUIDelegate(); |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 495 | if (!open_tabs) |
| 496 | return Error(kSessionSyncError); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 497 | |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 498 | const sessions::SessionTab* tab = NULL; |
[email protected] | a9f5662 | 2013-11-21 19:37:06 | [diff] [blame] | 499 | if (open_tabs->GetForeignTab(session_id.session_tag(), |
| 500 | session_id.id(), |
| 501 | &tab)) { |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 502 | TabStripModel* tab_strip = browser->tab_strip_model(); |
| 503 | content::WebContents* contents = tab_strip->GetActiveWebContents(); |
| 504 | |
| 505 | content::WebContents* tab_contents = |
nick | 3b04f32 | 2016-08-31 19:29:19 | [diff] [blame] | 506 | SessionRestore::RestoreForeignSessionTab( |
| 507 | contents, *tab, WindowOpenDisposition::NEW_FOREGROUND_TAB); |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 508 | return GetRestoredTabResult(tab_contents); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 509 | } |
| 510 | |
| 511 | // Restoring a full window. |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 512 | std::vector<const sessions::SessionWindow*> windows; |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 513 | if (!open_tabs->GetForeignSession(session_id.session_tag(), &windows)) |
| 514 | return Error(kInvalidSessionIdError, session_id.ToString()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 515 | |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 516 | std::vector<const sessions::SessionWindow*>::const_iterator window = |
| 517 | windows.begin(); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 518 | while (window != windows.end() |
| 519 | && (*window)->window_id.id() != session_id.id()) { |
| 520 | ++window; |
| 521 | } |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 522 | if (window == windows.end()) |
| 523 | return Error(kInvalidSessionIdError, session_id.ToString()); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 524 | |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 525 | // Only restore one window at a time. |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 526 | std::vector<Browser*> browsers = |
| 527 | SessionRestore::RestoreForeignSessionWindows(profile, window, window + 1); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 528 | // Will always create one browser because we only restore one window per call. |
| 529 | DCHECK_EQ(1u, browsers.size()); |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 530 | return GetRestoredWindowResult(ExtensionTabUtil::GetWindowId(browsers[0])); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 531 | } |
| 532 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 533 | ExtensionFunction::ResponseAction SessionsRestoreFunction::Run() { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 534 | std::unique_ptr<Restore::Params> params(Restore::Params::Create(*args_)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 535 | EXTENSION_FUNCTION_VALIDATE(params); |
| 536 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 537 | Profile* profile = Profile::FromBrowserContext(browser_context()); |
| 538 | Browser* browser = chrome::FindBrowserWithProfile(profile); |
| 539 | if (!browser) |
| 540 | return RespondNow(Error(kNoBrowserToRestoreSession)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 541 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 542 | if (profile != profile->GetOriginalProfile()) |
| 543 | return RespondNow(Error(kRestoreInIncognitoError)); |
[email protected] | ecf51988 | 2014-03-21 15:49:52 | [diff] [blame] | 544 | |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 545 | if (!params->session_id) |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 546 | return RespondNow(RestoreMostRecentlyClosed(browser)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 547 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 548 | std::unique_ptr<SessionId> session_id(SessionId::Parse(*params->session_id)); |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 549 | if (!session_id) |
| 550 | return RespondNow(Error(kInvalidSessionIdError, *params->session_id)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 551 | |
rdevlin.cronin | 456b283 | 2016-10-10 20:20:21 | [diff] [blame] | 552 | return RespondNow(session_id->IsForeign() |
| 553 | ? RestoreForeignSession(*session_id, browser) |
| 554 | : RestoreLocalSession(*session_id, browser)); |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 555 | } |
| 556 | |
[email protected] | 38f9258 | 2014-03-30 20:48:55 | [diff] [blame] | 557 | SessionsEventRouter::SessionsEventRouter(Profile* profile) |
| 558 | : profile_(profile), |
| 559 | tab_restore_service_(TabRestoreServiceFactory::GetForProfile(profile)) { |
| 560 | // TabRestoreServiceFactory::GetForProfile() can return NULL (i.e., when in |
| 561 | // incognito mode) |
| 562 | if (tab_restore_service_) { |
| 563 | tab_restore_service_->LoadTabsFromLastSession(); |
| 564 | tab_restore_service_->AddObserver(this); |
| 565 | } |
| 566 | } |
| 567 | |
| 568 | SessionsEventRouter::~SessionsEventRouter() { |
| 569 | if (tab_restore_service_) |
| 570 | tab_restore_service_->RemoveObserver(this); |
| 571 | } |
| 572 | |
| 573 | void SessionsEventRouter::TabRestoreServiceChanged( |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 574 | sessions::TabRestoreService* service) { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 575 | std::unique_ptr<base::ListValue> args(new base::ListValue()); |
ricea | 91d6fc12 | 2016-08-30 08:47:14 | [diff] [blame] | 576 | EventRouter::Get(profile_)->BroadcastEvent(base::MakeUnique<Event>( |
| 577 | events::SESSIONS_ON_CHANGED, api::sessions::OnChanged::kEventName, |
| 578 | std::move(args))); |
[email protected] | 38f9258 | 2014-03-30 20:48:55 | [diff] [blame] | 579 | } |
| 580 | |
| 581 | void SessionsEventRouter::TabRestoreServiceDestroyed( |
blundell | 74001adc | 2015-09-18 11:04:25 | [diff] [blame] | 582 | sessions::TabRestoreService* service) { |
[email protected] | 38f9258 | 2014-03-30 20:48:55 | [diff] [blame] | 583 | tab_restore_service_ = NULL; |
| 584 | } |
| 585 | |
| 586 | SessionsAPI::SessionsAPI(content::BrowserContext* context) |
| 587 | : browser_context_(context) { |
| 588 | EventRouter::Get(browser_context_)->RegisterObserver(this, |
| 589 | api::sessions::OnChanged::kEventName); |
| 590 | } |
| 591 | |
| 592 | SessionsAPI::~SessionsAPI() { |
| 593 | } |
| 594 | |
| 595 | void SessionsAPI::Shutdown() { |
| 596 | EventRouter::Get(browser_context_)->UnregisterObserver(this); |
| 597 | } |
| 598 | |
scottmg | 5e65e3a | 2017-03-08 08:48:46 | [diff] [blame^] | 599 | static base::LazyInstance< |
| 600 | BrowserContextKeyedAPIFactory<SessionsAPI>>::DestructorAtExit g_factory = |
| 601 | LAZY_INSTANCE_INITIALIZER; |
[email protected] | 38f9258 | 2014-03-30 20:48:55 | [diff] [blame] | 602 | |
| 603 | BrowserContextKeyedAPIFactory<SessionsAPI>* |
| 604 | SessionsAPI::GetFactoryInstance() { |
| 605 | return g_factory.Pointer(); |
| 606 | } |
| 607 | |
| 608 | void SessionsAPI::OnListenerAdded(const EventListenerInfo& details) { |
| 609 | sessions_event_router_.reset( |
| 610 | new SessionsEventRouter(Profile::FromBrowserContext(browser_context_))); |
| 611 | EventRouter::Get(browser_context_)->UnregisterObserver(this); |
| 612 | } |
| 613 | |
[email protected] | d791ad1 | 2013-08-23 02:12:59 | [diff] [blame] | 614 | } // namespace extensions |