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