OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/sessions/core/tab_restore_service_helper.h" | 5 #include "components/sessions/core/tab_restore_service_helper.h" |
6 | 6 |
7 #include <inttypes.h> | 7 #include <inttypes.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 void TabRestoreServiceHelper::RemoveObserver( | 75 void TabRestoreServiceHelper::RemoveObserver( |
76 TabRestoreServiceObserver* observer) { | 76 TabRestoreServiceObserver* observer) { |
77 observer_list_.RemoveObserver(observer); | 77 observer_list_.RemoveObserver(observer); |
78 } | 78 } |
79 | 79 |
80 void TabRestoreServiceHelper::CreateHistoricalTab(LiveTab* live_tab, | 80 void TabRestoreServiceHelper::CreateHistoricalTab(LiveTab* live_tab, |
81 int index) { | 81 int index) { |
82 if (restoring_) | 82 if (restoring_) |
83 return; | 83 return; |
84 | 84 |
85 // If an entire window is being closed than all of the tabs have already | |
86 // been persisted via "BrowserClosing". Ignore the subsequent tab closing | |
87 // notifications. | |
85 LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab); | 88 LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab); |
86 if (closing_contexts_.find(context) != closing_contexts_.end()) | 89 if (closing_contexts_.find(context) != closing_contexts_.end()) |
87 return; | 90 return; |
88 | 91 |
92 // If this is the last tab being closed in a window it is equivalent to a | |
sky
2017/05/08 22:51:36
We differentiate between closing a tab and closing
chrisha
2017/05/09 15:44:54
Ditto with moving this discussion to the bug.
| |
93 // window close action, thus save a "window" entry. This ensures that a | |
94 // "ctrl-shift-t" or "shift-click" will restore the tab to a window with the | |
95 // original display parameters. | |
96 if (context->GetTabCount() == 1) { | |
97 BrowserClosing(context); | |
98 return; | |
99 } | |
100 | |
89 auto local_tab = base::MakeUnique<Tab>(); | 101 auto local_tab = base::MakeUnique<Tab>(); |
90 PopulateTab(local_tab.get(), index, context, live_tab); | 102 PopulateTab(local_tab.get(), index, context, live_tab); |
91 if (local_tab->navigations.empty()) | 103 if (local_tab->navigations.empty()) |
92 return; | 104 return; |
93 | 105 |
94 AddEntry(std::move(local_tab), true, true); | 106 AddEntry(std::move(local_tab), true, true); |
95 } | 107 } |
96 | 108 |
97 void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) { | 109 void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) { |
98 closing_contexts_.insert(context); | 110 closing_contexts_.insert(context); |
99 | 111 |
100 auto window = base::MakeUnique<Window>(); | 112 auto window = base::MakeUnique<Window>(); |
101 window->selected_tab_index = context->GetSelectedIndex(); | 113 window->selected_tab_index = context->GetSelectedIndex(); |
102 window->timestamp = TimeNow(); | 114 window->timestamp = TimeNow(); |
103 window->app_name = context->GetAppName(); | 115 window->app_name = context->GetAppName(); |
116 window->bounds = context->GetBounds(); | |
117 window->show_state = context->GetShowState(); | |
118 window->workspace = context->GetWorkspace(); | |
104 | 119 |
105 for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) { | 120 for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) { |
106 auto tab = base::MakeUnique<Tab>(); | 121 auto tab = base::MakeUnique<Tab>(); |
107 PopulateTab(tab.get(), tab_index, context, | 122 PopulateTab(tab.get(), tab_index, context, |
108 context->GetLiveTabAt(tab_index)); | 123 context->GetLiveTabAt(tab_index)); |
109 if (!tab->navigations.empty()) { | 124 if (!tab->navigations.empty()) { |
110 tab->browser_id = context->GetSessionID().id(); | 125 tab->browser_id = context->GetSessionID().id(); |
111 window->tabs.push_back(std::move(tab)); | 126 window->tabs.push_back(std::move(tab)); |
112 } | 127 } |
113 } | 128 } |
114 if (window->tabs.size() == 1 && window->app_name.empty()) { | 129 |
115 // Short-circuit creating a Window if only 1 tab was present. This fixes | 130 if (!window->tabs.empty()) { |
116 // http://crbug.com/56744. | |
117 AddEntry(std::move(window->tabs[0]), true, true); | |
118 } else if (!window->tabs.empty()) { | |
119 window->selected_tab_index = std::min( | 131 window->selected_tab_index = std::min( |
120 static_cast<int>(window->tabs.size() - 1), window->selected_tab_index); | 132 static_cast<int>(window->tabs.size() - 1), window->selected_tab_index); |
121 AddEntry(std::move(window), true, true); | 133 AddEntry(std::move(window), true, true); |
122 } | 134 } |
123 } | 135 } |
124 | 136 |
125 void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) { | 137 void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) { |
126 closing_contexts_.erase(context); | 138 closing_contexts_.erase(context); |
127 } | 139 } |
128 | 140 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 | 173 |
162 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById( | 174 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById( |
163 LiveTabContext* context, | 175 LiveTabContext* context, |
164 SessionID::id_type id, | 176 SessionID::id_type id, |
165 WindowOpenDisposition disposition) { | 177 WindowOpenDisposition disposition) { |
166 Entries::iterator entry_iterator = GetEntryIteratorById(id); | 178 Entries::iterator entry_iterator = GetEntryIteratorById(id); |
167 if (entry_iterator == entries_.end()) { | 179 if (entry_iterator == entries_.end()) { |
168 // Don't hoark here, we allow an invalid id. | 180 // Don't hoark here, we allow an invalid id. |
169 return std::vector<LiveTab*>(); | 181 return std::vector<LiveTab*>(); |
170 } | 182 } |
183 auto& entry = **entry_iterator; | |
184 | |
185 // If a window containing a single tab is being restored with "tab" | |
186 // disposition then treat it as restoring that tab rather than as restoring | |
187 // the entire window. This ensures that clicking or ctrl-clicking on 1-tab | |
188 // windows (which are visually presented as tabs in the "History > Recent | |
189 // Tabs" menu) are opened in the current browser window, like other tab items. | |
190 // | |
191 // However, shift-clicking or Ctrl-Shift-T activating these items will ensure | |
192 // that they are opened as a separate window with restored display parameters. | |
193 if (entry.id == id && entry.type == TabRestoreService::WINDOW && | |
194 (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || | |
195 disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB)) { | |
196 auto& window = static_cast<Window&>(entry); | |
197 if (window.tabs.size() == 1) | |
198 return RestoreEntryById(context, window.tabs[0]->id, disposition); | |
199 } | |
171 | 200 |
172 if (observer_) | 201 if (observer_) |
173 observer_->OnRestoreEntryById(id, entry_iterator); | 202 observer_->OnRestoreEntryById(id, entry_iterator); |
174 restoring_ = true; | 203 restoring_ = true; |
175 auto& entry = **entry_iterator; | |
176 | 204 |
177 // If the entry's ID does not match the ID that is being restored, then the | 205 // If the entry's ID does not match the ID that is being restored, then the |
178 // entry is a window from which a single tab will be restored. | 206 // entry is a window from which a single tab will be restored. |
179 bool restoring_tab_in_window = entry.id != id; | 207 bool restoring_tab_in_window = entry.id != id; |
180 | 208 |
181 // |context| will be NULL in cases where one isn't already available (eg, | 209 // |context| will be NULL in cases where one isn't already available (eg, |
182 // when invoked on Mac OS X with no windows open). In this case, create a | 210 // when invoked on Mac OS X with no windows open). In this case, create a |
183 // new browser into which we restore the tabs. | 211 // new browser into which we restore the tabs. |
184 std::vector<LiveTab*> live_tabs; | 212 std::vector<LiveTab*> live_tabs; |
185 switch (entry.type) { | 213 switch (entry.type) { |
186 case TabRestoreService::TAB: { | 214 case TabRestoreService::TAB: { |
187 auto& tab = static_cast<const Tab&>(entry); | 215 auto& tab = static_cast<const Tab&>(entry); |
188 LiveTab* restored_tab = nullptr; | 216 LiveTab* restored_tab = nullptr; |
189 context = RestoreTab(tab, context, disposition, &restored_tab); | 217 context = RestoreTab(tab, context, disposition, &restored_tab); |
190 live_tabs.push_back(restored_tab); | 218 live_tabs.push_back(restored_tab); |
191 context->ShowBrowserWindow(); | 219 context->ShowBrowserWindow(); |
192 break; | 220 break; |
193 } | 221 } |
194 case TabRestoreService::WINDOW: { | 222 case TabRestoreService::WINDOW: { |
195 LiveTabContext* current_context = context; | 223 LiveTabContext* current_context = context; |
196 auto& window = static_cast<Window&>(entry); | 224 auto& window = static_cast<Window&>(entry); |
197 | 225 |
198 // When restoring a window, either the entire window can be restored, or a | 226 // When restoring a window, either the entire window can be restored, or a |
199 // single tab within it. If the entry's ID matches the one to restore, | 227 // single tab within it. If the entry's ID matches the one to restore, |
200 // then the entire window will be restored. | 228 // then the entire window will be restored. |
201 if (!restoring_tab_in_window) { | 229 if (!restoring_tab_in_window) { |
202 context = client_->CreateLiveTabContext(window.app_name); | 230 context = |
231 client_->CreateLiveTabContext(window.app_name, window.bounds, | |
232 window.show_state, window.workspace); | |
203 for (size_t tab_i = 0; tab_i < window.tabs.size(); ++tab_i) { | 233 for (size_t tab_i = 0; tab_i < window.tabs.size(); ++tab_i) { |
204 const Tab& tab = *window.tabs[tab_i]; | 234 const Tab& tab = *window.tabs[tab_i]; |
205 LiveTab* restored_tab = context->AddRestoredTab( | 235 LiveTab* restored_tab = context->AddRestoredTab( |
206 tab.navigations, context->GetTabCount(), | 236 tab.navigations, context->GetTabCount(), |
207 tab.current_navigation_index, tab.extension_app_id, | 237 tab.current_navigation_index, tab.extension_app_id, |
208 static_cast<int>(tab_i) == window.selected_tab_index, tab.pinned, | 238 static_cast<int>(tab_i) == window.selected_tab_index, tab.pinned, |
209 tab.from_last_session, tab.platform_data.get(), | 239 tab.from_last_session, tab.platform_data.get(), |
210 tab.user_agent_override); | 240 tab.user_agent_override); |
211 if (restored_tab) { | 241 if (restored_tab) { |
212 client_->OnTabRestored( | 242 client_->OnTabRestored( |
213 tab.navigations.at(tab.current_navigation_index).virtual_url()); | 243 tab.navigations.at(tab.current_navigation_index).virtual_url()); |
214 live_tabs.push_back(restored_tab); | 244 live_tabs.push_back(restored_tab); |
215 } | 245 } |
216 } | 246 } |
217 // All the window's tabs had the same former browser_id. | 247 // All the window's tabs had the same former browser_id. |
218 if (auto browser_id = window.tabs[0]->browser_id) { | 248 if (auto browser_id = window.tabs[0]->browser_id) { |
219 UpdateTabBrowserIDs(browser_id, context->GetSessionID().id()); | 249 UpdateTabBrowserIDs(browser_id, context->GetSessionID().id()); |
220 } | 250 } |
221 } else { | 251 } else { |
222 // Restore a single tab from the window. Find the tab that matches the | 252 // Restore a single tab from the window. Find the tab that matches the |
223 // ID | 253 // ID in the window and restore it. |
224 // in the window and restore it. | |
225 for (auto tab_i = window.tabs.begin(); tab_i != window.tabs.end(); | 254 for (auto tab_i = window.tabs.begin(); tab_i != window.tabs.end(); |
226 ++tab_i) { | 255 ++tab_i) { |
227 SessionID::id_type restored_tab_browser_id; | 256 SessionID::id_type restored_tab_browser_id; |
228 { | 257 { |
229 const Tab& tab = **tab_i; | 258 const Tab& tab = **tab_i; |
230 if (tab.id != id) | 259 if (tab.id != id) |
231 continue; | 260 continue; |
232 | 261 |
233 restored_tab_browser_id = tab.browser_id; | 262 restored_tab_browser_id = tab.browser_id; |
234 LiveTab* restored_tab = nullptr; | 263 LiveTab* restored_tab = nullptr; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 const Tab& tab, | 467 const Tab& tab, |
439 LiveTabContext* context, | 468 LiveTabContext* context, |
440 WindowOpenDisposition disposition, | 469 WindowOpenDisposition disposition, |
441 LiveTab** live_tab) { | 470 LiveTab** live_tab) { |
442 LiveTab* restored_tab; | 471 LiveTab* restored_tab; |
443 if (disposition == WindowOpenDisposition::CURRENT_TAB && context) { | 472 if (disposition == WindowOpenDisposition::CURRENT_TAB && context) { |
444 restored_tab = context->ReplaceRestoredTab( | 473 restored_tab = context->ReplaceRestoredTab( |
445 tab.navigations, tab.current_navigation_index, tab.from_last_session, | 474 tab.navigations, tab.current_navigation_index, tab.from_last_session, |
446 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); | 475 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); |
447 } else { | 476 } else { |
448 // We only respsect the tab's original browser if there's no disposition. | 477 // We only respect the tab's original browser if there's no disposition. |
449 if (disposition == WindowOpenDisposition::UNKNOWN && tab.browser_id) { | 478 if (disposition == WindowOpenDisposition::UNKNOWN && tab.browser_id) { |
450 context = client_->FindLiveTabContextWithID(tab.browser_id); | 479 context = client_->FindLiveTabContextWithID(tab.browser_id); |
451 } | 480 } |
452 | 481 |
453 int tab_index = -1; | 482 int tab_index = -1; |
454 | 483 |
455 // |context| will be NULL in cases where one isn't already available (eg, | 484 // |context| will be NULL in cases where one isn't already available (eg, |
456 // when invoked on Mac OS X with no windows open). In this case, create a | 485 // when invoked on Mac OS X with no windows open). In this case, create a |
457 // new browser into which we restore the tabs. | 486 // new browser into which we restore the tabs. |
458 if (context && disposition != WindowOpenDisposition::NEW_WINDOW) { | 487 if (context && disposition != WindowOpenDisposition::NEW_WINDOW) { |
459 tab_index = tab.tabstrip_index; | 488 tab_index = tab.tabstrip_index; |
460 } else { | 489 } else { |
461 context = client_->CreateLiveTabContext(std::string()); | 490 context = client_->CreateLiveTabContext(std::string(), gfx::Rect(), |
491 ui::SHOW_STATE_NORMAL, ""); | |
462 if (tab.browser_id) | 492 if (tab.browser_id) |
463 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); | 493 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
464 } | 494 } |
465 | 495 |
466 // Place the tab at the end if the tab index is no longer valid or | 496 // Place the tab at the end if the tab index is no longer valid or |
467 // we were passed a specific disposition. | 497 // we were passed a specific disposition. |
468 if (tab_index < 0 || tab_index > context->GetTabCount() || | 498 if (tab_index < 0 || tab_index > context->GetTabCount() || |
469 disposition != WindowOpenDisposition::UNKNOWN) { | 499 disposition != WindowOpenDisposition::UNKNOWN) { |
470 tab_index = context->GetTabCount(); | 500 tab_index = context->GetTabCount(); |
471 } | 501 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 tab.browser_id = new_id; | 579 tab.browser_id = new_id; |
550 } | 580 } |
551 } | 581 } |
552 } | 582 } |
553 | 583 |
554 base::Time TabRestoreServiceHelper::TimeNow() const { | 584 base::Time TabRestoreServiceHelper::TimeNow() const { |
555 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); | 585 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); |
556 } | 586 } |
557 | 587 |
558 } // namespace sessions | 588 } // namespace sessions |
OLD | NEW |