1// Copyright (c) 2010 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/sync/glue/foreign_session_tracker.h"
6#include "chrome/browser/sync/glue/session_model_associator.h"
7
8namespace browser_sync {
9
10
11ForeignSessionTracker::ForeignSessionTracker() {
12}
13
14ForeignSessionTracker::~ForeignSessionTracker() {
15  clear();
16}
17
18bool ForeignSessionTracker::LookupAllForeignSessions(
19    std::vector<const ForeignSession*>* sessions) {
20  DCHECK(sessions);
21  // Fill vector of sessions from our foreign session map.
22  for (ForeignSessionMap::const_iterator i =
23    foreign_session_map_.begin(); i != foreign_session_map_.end(); ++i) {
24    // Only include sessions with open tabs.
25    ForeignSession* foreign_session = i->second;
26    if (!foreign_session->windows.empty() &&
27        !SessionModelAssociator::SessionWindowHasNoTabsToSync(
28            *foreign_session->windows[0])) {
29      sessions->push_back(foreign_session);
30    }
31  }
32
33  return !sessions->empty();
34}
35
36bool ForeignSessionTracker::LookupSessionWindows(
37    const std::string& foreign_session_tag,
38    std::vector<SessionWindow*>* windows) {
39  DCHECK(windows);
40  ForeignSessionMap::iterator iter = foreign_session_map_.find(
41      foreign_session_tag);
42  if (iter == foreign_session_map_.end())
43    return false;
44  *windows = iter->second->windows;
45  return true;
46}
47
48bool ForeignSessionTracker::LookupSessionTab(
49    const std::string& tag,
50    SessionID::id_type tab_id,
51    const SessionTab** tab) {
52  DCHECK(tab);
53  if (foreign_tab_map_.find(tag) == foreign_tab_map_.end()) {
54    // We have no record of this session.
55    *tab = NULL;
56    return false;
57  }
58  if (foreign_tab_map_[tag]->find(tab_id) == foreign_tab_map_[tag]->end()) {
59    // We have no record of this tab.
60    *tab = NULL;
61    return false;
62  }
63  *tab = (*foreign_tab_map_[tag])[tab_id];
64  return true;
65}
66
67ForeignSession* ForeignSessionTracker::GetForeignSession(
68    const std::string& foreign_session_tag) {
69  scoped_ptr<ForeignSession> foreign_session;
70  if (foreign_session_map_.find(foreign_session_tag) !=
71      foreign_session_map_.end()) {
72    foreign_session.reset(foreign_session_map_[foreign_session_tag]);
73  } else {
74    foreign_session.reset(new ForeignSession);
75    foreign_session->foreign_session_tag = foreign_session_tag;
76    foreign_session_map_[foreign_session_tag] = foreign_session.get();
77  }
78  DCHECK(foreign_session.get());
79  return foreign_session.release();
80}
81
82bool ForeignSessionTracker::DeleteForeignSession(
83    const std::string& foreign_session_tag) {
84    ForeignSessionMap::iterator iter =
85        foreign_session_map_.find(foreign_session_tag);
86  if (iter != foreign_session_map_.end()) {
87    delete iter->second;  // Delete the ForeignSession object.
88    foreign_session_map_.erase(iter);
89    return true;
90  } else {
91    return false;
92  }
93}
94
95SessionTab* ForeignSessionTracker::GetSessionTab(
96    const std::string& foreign_session_tag,
97    SessionID::id_type tab_id,
98    bool has_window) {
99  if (foreign_tab_map_.find(foreign_session_tag) == foreign_tab_map_.end())
100    foreign_tab_map_[foreign_session_tag] = new IDToSessionTabMap;
101  scoped_ptr<SessionTab> tab;
102  IDToSessionTabMap::iterator iter =
103      foreign_tab_map_[foreign_session_tag]->find(tab_id);
104  if (iter != foreign_tab_map_[foreign_session_tag]->end()) {
105    tab.reset(iter->second);
106    if (has_window)  // This tab is linked to a window, so it's not an orphan.
107      unmapped_tabs_.erase(tab.get());
108    VLOG(1) << "Associating " << foreign_session_tag << "'s seen tab " <<
109        tab_id  << " at " << tab.get();
110  } else {
111    tab.reset(new SessionTab());
112    (*foreign_tab_map_[foreign_session_tag])[tab_id] = tab.get();
113    if (!has_window)  // This tab is not linked to a window, it's an orphan.
114    unmapped_tabs_.insert(tab.get());
115    VLOG(1) << "Associating " << foreign_session_tag << "'s new tab " <<
116        tab_id  << " at " << tab.get();
117  }
118  DCHECK(tab.get());
119  return tab.release();
120}
121
122void ForeignSessionTracker::clear() {
123  // Delete ForeignSession objects (which also deletes all their windows/tabs).
124  STLDeleteContainerPairSecondPointers(foreign_session_map_.begin(),
125      foreign_session_map_.end());
126  foreign_session_map_.clear();
127
128  // Delete IDToSessTab maps. Does not delete the SessionTab objects, because
129  // they should already be referenced through foreign_session_map_.
130  STLDeleteContainerPairSecondPointers(foreign_tab_map_.begin(),
131      foreign_tab_map_.end());
132  foreign_tab_map_.clear();
133
134  // Go through and delete any tabs we had allocated but had not yet placed into
135  // a ForeignSessionobject.
136  STLDeleteContainerPointers(unmapped_tabs_.begin(), unmapped_tabs_.end());
137  unmapped_tabs_.clear();
138}
139
140}  // namespace browser_sync
141