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

Side by Side Diff: chrome/browser/sessions/session_service_commands.cc

Issue 672083002: Refactoring of SessionService to get componentized. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: One more self nit Created 6 years, 1 month 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
(Empty)
1 // Copyright 2014 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/sessions/session_service_commands.h"
6
7 #include <vector>
8
9 #include "base/pickle.h"
10 #include "chrome/browser/sessions/base_session_service_commands.h"
11 #include "chrome/browser/sessions/base_session_service_delegate.h"
12 #include "chrome/browser/sessions/session_command.h"
13 #include "chrome/browser/sessions/session_types.h"
14
15 // Identifier for commands written to file.
16 static const SessionCommand::id_type kCommandSetTabWindow = 0;
17 // OBSOLETE Superseded by kCommandSetWindowBounds3.
18 // static const SessionCommand::id_type kCommandSetWindowBounds = 1;
19 static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2;
20 static const SessionCommand::id_type
21 kCommandTabNavigationPathPrunedFromBack = 5;
22 static const SessionCommand::id_type kCommandUpdateTabNavigation = 6;
23 static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7;
24 static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8;
25 static const SessionCommand::id_type kCommandSetWindowType = 9;
26 // OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration.
27 // static const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
28 static const SessionCommand::id_type
29 kCommandTabNavigationPathPrunedFromFront = 11;
30 static const SessionCommand::id_type kCommandSetPinnedState = 12;
31 static const SessionCommand::id_type kCommandSetExtensionAppID = 13;
32 static const SessionCommand::id_type kCommandSetWindowBounds3 = 14;
33 static const SessionCommand::id_type kCommandSetWindowAppName = 15;
34 static const SessionCommand::id_type kCommandTabClosed = 16;
35 static const SessionCommand::id_type kCommandWindowClosed = 17;
36 static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18;
37 static const SessionCommand::id_type kCommandSessionStorageAssociated = 19;
38 static const SessionCommand::id_type kCommandSetActiveWindow = 20;
39
40 namespace {
41
42 // Various payload structures.
43 struct ClosedPayload {
44 SessionID::id_type id;
45 int64 close_time;
46 };
47
48 struct WindowBoundsPayload2 {
49 SessionID::id_type window_id;
50 int32 x;
51 int32 y;
52 int32 w;
53 int32 h;
54 bool is_maximized;
55 };
56
57 struct WindowBoundsPayload3 {
58 SessionID::id_type window_id;
59 int32 x;
60 int32 y;
61 int32 w;
62 int32 h;
63 int32 show_state;
64 };
65
66 typedef SessionID::id_type ActiveWindowPayload;
67
68 struct IDAndIndexPayload {
69 SessionID::id_type id;
70 int32 index;
71 };
72
73 typedef IDAndIndexPayload TabIndexInWindowPayload;
74
75 typedef IDAndIndexPayload TabNavigationPathPrunedFromBackPayload;
76
77 typedef IDAndIndexPayload SelectedNavigationIndexPayload;
78
79 typedef IDAndIndexPayload SelectedTabInIndexPayload;
80
81 typedef IDAndIndexPayload WindowTypePayload;
82
83 typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload;
84
85 struct PinnedStatePayload {
86 SessionID::id_type tab_id;
87 bool pinned_state;
88 };
89
90 // Persisted versions of ui::WindowShowState that are written to disk and can
91 // never change.
92 enum PersistedWindowShowState {
93 // SHOW_STATE_DEFAULT (0) never persisted.
94 PERSISTED_SHOW_STATE_NORMAL = 1,
95 PERSISTED_SHOW_STATE_MINIMIZED = 2,
96 PERSISTED_SHOW_STATE_MAXIMIZED = 3,
97 // SHOW_STATE_INACTIVE (4) never persisted.
98 PERSISTED_SHOW_STATE_FULLSCREEN = 5,
99 PERSISTED_SHOW_STATE_DETACHED_DEPRECATED = 6,
100 PERSISTED_SHOW_STATE_END = 6
101 };
102
103 // Assert to ensure PersistedWindowShowState is updated if ui::WindowShowState
104 // is changed.
105 COMPILE_ASSERT(ui::SHOW_STATE_END ==
106 static_cast<ui::WindowShowState>(PERSISTED_SHOW_STATE_END),
107 persisted_show_state_mismatch);
108
109 // Returns the show state to store to disk based |state|.
110 PersistedWindowShowState ShowStateToPersistedShowState(
111 ui::WindowShowState state) {
112 switch (state) {
113 case ui::SHOW_STATE_NORMAL:
114 return PERSISTED_SHOW_STATE_NORMAL;
115 case ui::SHOW_STATE_MINIMIZED:
116 return PERSISTED_SHOW_STATE_MINIMIZED;
117 case ui::SHOW_STATE_MAXIMIZED:
118 return PERSISTED_SHOW_STATE_MAXIMIZED;
119 case ui::SHOW_STATE_FULLSCREEN:
120 return PERSISTED_SHOW_STATE_FULLSCREEN;
121
122 case ui::SHOW_STATE_DEFAULT:
123 case ui::SHOW_STATE_INACTIVE:
124 return PERSISTED_SHOW_STATE_NORMAL;
125
126 case ui::SHOW_STATE_END:
127 break;
128 }
129 NOTREACHED();
130 return PERSISTED_SHOW_STATE_NORMAL;
131 }
132
133 // Lints show state values when read back from persited disk.
134 ui::WindowShowState PersistedShowStateToShowState(int state) {
135 switch (state) {
136 case PERSISTED_SHOW_STATE_NORMAL:
137 return ui::SHOW_STATE_NORMAL;
138 case PERSISTED_SHOW_STATE_MINIMIZED:
139 return ui::SHOW_STATE_MINIMIZED;
140 case PERSISTED_SHOW_STATE_MAXIMIZED:
141 return ui::SHOW_STATE_MAXIMIZED;
142 case PERSISTED_SHOW_STATE_FULLSCREEN:
143 return ui::SHOW_STATE_FULLSCREEN;
144 case PERSISTED_SHOW_STATE_DETACHED_DEPRECATED:
145 return ui::SHOW_STATE_NORMAL;
146 }
147 NOTREACHED();
148 return ui::SHOW_STATE_NORMAL;
149 }
150
151 } // namespace
152
153 // SessionService -------------------------------------------------------------
154
155 SessionServiceCommands::SessionServiceCommands(
156 SessionServiceCommandsDelegate* delegate) : delegate_(delegate) {}
157
158 SessionServiceCommands::~SessionServiceCommands() {
159 // The owner is responsible to save upon exit.
160 }
161
162 scoped_ptr<SessionCommand>
163 SessionServiceCommands::CreateSetSelectedTabInWindowCommand(
164 const SessionID& window_id,
165 int index) {
166 SelectedTabInIndexPayload payload = { 0 };
167 payload.id = window_id.id();
168 payload.index = index;
169 scoped_ptr<SessionCommand> command(
170 new SessionCommand(kCommandSetSelectedTabInIndex, sizeof(payload)));
171 memcpy(command->contents(), &payload, sizeof(payload));
172 return command.Pass();
173 }
174
175 scoped_ptr<SessionCommand>
176 SessionServiceCommands::CreateSetTabWindowCommand(
177 const SessionID& window_id,
178 const SessionID& tab_id) {
179 SessionID::id_type payload[] = { window_id.id(), tab_id.id() };
180 scoped_ptr<SessionCommand> command(
181 new SessionCommand(kCommandSetTabWindow, sizeof(payload)));
182 memcpy(command->contents(), payload, sizeof(payload));
183 return command.Pass();
184 }
185
186 scoped_ptr<SessionCommand>
187 SessionServiceCommands::CreateSetWindowBoundsCommand(
188 const SessionID& window_id,
189 const gfx::Rect& bounds,
190 ui::WindowShowState show_state) {
191 WindowBoundsPayload3 payload = { 0 };
192 payload.window_id = window_id.id();
193 payload.x = bounds.x();
194 payload.y = bounds.y();
195 payload.w = bounds.width();
196 payload.h = bounds.height();
197 payload.show_state = ShowStateToPersistedShowState(show_state);
198 scoped_ptr<SessionCommand> command(
199 new SessionCommand(kCommandSetWindowBounds3, sizeof(payload)));
200 memcpy(command->contents(), &payload, sizeof(payload));
201 return command.Pass();
202 }
203
204 scoped_ptr<SessionCommand>
205 SessionServiceCommands::CreateSetTabIndexInWindowCommand(
206 const SessionID& tab_id,
207 int new_index) {
208 TabIndexInWindowPayload payload = { 0 };
209 payload.id = tab_id.id();
210 payload.index = new_index;
211 scoped_ptr<SessionCommand> command(
212 new SessionCommand(kCommandSetTabIndexInWindow, sizeof(payload)));
213 memcpy(command->contents(), &payload, sizeof(payload));
214 return command.Pass();
215 }
216
217 scoped_ptr<SessionCommand>
218 SessionServiceCommands::CreateTabClosedCommand(
219 const SessionID::id_type tab_id) {
220 ClosedPayload payload;
221 // Because of what appears to be a compiler bug setting payload to {0} doesn't
222 // set the padding to 0, resulting in Purify reporting an UMR when we write
223 // the structure to disk. To avoid this we explicitly memset the struct.
224 memset(&payload, 0, sizeof(payload));
225 payload.id = tab_id;
226 payload.close_time = base::Time::Now().ToInternalValue();
227 scoped_ptr<SessionCommand> command(
228 new SessionCommand(kCommandTabClosed, sizeof(payload)));
229 memcpy(command->contents(), &payload, sizeof(payload));
230 return command.Pass();
231 }
232
233 scoped_ptr<SessionCommand>
234 SessionServiceCommands::CreateWindowClosedCommand(
235 const SessionID::id_type window_id) {
236 ClosedPayload payload;
237 // See comment in CreateTabClosedCommand as to why we do this.
238 memset(&payload, 0, sizeof(payload));
239 payload.id = window_id;
240 payload.close_time = base::Time::Now().ToInternalValue();
241 scoped_ptr<SessionCommand> command(
242 new SessionCommand(kCommandWindowClosed, sizeof(payload)));
243 memcpy(command->contents(), &payload, sizeof(payload));
244 return command.Pass();
245 }
246
247 scoped_ptr<SessionCommand>
248 SessionServiceCommands::CreateSetSelectedNavigationIndexCommand(
249 const SessionID& tab_id,
250 int index) {
251 SelectedNavigationIndexPayload payload = { 0 };
252 payload.id = tab_id.id();
253 payload.index = index;
254 scoped_ptr<SessionCommand> command(
255 new SessionCommand(kCommandSetSelectedNavigationIndex, sizeof(payload)));
256 memcpy(command->contents(), &payload, sizeof(payload));
257 return command.Pass();
258 }
259
260 scoped_ptr<SessionCommand>
261 SessionServiceCommands::CreateSetWindowTypeCommand(
262 const SessionID& window_id,
263 SessionWindow::WindowType type) {
264 WindowTypePayload payload = { 0 };
265 payload.id = window_id.id();
266 payload.index = static_cast<int32>(type);
267 scoped_ptr<SessionCommand> command(
268 new SessionCommand( kCommandSetWindowType, sizeof(payload)));
269 memcpy(command->contents(), &payload, sizeof(payload));
270 return command.Pass();
271 }
272
273 scoped_ptr<SessionCommand>
274 SessionServiceCommands::CreatePinnedStateCommand(
275 const SessionID& tab_id,
276 bool is_pinned) {
277 PinnedStatePayload payload = { 0 };
278 payload.tab_id = tab_id.id();
279 payload.pinned_state = is_pinned;
280 scoped_ptr<SessionCommand> command(
281 new SessionCommand(kCommandSetPinnedState, sizeof(payload)));
282 memcpy(command->contents(), &payload, sizeof(payload));
283 return command.Pass();
284 }
285
286 scoped_ptr<SessionCommand>
287 SessionServiceCommands::CreateSessionStorageAssociatedCommand(
288 const SessionID& tab_id,
289 const std::string& session_storage_persistent_id) {
290 Pickle pickle;
291 pickle.WriteInt(tab_id.id());
292 pickle.WriteString(session_storage_persistent_id);
293 return scoped_ptr<SessionCommand>(
294 new SessionCommand(kCommandSessionStorageAssociated, pickle));
295 }
296
297 scoped_ptr<SessionCommand> SessionServiceCommands::CreateSetActiveWindowCommand(
298 const SessionID& window_id) {
299 ActiveWindowPayload payload = 0;
300 payload = window_id.id();
301 scoped_ptr<SessionCommand> command(
302 new SessionCommand(kCommandSetActiveWindow, sizeof(payload)));
303 memcpy(command->contents(), &payload, sizeof(payload));
304 return command.Pass();
305 }
306
307 scoped_ptr<SessionCommand>
308 SessionServiceCommands::CreateTabNavigationPathPrunedFromBackCommand(
309 const SessionID& tab_id,
310 int count) {
311 TabNavigationPathPrunedFromBackPayload payload = { 0 };
312 payload.id = tab_id.id();
313 payload.index = count;
314 scoped_ptr<SessionCommand> command(
315 new SessionCommand(kCommandTabNavigationPathPrunedFromBack,
316 sizeof(payload)));
317 memcpy(command->contents(), &payload, sizeof(payload));
318 return command.Pass();
319 }
320
321 scoped_ptr<SessionCommand>
322 SessionServiceCommands::CreateTabNavigationPathPrunedFromFrontCommand(
323 const SessionID& tab_id,
324 int count) {
325 TabNavigationPathPrunedFromFrontPayload payload = { 0 };
326 payload.id = tab_id.id();
327 payload.index = count;
328 scoped_ptr<SessionCommand> command(
329 new SessionCommand(kCommandTabNavigationPathPrunedFromFront,
330 sizeof(payload)));
331 memcpy(command->contents(), &payload, sizeof(payload));
332 return command.Pass();
333 }
334
335 scoped_ptr<SessionCommand>
336 SessionServiceCommands::CreateUpdateTabNavigationCommand(
337 const SessionID& tab_id,
338 const sessions::SerializedNavigationEntry& navigation) {
339 // TODO(skuhne): Check why this command needs to be called from the base.
340 // thus: could eliminate the use of that class here.
341 return BaseSessionServiceCommands::CreateUpdateTabNavigationCommand(
342 kCommandUpdateTabNavigation,
343 tab_id.id(),
344 navigation).Pass();
345 }
346
347 scoped_ptr<SessionCommand>
348 SessionServiceCommands::CreateSetTabExtensionAppIDCommand(
349 const SessionID& tab_id,
350 const std::string& extension_id) {
351 return BaseSessionServiceCommands::CreateSetTabExtensionAppIDCommand(
352 kCommandSetExtensionAppID,
353 tab_id.id(),
354 extension_id).Pass();
355 }
356
357 scoped_ptr<SessionCommand>
358 SessionServiceCommands::CreateSetTabUserAgentOverrideCommand(
359 const SessionID& tab_id,
360 const std::string& user_agent_override) {
361 return BaseSessionServiceCommands::CreateSetTabUserAgentOverrideCommand(
362 kCommandSetTabUserAgentOverride,
363 tab_id.id(),
364 user_agent_override).Pass();
365 }
366
367 scoped_ptr<SessionCommand>
368 SessionServiceCommands::CreateSetWindowAppNameCommand(
369 const SessionID& window_id,
370 const std::string& app_name) {
371 return BaseSessionServiceCommands::CreateSetWindowAppNameCommand(
372 kCommandSetWindowAppName,
373 window_id.id(),
374 app_name).Pass();
375 }
376
377 bool SessionServiceCommands::ReplacePendingCommand(
378 scoped_ptr<SessionCommand>* command,
379 ScopedVector<SessionCommand>& pending_commands) {
380 // We optimize page navigations, which can happen quite frequently and
381 // is expensive. And activation is like Highlander, there can only be one!
382 if ((*command)->id() != kCommandUpdateTabNavigation &&
383 (*command)->id() != kCommandSetActiveWindow) {
384 return false;
385 }
386 for (ScopedVector<SessionCommand>::reverse_iterator i =
387 pending_commands.rbegin(); i != pending_commands.rend(); ++i) {
388 SessionCommand* existing_command = *i;
389 if ((*command)->id() == kCommandUpdateTabNavigation &&
390 existing_command->id() == kCommandUpdateTabNavigation) {
391 scoped_ptr<Pickle> command_pickle((*command)->PayloadAsPickle());
392 PickleIterator iterator(*command_pickle);
393 SessionID::id_type command_tab_id;
394 int command_nav_index;
395 if (!command_pickle->ReadInt(&iterator, &command_tab_id) ||
396 !command_pickle->ReadInt(&iterator, &command_nav_index)) {
397 return false;
398 }
399 SessionID::id_type existing_tab_id;
400 int existing_nav_index;
401 {
402 // Creating a pickle like this means the Pickle references the data from
403 // the command. Make sure we delete the pickle before the command, else
404 // the pickle references deleted memory.
405 scoped_ptr<Pickle> existing_pickle(existing_command->PayloadAsPickle());
406 iterator = PickleIterator(*existing_pickle);
407 if (!existing_pickle->ReadInt(&iterator, &existing_tab_id) ||
408 !existing_pickle->ReadInt(&iterator, &existing_nav_index)) {
409 return false;
410 }
411 }
412 if (existing_tab_id == command_tab_id &&
413 existing_nav_index == command_nav_index) {
414 // existing_command is an update for the same tab/index pair. Replace
415 // it with the new one. We need to add to the end of the list just in
416 // case there is a prune command after the update command.
417 pending_commands.erase(i.base() - 1);
418 pending_commands.push_back((*command).release());
419 return true;
420 }
421 return false;
422 }
423 if ((*command)->id() == kCommandSetActiveWindow &&
424 existing_command->id() == kCommandSetActiveWindow) {
425 *i = (*command).release();
426 return true;
427 }
428 }
429 return false;
430 }
431
432 bool SessionServiceCommands::IsClosingCommand(SessionCommand* command) const {
433 return command->id() == kCommandTabClosed ||
434 command->id() == kCommandWindowClosed;
435 }
436
437 void SessionServiceCommands::RestoreSessionFromCommands(
438 const ScopedVector<SessionCommand>& commands,
439 std::vector<SessionWindow*>* valid_windows,
440 SessionID::id_type* active_window_id) {
441 std::map<int, SessionTab*> tabs;
442 std::map<int, SessionWindow*> windows;
443
444 VLOG(1) << "RestoreSessionFromCommands " << commands.size();
445 if (CreateTabsAndWindows(commands, &tabs, &windows, active_window_id)) {
446 AddTabsToWindows(&tabs, &windows);
447 SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows);
448 UpdateSelectedTabIndex(valid_windows);
449 }
450 STLDeleteValues(&tabs);
451 // Don't delete contents of windows, that is done by the caller as all
452 // valid windows are added to valid_windows.
453 }
454
455 void SessionServiceCommands::UpdateSelectedTabIndex(
456 std::vector<SessionWindow*>* windows) {
457 for (std::vector<SessionWindow*>::const_iterator i = windows->begin();
458 i != windows->end(); ++i) {
459 // See note in SessionWindow as to why we do this.
460 int new_index = 0;
461 for (std::vector<SessionTab*>::const_iterator j = (*i)->tabs.begin();
462 j != (*i)->tabs.end(); ++j) {
463 if ((*j)->tab_visual_index == (*i)->selected_tab_index) {
464 new_index = static_cast<int>(j - (*i)->tabs.begin());
465 break;
466 }
467 }
468 (*i)->selected_tab_index = new_index;
469 }
470 }
471
472 SessionWindow* SessionServiceCommands::GetWindow(SessionID::id_type window_id,
473 IdToSessionWindow* windows) {
474 std::map<int, SessionWindow*>::iterator i = windows->find(window_id);
475 if (i == windows->end()) {
476 SessionWindow* window = new SessionWindow();
477 window->window_id.set_id(window_id);
478 (*windows)[window_id] = window;
479 return window;
480 }
481 return i->second;
482 }
483
484 SessionTab* SessionServiceCommands::GetTab(SessionID::id_type tab_id,
485 IdToSessionTab* tabs) {
486 DCHECK(tabs);
487 std::map<int, SessionTab*>::iterator i = tabs->find(tab_id);
488 if (i == tabs->end()) {
489 SessionTab* tab = new SessionTab();
490 tab->tab_id.set_id(tab_id);
491 (*tabs)[tab_id] = tab;
492 return tab;
493 }
494 return i->second;
495 }
496
497 std::vector<sessions::SerializedNavigationEntry>::iterator
498 SessionServiceCommands::FindClosestNavigationWithIndex(
499 std::vector<sessions::SerializedNavigationEntry>* navigations,
500 int index) {
501 DCHECK(navigations);
502 for (std::vector<sessions::SerializedNavigationEntry>::iterator
503 i = navigations->begin(); i != navigations->end(); ++i) {
504 if (i->index() >= index)
505 return i;
506 }
507 return navigations->end();
508 }
509
510 // Function used in sorting windows. Sorting is done based on window id. As
511 // window ids increment for each new window, this effectively sorts by creation
512 // time.
513 static bool WindowOrderSortFunction(const SessionWindow* w1,
514 const SessionWindow* w2) {
515 return w1->window_id.id() < w2->window_id.id();
516 }
517
518 // Compares the two tabs based on visual index.
519 static bool TabVisualIndexSortFunction(const SessionTab* t1,
520 const SessionTab* t2) {
521 const int delta = t1->tab_visual_index - t2->tab_visual_index;
522 return delta == 0 ? (t1->tab_id.id() < t2->tab_id.id()) : (delta < 0);
523 }
524
525 void SessionServiceCommands::SortTabsBasedOnVisualOrderAndPrune(
526 std::map<int, SessionWindow*>* windows,
527 std::vector<SessionWindow*>* valid_windows) {
528 std::map<int, SessionWindow*>::iterator i = windows->begin();
529 while (i != windows->end()) {
530 SessionWindow* window = i->second;
531 AppType app_type = window->app_name.empty() ? TYPE_NORMAL : TYPE_APP;
532 if (window->tabs.empty() || window->is_constrained ||
533 !delegate_->ShouldRestoreWindowOfType(window->type, app_type)) {
534 delete window;
535 windows->erase(i++);
536 } else {
537 // Valid window; sort the tabs and add it to the list of valid windows.
538 std::sort(window->tabs.begin(), window->tabs.end(),
539 &TabVisualIndexSortFunction);
540 // Otherwise, add the window such that older windows appear first.
541 if (valid_windows->empty()) {
542 valid_windows->push_back(window);
543 } else {
544 valid_windows->insert(
545 std::upper_bound(valid_windows->begin(), valid_windows->end(),
546 window, &WindowOrderSortFunction),
547 window);
548 }
549 ++i;
550 }
551 }
552 }
553
554 void SessionServiceCommands::AddTabsToWindows(
555 std::map<int, SessionTab*>* tabs,
556 std::map<int, SessionWindow*>* windows) {
557 VLOG(1) << "AddTabsToWindws";
558 VLOG(1) << "Tabs " << tabs->size() << ", windows " << windows->size();
559 std::map<int, SessionTab*>::iterator i = tabs->begin();
560 while (i != tabs->end()) {
561 SessionTab* tab = i->second;
562 if (tab->window_id.id() && !tab->navigations.empty()) {
563 SessionWindow* window = GetWindow(tab->window_id.id(), windows);
564 window->tabs.push_back(tab);
565 tabs->erase(i++);
566
567 // See note in SessionTab as to why we do this.
568 std::vector<sessions::SerializedNavigationEntry>::iterator j =
569 FindClosestNavigationWithIndex(&(tab->navigations),
570 tab->current_navigation_index);
571 if (j == tab->navigations.end()) {
572 tab->current_navigation_index =
573 static_cast<int>(tab->navigations.size() - 1);
574 } else {
575 tab->current_navigation_index =
576 static_cast<int>(j - tab->navigations.begin());
577 }
578 } else {
579 // Never got a set tab index in window, or tabs are empty, nothing
580 // to do.
581 ++i;
582 }
583 }
584 }
585
586 bool SessionServiceCommands::CreateTabsAndWindows(
587 const ScopedVector<SessionCommand>& data,
588 std::map<int, SessionTab*>* tabs,
589 std::map<int, SessionWindow*>* windows,
590 SessionID::id_type* active_window_id) {
591 // If the file is corrupt (command with wrong size, or unknown command), we
592 // still return true and attempt to restore what we we can.
593 VLOG(1) << "CreateTabsAndWindows";
594
595 for (std::vector<SessionCommand*>::const_iterator i = data.begin();
596 i != data.end(); ++i) {
597 const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
598 const SessionCommand* command = *i;
599
600 VLOG(1) << "Read command " << (int) command->id();
601 switch (command->id()) {
602 case kCommandSetTabWindow: {
603 SessionID::id_type payload[2];
604 if (!command->GetPayload(payload, sizeof(payload))) {
605 VLOG(1) << "Failed reading command " << command->id();
606 return true;
607 }
608 GetTab(payload[1], tabs)->window_id.set_id(payload[0]);
609 break;
610 }
611
612 // This is here for forward migration only. New data is saved with
613 // |kCommandSetWindowBounds3|.
614 case kCommandSetWindowBounds2: {
615 WindowBoundsPayload2 payload;
616 if (!command->GetPayload(&payload, sizeof(payload))) {
617 VLOG(1) << "Failed reading command " << command->id();
618 return true;
619 }
620 GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x,
621 payload.y,
622 payload.w,
623 payload.h);
624 GetWindow(payload.window_id, windows)->show_state =
625 payload.is_maximized ?
626 ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_NORMAL;
627 break;
628 }
629
630 case kCommandSetWindowBounds3: {
631 WindowBoundsPayload3 payload;
632 if (!command->GetPayload(&payload, sizeof(payload))) {
633 VLOG(1) << "Failed reading command " << command->id();
634 return true;
635 }
636 GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x,
637 payload.y,
638 payload.w,
639 payload.h);
640 GetWindow(payload.window_id, windows)->show_state =
641 PersistedShowStateToShowState(payload.show_state);
642 break;
643 }
644
645 case kCommandSetTabIndexInWindow: {
646 TabIndexInWindowPayload payload;
647 if (!command->GetPayload(&payload, sizeof(payload))) {
648 VLOG(1) << "Failed reading command " << command->id();
649 return true;
650 }
651 GetTab(payload.id, tabs)->tab_visual_index = payload.index;
652 break;
653 }
654
655 case kCommandTabClosed:
656 case kCommandWindowClosed: {
657 ClosedPayload payload;
658 if (!command->GetPayload(&payload, sizeof(payload))) {
659 VLOG(1) << "Failed reading command " << command->id();
660 return true;
661 }
662 if (command->id() == kCommandTabClosed) {
663 delete GetTab(payload.id, tabs);
664 tabs->erase(payload.id);
665 } else {
666 delete GetWindow(payload.id, windows);
667 windows->erase(payload.id);
668 }
669 break;
670 }
671
672 case kCommandTabNavigationPathPrunedFromBack: {
673 TabNavigationPathPrunedFromBackPayload payload;
674 if (!command->GetPayload(&payload, sizeof(payload))) {
675 VLOG(1) << "Failed reading command " << command->id();
676 return true;
677 }
678 SessionTab* tab = GetTab(payload.id, tabs);
679 tab->navigations.erase(
680 FindClosestNavigationWithIndex(&(tab->navigations), payload.index),
681 tab->navigations.end());
682 break;
683 }
684
685 case kCommandTabNavigationPathPrunedFromFront: {
686 TabNavigationPathPrunedFromFrontPayload payload;
687 if (!command->GetPayload(&payload, sizeof(payload)) ||
688 payload.index <= 0) {
689 VLOG(1) << "Failed reading command " << command->id();
690 return true;
691 }
692 SessionTab* tab = GetTab(payload.id, tabs);
693
694 // Update the selected navigation index.
695 tab->current_navigation_index =
696 std::max(-1, tab->current_navigation_index - payload.index);
697
698 // And update the index of existing navigations.
699 for (std::vector<sessions::SerializedNavigationEntry>::iterator
700 i = tab->navigations.begin();
701 i != tab->navigations.end();) {
702 i->set_index(i->index() - payload.index);
703 if (i->index() < 0)
704 i = tab->navigations.erase(i);
705 else
706 ++i;
707 }
708 break;
709 }
710
711 case kCommandUpdateTabNavigation: {
712 sessions::SerializedNavigationEntry navigation;
713 SessionID::id_type tab_id;
714 if (!BaseSessionServiceCommands::RestoreUpdateTabNavigationCommand(
715 *command,
716 &navigation,
717 &tab_id)) {
718 VLOG(1) << "Failed reading command " << command->id();
719 return true;
720 }
721 SessionTab* tab = GetTab(tab_id, tabs);
722 std::vector<sessions::SerializedNavigationEntry>::iterator i =
723 FindClosestNavigationWithIndex(&(tab->navigations),
724 navigation.index());
725 if (i != tab->navigations.end() && i->index() == navigation.index())
726 *i = navigation;
727 else
728 tab->navigations.insert(i, navigation);
729 break;
730 }
731
732 case kCommandSetSelectedNavigationIndex: {
733 SelectedNavigationIndexPayload payload;
734 if (!command->GetPayload(&payload, sizeof(payload))) {
735 VLOG(1) << "Failed reading command " << command->id();
736 return true;
737 }
738 GetTab(payload.id, tabs)->current_navigation_index = payload.index;
739 break;
740 }
741
742 case kCommandSetSelectedTabInIndex: {
743 SelectedTabInIndexPayload payload;
744 if (!command->GetPayload(&payload, sizeof(payload))) {
745 VLOG(1) << "Failed reading command " << command->id();
746 return true;
747 }
748 GetWindow(payload.id, windows)->selected_tab_index = payload.index;
749 break;
750 }
751
752 case kCommandSetWindowType: {
753 WindowTypePayload payload;
754 if (!command->GetPayload(&payload, sizeof(payload))) {
755 VLOG(1) << "Failed reading command " << command->id();
756 return true;
757 }
758 GetWindow(payload.id, windows)->is_constrained = false;
759 GetWindow(payload.id, windows)->type =
760 static_cast<SessionWindow::WindowType>(payload.index);
761 break;
762 }
763
764 case kCommandSetPinnedState: {
765 PinnedStatePayload payload;
766 if (!command->GetPayload(&payload, sizeof(payload))) {
767 VLOG(1) << "Failed reading command " << command->id();
768 return true;
769 }
770 GetTab(payload.tab_id, tabs)->pinned = payload.pinned_state;
771 break;
772 }
773
774 case kCommandSetWindowAppName: {
775 SessionID::id_type window_id;
776 std::string app_name;
777 if (!BaseSessionServiceCommands::RestoreSetWindowAppNameCommand(
778 *command,
779 &window_id,
780 &app_name))
781 return true;
782
783 GetWindow(window_id, windows)->app_name.swap(app_name);
784 break;
785 }
786
787 case kCommandSetExtensionAppID: {
788 SessionID::id_type tab_id;
789 std::string extension_app_id;
790 if (!BaseSessionServiceCommands::RestoreSetTabExtensionAppIDCommand(
791 *command,
792 &tab_id,
793 &extension_app_id)) {
794 VLOG(1) << "Failed reading command " << command->id();
795 return true;
796 }
797
798 GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id);
799 break;
800 }
801
802 case kCommandSetTabUserAgentOverride: {
803 SessionID::id_type tab_id;
804 std::string user_agent_override;
805 if (!BaseSessionServiceCommands::RestoreSetTabUserAgentOverrideCommand(
806 *command,
807 &tab_id,
808 &user_agent_override)) {
809 return true;
810 }
811
812 GetTab(tab_id, tabs)->user_agent_override.swap(user_agent_override);
813 break;
814 }
815
816 case kCommandSessionStorageAssociated: {
817 scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
818 SessionID::id_type command_tab_id;
819 std::string session_storage_persistent_id;
820 PickleIterator iter(*command_pickle.get());
821 if (!command_pickle->ReadInt(&iter, &command_tab_id) ||
822 !command_pickle->ReadString(&iter, &session_storage_persistent_id))
823 return true;
824 // Associate the session storage back.
825 GetTab(command_tab_id, tabs)->session_storage_persistent_id =
826 session_storage_persistent_id;
827 break;
828 }
829
830 case kCommandSetActiveWindow: {
831 ActiveWindowPayload payload;
832 if (!command->GetPayload(&payload, sizeof(payload))) {
833 VLOG(1) << "Failed reading command " << command->id();
834 return true;
835 }
836 *active_window_id = payload;
837 break;
838 }
839
840 default:
841 // TODO(skuhne): This might call back into a callback handler to extend
842 // the command set for specific implementations.
843 VLOG(1) << "Failed reading an unknown command " << command->id();
844 return true;
845 }
846 }
847 return true;
848 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698