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

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

Powered by Google App Engine
This is Rietveld 408576698