Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: components/sessions/core/tab_restore_service_helper.cc

Issue 2868983003: Ensure History > Recent Tabs restore preserves window disposition. (Closed)
Patch Set: Small cleanup. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698