OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/sync/glue/session_model_associator.h" | 5 #include "chrome/browser/sync/glue/session_model_associator.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 SessionModelAssociator::SessionModelAssociator( | 30 SessionModelAssociator::SessionModelAssociator( |
31 ProfileSyncService* sync_service) : sync_service_(sync_service) { | 31 ProfileSyncService* sync_service) : sync_service_(sync_service) { |
32 DCHECK(CalledOnValidThread()); | 32 DCHECK(CalledOnValidThread()); |
33 DCHECK(sync_service_); | 33 DCHECK(sync_service_); |
34 } | 34 } |
35 | 35 |
36 SessionModelAssociator::~SessionModelAssociator() { | 36 SessionModelAssociator::~SessionModelAssociator() { |
37 DCHECK(CalledOnValidThread()); | 37 DCHECK(CalledOnValidThread()); |
38 } | 38 } |
39 | 39 |
40 // Sends a notification to ForeignSessionHandler to update the UI, because | |
41 // the session corresponding to the id given has changed state. | |
42 void SessionModelAssociator::Associate( | |
43 const sync_pb::SessionSpecifics* specifics, int64 sync_id) { | |
44 DCHECK(CalledOnValidThread()); | |
45 NotificationService::current()->Notify( | |
46 NotificationType::FOREIGN_SESSION_UPDATED, | |
47 NotificationService::AllSources(), | |
48 Details<int64>(&sync_id)); | |
49 } | |
50 | |
51 bool SessionModelAssociator::AssociateModels() { | 40 bool SessionModelAssociator::AssociateModels() { |
52 DCHECK(CalledOnValidThread()); | 41 DCHECK(CalledOnValidThread()); |
| 42 |
| 43 // Make sure we have a machine tag. |
| 44 if (current_machine_tag_.empty()) |
| 45 InitializeCurrentMachineTag(); // Creates a syncable::BaseTransaction. |
| 46 |
| 47 { |
| 48 // Do an initial update from sync model (in case we just re-enabled and |
| 49 // already had data). |
| 50 sync_api::ReadTransaction trans( |
| 51 sync_service_->backend()->GetUserShareHandle()); |
| 52 UpdateFromSyncModel(&trans); |
| 53 } |
| 54 |
| 55 // Check if anything has changed on the client side. |
53 UpdateSyncModelDataFromClient(); | 56 UpdateSyncModelDataFromClient(); |
54 return true; | 57 return true; |
55 } | 58 } |
56 | 59 |
57 bool SessionModelAssociator::ChromeModelHasUserCreatedNodes( | 60 bool SessionModelAssociator::ChromeModelHasUserCreatedNodes( |
58 bool* has_nodes) { | 61 bool* has_nodes) { |
59 DCHECK(CalledOnValidThread()); | 62 DCHECK(CalledOnValidThread()); |
60 CHECK(has_nodes); | 63 CHECK(has_nodes); |
61 // This is wrong, but this function is unused, anyway. | 64 // This is wrong, but this function is unused, anyway. |
62 *has_nodes = true; | 65 *has_nodes = true; |
63 return true; | 66 return true; |
64 } | 67 } |
65 | 68 |
66 // Sends a notification to ForeignSessionHandler to update the UI, because | 69 bool SessionModelAssociator::DisassociateModels() { |
67 // the session corresponding to the id given has been deleted. | 70 specifics_.clear(); |
68 void SessionModelAssociator::Disassociate(int64 sync_id) { | 71 |
| 72 // There is no local model stored with which to disassociate, just notify |
| 73 // foreign session handlers. |
69 NotificationService::current()->Notify( | 74 NotificationService::current()->Notify( |
70 NotificationType::FOREIGN_SESSION_DELETED, | 75 NotificationType::FOREIGN_SESSION_DISABLED, |
71 NotificationService::AllSources(), | 76 NotificationService::AllSources(), |
72 Details<int64>(&sync_id)); | 77 NotificationService::NoDetails()); |
| 78 return true; |
73 } | 79 } |
74 | 80 |
75 const sync_pb::SessionSpecifics* SessionModelAssociator:: | 81 const sync_pb::SessionSpecifics* SessionModelAssociator:: |
76 GetChromeNodeFromSyncId(int64 sync_id) { | 82 GetChromeNodeFromSyncId(int64 sync_id) { |
77 sync_api::ReadTransaction trans( | 83 sync_api::ReadTransaction trans( |
78 sync_service_->backend()->GetUserShareHandle()); | 84 sync_service_->backend()->GetUserShareHandle()); |
79 sync_api::ReadNode node(&trans); | 85 sync_api::ReadNode node(&trans); |
80 if (!node.InitByIdLookup(sync_id)) | 86 if (!node.InitByIdLookup(sync_id)) |
81 return NULL; | 87 return NULL; |
82 return new sync_pb::SessionSpecifics(node.GetSessionSpecifics()); | 88 return new sync_pb::SessionSpecifics(node.GetSessionSpecifics()); |
(...skipping 30 matching lines...) Expand all Loading... |
113 LOG(ERROR) << kNoSessionsFolderError; | 119 LOG(ERROR) << kNoSessionsFolderError; |
114 return false; | 120 return false; |
115 } | 121 } |
116 // The sync model has user created nodes iff the sessions folder has | 122 // The sync model has user created nodes iff the sessions folder has |
117 // any children. | 123 // any children. |
118 *has_nodes = root.GetFirstChildId() != sync_api::kInvalidId; | 124 *has_nodes = root.GetFirstChildId() != sync_api::kInvalidId; |
119 return true; | 125 return true; |
120 } | 126 } |
121 | 127 |
122 std::string SessionModelAssociator::GetCurrentMachineTag() { | 128 std::string SessionModelAssociator::GetCurrentMachineTag() { |
123 if (current_machine_tag_.empty()) | |
124 InitializeCurrentMachineTag(); | |
125 DCHECK(!current_machine_tag_.empty()); | 129 DCHECK(!current_machine_tag_.empty()); |
126 return current_machine_tag_; | 130 return current_machine_tag_; |
127 } | 131 } |
128 | 132 |
129 void SessionModelAssociator::AppendForeignSessionFromSpecifics( | |
130 const sync_pb::SessionSpecifics* specifics, | |
131 std::vector<ForeignSession*>* session) { | |
132 ForeignSession* foreign_session = new ForeignSession(); | |
133 foreign_session->foreign_tession_tag = specifics->session_tag(); | |
134 session->insert(session->end(), foreign_session); | |
135 for (int i = 0; i < specifics->session_window_size(); i++) { | |
136 const sync_pb::SessionWindow* window = &specifics->session_window(i); | |
137 SessionWindow* session_window = new SessionWindow(); | |
138 PopulateSessionWindowFromSpecifics(session_window, window); | |
139 foreign_session->windows.insert( | |
140 foreign_session->windows.end(), session_window); | |
141 } | |
142 } | |
143 | |
144 // Fills the given vector with foreign session windows to restore. | |
145 void SessionModelAssociator::AppendForeignSessionWithID(int64 id, | |
146 std::vector<ForeignSession*>* session, sync_api::BaseTransaction* trans) { | |
147 if (id == sync_api::kInvalidId) | |
148 return; | |
149 sync_api::ReadNode node(trans); | |
150 if (!node.InitByIdLookup(id)) | |
151 return; | |
152 const sync_pb::SessionSpecifics* ref = &node.GetSessionSpecifics(); | |
153 AppendForeignSessionFromSpecifics(ref, session); | |
154 } | |
155 | |
156 void SessionModelAssociator::UpdateSyncModelDataFromClient() { | 133 void SessionModelAssociator::UpdateSyncModelDataFromClient() { |
157 DCHECK(CalledOnValidThread()); | 134 DCHECK(CalledOnValidThread()); |
158 SessionService::SessionCallback* callback = | 135 SessionService::SessionCallback* callback = |
159 NewCallback(this, &SessionModelAssociator::OnGotSession); | 136 NewCallback(this, &SessionModelAssociator::OnGotSession); |
160 // TODO(jerrica): Stop current race condition, possibly make new method in | 137 // TODO(jerrica): Stop current race condition, possibly make new method in |
161 // session service, which only grabs the windows from memory. | 138 // session service, which only grabs the windows from memory. |
162 GetSessionService()->GetCurrentSession(&consumer_, callback); | 139 GetSessionService()->GetCurrentSession(&consumer_, callback); |
163 } | 140 } |
164 | 141 |
165 bool SessionModelAssociator::GetSessionDataFromSyncModel( | 142 // TODO(zea): Don't recreate sessions_ vector from scratch each time. This |
166 std::vector<ForeignSession*>* sessions) { | 143 // will involve knowing which sessions have been changed (a different data |
167 std::vector<const sync_pb::SessionSpecifics*> specifics; | 144 // structure will probably be better too). |
| 145 bool SessionModelAssociator::UpdateFromSyncModel( |
| 146 const sync_api::BaseTransaction* trans) { |
168 DCHECK(CalledOnValidThread()); | 147 DCHECK(CalledOnValidThread()); |
169 sync_api::ReadTransaction trans( | 148 |
170 sync_service_->backend()->GetUserShareHandle()); | 149 // Rebuild specifics_ vector |
171 sync_api::ReadNode root(&trans); | 150 specifics_.clear(); |
| 151 if (!QuerySyncModel(trans, specifics_)) { |
| 152 LOG(ERROR) << "SessionModelAssociator failed to updated from sync model"; |
| 153 return false; |
| 154 } |
| 155 |
| 156 return true; |
| 157 } |
| 158 |
| 159 bool SessionModelAssociator::QuerySyncModel( |
| 160 const sync_api::BaseTransaction* trans, |
| 161 std::vector<const sync_pb::SessionSpecifics*>& specifics) { |
| 162 DCHECK(CalledOnValidThread()); |
| 163 sync_api::ReadNode root(trans); |
172 if (!root.InitByTagLookup(kSessionsTag)) { | 164 if (!root.InitByTagLookup(kSessionsTag)) { |
173 LOG(ERROR) << kNoSessionsFolderError; | 165 LOG(ERROR) << kNoSessionsFolderError; |
174 return false; | 166 return false; |
175 } | 167 } |
176 sync_api::ReadNode current_machine(&trans); | 168 sync_api::ReadNode current_machine(trans); |
177 int64 current_id = (current_machine.InitByClientTagLookup(syncable::SESSIONS, | 169 int64 current_id = (current_machine.InitByClientTagLookup(syncable::SESSIONS, |
178 GetCurrentMachineTag())) ? current_machine.GetId() : sync_api::kInvalidId; | 170 GetCurrentMachineTag())) ? current_machine.GetId() : sync_api::kInvalidId; |
| 171 |
179 // Iterate through the nodes and populate the session model. | 172 // Iterate through the nodes and populate the session model. |
180 int64 id = root.GetFirstChildId(); | 173 int64 id = root.GetFirstChildId(); |
181 while (id != sync_api::kInvalidId) { | 174 while (id != sync_api::kInvalidId) { |
182 sync_api::ReadNode sync_node(&trans); | 175 sync_api::ReadNode sync_node(trans); |
183 if (!sync_node.InitByIdLookup(id)) { | 176 if (!sync_node.InitByIdLookup(id)) { |
184 LOG(ERROR) << "Failed to fetch sync node for id " << id; | 177 LOG(ERROR) << "Failed to fetch sync node for id " << id; |
185 return false; | 178 return false; |
186 } | 179 } |
187 if (id != current_id) { | 180 if (id != current_id) { |
188 specifics.insert(specifics.end(), &sync_node.GetSessionSpecifics()); | 181 specifics.insert(specifics.end(), &sync_node.GetSessionSpecifics()); |
189 } | 182 } |
190 id = sync_node.GetSuccessorId(); | 183 id = sync_node.GetSuccessorId(); |
191 } | 184 } |
| 185 return true; |
| 186 } |
| 187 |
| 188 bool SessionModelAssociator::GetSessionData( |
| 189 std::vector<ForeignSession*>* sessions) { |
| 190 DCHECK(CalledOnValidThread()); |
| 191 |
| 192 // Build vector of sessions from specifics data |
192 for (std::vector<const sync_pb::SessionSpecifics*>::const_iterator i = | 193 for (std::vector<const sync_pb::SessionSpecifics*>::const_iterator i = |
193 specifics.begin(); i != specifics.end(); ++i) { | 194 specifics_.begin(); i != specifics_.end(); ++i) { |
194 AppendForeignSessionFromSpecifics(*i, sessions); | 195 AppendForeignSessionFromSpecifics(*i, sessions); |
195 } | 196 } |
| 197 |
196 return true; | 198 return true; |
197 } | 199 } |
198 | 200 |
| 201 void SessionModelAssociator::AppendForeignSessionFromSpecifics( |
| 202 const sync_pb::SessionSpecifics* specifics, |
| 203 std::vector<ForeignSession*>* session) { |
| 204 ForeignSession* foreign_session = new ForeignSession(); |
| 205 foreign_session->foreign_tession_tag = specifics->session_tag(); |
| 206 session->insert(session->end(), foreign_session); |
| 207 for (int i = 0; i < specifics->session_window_size(); i++) { |
| 208 const sync_pb::SessionWindow* window = &specifics->session_window(i); |
| 209 SessionWindow* session_window = new SessionWindow(); |
| 210 PopulateSessionWindowFromSpecifics(session_window, window); |
| 211 foreign_session->windows.insert( |
| 212 foreign_session->windows.end(), session_window); |
| 213 } |
| 214 } |
| 215 |
| 216 // Fills the given vector with foreign session windows to restore. |
| 217 void SessionModelAssociator::AppendForeignSessionWithID(int64 id, |
| 218 std::vector<ForeignSession*>* session, sync_api::BaseTransaction* trans) { |
| 219 if (id == sync_api::kInvalidId) |
| 220 return; |
| 221 sync_api::ReadNode node(trans); |
| 222 if (!node.InitByIdLookup(id)) |
| 223 return; |
| 224 const sync_pb::SessionSpecifics* ref = &node.GetSessionSpecifics(); |
| 225 AppendForeignSessionFromSpecifics(ref, session); |
| 226 } |
| 227 |
199 SessionService* SessionModelAssociator::GetSessionService() { | 228 SessionService* SessionModelAssociator::GetSessionService() { |
200 DCHECK(sync_service_); | 229 DCHECK(sync_service_); |
201 Profile* profile = sync_service_->profile(); | 230 Profile* profile = sync_service_->profile(); |
202 DCHECK(profile); | 231 DCHECK(profile); |
203 SessionService* sessions_service = profile->GetSessionService(); | 232 SessionService* sessions_service = profile->GetSessionService(); |
204 DCHECK(sessions_service); | 233 DCHECK(sessions_service); |
205 return sessions_service; | 234 return sessions_service; |
206 } | 235 } |
207 | 236 |
208 void SessionModelAssociator::InitializeCurrentMachineTag() { | 237 void SessionModelAssociator::InitializeCurrentMachineTag() { |
209 sync_api::WriteTransaction trans(sync_service_->backend()-> | 238 sync_api::WriteTransaction trans(sync_service_->backend()-> |
210 GetUserShareHandle()); | 239 GetUserShareHandle()); |
211 syncable::Directory* dir = | 240 syncable::Directory* dir = |
212 trans.GetWrappedWriteTrans()->directory(); | 241 trans.GetWrappedWriteTrans()->directory(); |
| 242 |
| 243 // TODO(zea): We need a better way of creating a machine tag. The directory |
| 244 // kernel's cache_guid changes every time syncing is turned on and off. This |
| 245 // will result in session's associated with stale machine tags persisting on |
| 246 // the server since that tag will not be reused. Eventually this should |
| 247 // become some string identifiable to the user. (Home, Work, Laptop, etc.) |
| 248 // See issue 59672 |
213 current_machine_tag_ = "session_sync"; | 249 current_machine_tag_ = "session_sync"; |
214 current_machine_tag_.append(dir->cache_guid()); | 250 current_machine_tag_.append(dir->cache_guid()); |
| 251 LOG(INFO) << "Creating machine tag: " << current_machine_tag_; |
215 } | 252 } |
216 | 253 |
217 // See PopulateSessionSpecificsTab for use. May add functionality that includes | 254 // See PopulateSessionSpecificsTab for use. May add functionality that includes |
218 // the state later. | 255 // the state later. |
219 void SessionModelAssociator::PopulateSessionSpecificsNavigation( | 256 void SessionModelAssociator::PopulateSessionSpecificsNavigation( |
220 const TabNavigation* navigation, sync_pb::TabNavigation* tab_navigation) { | 257 const TabNavigation* navigation, sync_pb::TabNavigation* tab_navigation) { |
221 tab_navigation->set_index(navigation->index()); | 258 tab_navigation->set_index(navigation->index()); |
222 tab_navigation->set_virtual_url(navigation->virtual_url().spec()); | 259 tab_navigation->set_virtual_url(navigation->virtual_url().spec()); |
223 tab_navigation->set_referrer(navigation->referrer().spec()); | 260 tab_navigation->set_referrer(navigation->referrer().spec()); |
224 tab_navigation->set_title(UTF16ToUTF8(navigation->title())); | 261 tab_navigation->set_title(UTF16ToUTF8(navigation->title())); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 return false; | 555 return false; |
519 } | 556 } |
520 create_node.SetSessionSpecifics(*session_data); | 557 create_node.SetSessionSpecifics(*session_data); |
521 return true; | 558 return true; |
522 } | 559 } |
523 write_node.SetSessionSpecifics(*session_data); | 560 write_node.SetSessionSpecifics(*session_data); |
524 return true; | 561 return true; |
525 } | 562 } |
526 | 563 |
527 } // namespace browser_sync | 564 } // namespace browser_sync |
528 | |
OLD | NEW |