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/dom_ui/foreign_session_handler.h" | 5 #include "chrome/browser/dom_ui/foreign_session_handler.h" |
6 | 6 |
| 7 #include <algorithm> |
7 #include <string> | 8 #include <string> |
8 | 9 #include <vector> |
9 #include "base/scoped_vector.h" | 10 #include "base/scoped_vector.h" |
| 11 #include "base/string_number_conversions.h" |
10 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
11 #include "chrome/browser/dom_ui/value_helper.h" | 13 #include "base/values.h" |
| 14 #include "chrome/browser/dom_ui/new_tab_ui.h" |
12 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/browser/sessions/session_restore.h" | 16 #include "chrome/browser/sessions/session_restore.h" |
14 #include "chrome/browser/sessions/tab_restore_service.h" | |
15 #include "chrome/browser/sync/engine/syncapi.h" | 17 #include "chrome/browser/sync/engine/syncapi.h" |
16 #include "chrome/browser/sync/profile_sync_service.h" | 18 #include "chrome/browser/sync/profile_sync_service.h" |
17 #include "chrome/browser/ui/browser.h" | 19 #include "chrome/browser/ui/browser.h" |
18 #include "chrome/common/notification_details.h" | 20 #include "chrome/common/notification_details.h" |
19 #include "chrome/common/notification_service.h" | 21 #include "chrome/common/notification_service.h" |
| 22 #include "chrome/common/url_constants.h" |
20 | 23 |
21 namespace browser_sync { | 24 namespace browser_sync { |
22 | 25 |
| 26 // Maximum number of session we're going to display on the NTP |
23 static const int kMaxSessionsToShow = 10; | 27 static const int kMaxSessionsToShow = 10; |
24 | 28 |
| 29 // Invalid value, used to note that we don't have a tab or window number. |
| 30 static const int kInvalidId = -1; |
| 31 |
25 ForeignSessionHandler::ForeignSessionHandler() { | 32 ForeignSessionHandler::ForeignSessionHandler() { |
26 Init(); | 33 Init(); |
27 } | 34 } |
28 | 35 |
29 void ForeignSessionHandler::RegisterMessages() { | 36 void ForeignSessionHandler::RegisterMessages() { |
30 dom_ui_->RegisterMessageCallback("getForeignSessions", | 37 dom_ui_->RegisterMessageCallback("getForeignSessions", |
31 NewCallback(this, | 38 NewCallback(this, |
32 &ForeignSessionHandler::HandleGetForeignSessions)); | 39 &ForeignSessionHandler::HandleGetForeignSessions)); |
33 dom_ui_->RegisterMessageCallback("reopenForeignSession", | 40 dom_ui_->RegisterMessageCallback("openForeignSession", |
34 NewCallback(this, | 41 NewCallback(this, |
35 &ForeignSessionHandler::HandleReopenForeignSession)); | 42 &ForeignSessionHandler::HandleOpenForeignSession)); |
36 } | 43 } |
37 | 44 |
38 void ForeignSessionHandler::Init() { | 45 void ForeignSessionHandler::Init() { |
39 registrar_.Add(this, NotificationType::SYNC_CONFIGURE_DONE, | 46 registrar_.Add(this, NotificationType::SYNC_CONFIGURE_DONE, |
40 NotificationService::AllSources()); | 47 NotificationService::AllSources()); |
41 registrar_.Add(this, NotificationType::FOREIGN_SESSION_UPDATED, | 48 registrar_.Add(this, NotificationType::FOREIGN_SESSION_UPDATED, |
42 NotificationService::AllSources()); | 49 NotificationService::AllSources()); |
43 registrar_.Add(this, NotificationType::FOREIGN_SESSION_DISABLED, | 50 registrar_.Add(this, NotificationType::FOREIGN_SESSION_DISABLED, |
44 NotificationService::AllSources()); | 51 NotificationService::AllSources()); |
45 } | 52 } |
(...skipping 28 matching lines...) Expand all Loading... |
74 if (model_associator == NULL || | 81 if (model_associator == NULL || |
75 !service->ShouldPushChanges()) { | 82 !service->ShouldPushChanges()) { |
76 return NULL; | 83 return NULL; |
77 } | 84 } |
78 return dom_ui_->GetProfile()->GetProfileSyncService()-> | 85 return dom_ui_->GetProfile()->GetProfileSyncService()-> |
79 GetSessionModelAssociator(); | 86 GetSessionModelAssociator(); |
80 } | 87 } |
81 | 88 |
82 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) { | 89 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) { |
83 SessionModelAssociator* associator = GetModelAssociator(); | 90 SessionModelAssociator* associator = GetModelAssociator(); |
84 if (associator) | 91 std::vector<const ForeignSession*> sessions; |
85 GetForeignSessions(associator); | |
86 } | |
87 | 92 |
88 void ForeignSessionHandler::HandleReopenForeignSession( | 93 if (associator == NULL) { |
89 const ListValue* args) { | 94 // Called before associator created, exit. |
90 // Extract the machine tag and use it to obtain the id for the node we are | 95 return; |
91 // looking for. Send it along with a valid associator to OpenForeignSessions. | |
92 std::string session_string_value = WideToUTF8(ExtractStringValue(args)); | |
93 SessionModelAssociator* associator = GetModelAssociator(); | |
94 if (associator && !session_string_value.empty()) { | |
95 int64 id = associator->GetSyncIdFromChromeId(session_string_value); | |
96 OpenForeignSession(associator, id); | |
97 } | 96 } |
98 } | |
99 | 97 |
100 void ForeignSessionHandler::OpenForeignSession( | 98 // Note: we don't own the ForeignSessions themselves. |
101 SessionModelAssociator* associator, int64 id) { | 99 if (!associator->GetAllForeignSessions(&sessions)) { |
102 // Obtain the session windows for the foreign session. | |
103 // We don't have a ForeignSessionHandler in off the record mode, so we | |
104 // expect the ProfileSyncService to exist. | |
105 sync_api::ReadTransaction trans(dom_ui_->GetProfile()-> | |
106 GetProfileSyncService()->backend()->GetUserShareHandle()); | |
107 ScopedVector<ForeignSession> session; | |
108 associator->AppendForeignSessionWithID(id, &session.get(), &trans); | |
109 | |
110 DCHECK_EQ(1U, session.size()); | |
111 std::vector<SessionWindow*> windows = (*session.begin())->windows; | |
112 SessionRestore::RestoreForeignSessionWindows(dom_ui_->GetProfile(), &windows); | |
113 } | |
114 | |
115 void ForeignSessionHandler::GetForeignSessions( | |
116 SessionModelAssociator* associator) { | |
117 ScopedVector<ForeignSession> clients; | |
118 if (!associator->GetSessionData(&clients.get())) { | |
119 LOG(ERROR) << "ForeignSessionHandler failed to get session data from" | 100 LOG(ERROR) << "ForeignSessionHandler failed to get session data from" |
120 "SessionModelAssociator."; | 101 "SessionModelAssociator."; |
121 return; | 102 return; |
122 } | 103 } |
123 int added_count = 0; | 104 int added_count = 0; |
124 ListValue client_list; | 105 ListValue session_list; |
125 for (std::vector<ForeignSession*>::const_iterator i = | 106 for (std::vector<const ForeignSession*>::const_iterator i = |
126 clients->begin(); i != clients->end() && | 107 sessions.begin(); i != sessions.end() && |
127 added_count < kMaxSessionsToShow; ++i) { | 108 added_count < kMaxSessionsToShow; ++i) { |
128 ForeignSession* foreign_session = *i; | 109 const ForeignSession* foreign_session = *i; |
129 std::vector<TabRestoreService::Entry*> entries; | |
130 dom_ui_->GetProfile()->GetTabRestoreService()->CreateEntriesFromWindows( | |
131 &foreign_session->windows, &entries); | |
132 scoped_ptr<ListValue> window_list(new ListValue()); | 110 scoped_ptr<ListValue> window_list(new ListValue()); |
133 for (std::vector<TabRestoreService::Entry*>::const_iterator it = | 111 for (std::vector<SessionWindow*>::const_iterator it = |
134 entries.begin(); it != entries.end(); ++it) { | 112 foreign_session->windows.begin(); it != foreign_session->windows.end(); |
135 TabRestoreService::Entry* entry = *it; | 113 ++it) { |
| 114 SessionWindow* window = *it; |
136 scoped_ptr<DictionaryValue> window_data(new DictionaryValue()); | 115 scoped_ptr<DictionaryValue> window_data(new DictionaryValue()); |
137 if (entry->type == TabRestoreService::WINDOW && | 116 if (SessionWindowToValue(*window, window_data.get())) { |
138 ValueHelper::WindowToValue( | |
139 *static_cast<TabRestoreService::Window*>(entry), | |
140 window_data.get())) { | |
141 // The javascript checks if the session id is a valid session id, | |
142 // when rendering session information to the new tab page, and it | |
143 // sends the sessionTag back when we need to restore a session. | |
144 | |
145 // TODO(zea): sessionTag is per client, it might be better per window. | |
146 window_data->SetString("sessionTag", | 117 window_data->SetString("sessionTag", |
147 foreign_session->foreign_session_tag); | 118 foreign_session->foreign_session_tag); |
148 window_data->SetInteger("sessionId", entry->id); | |
149 | 119 |
150 // Give ownership to |list_value|. | 120 // Give ownership to |list_value|. |
151 window_list->Append(window_data.release()); | 121 window_list->Append(window_data.release()); |
152 } | 122 } |
153 } | 123 } |
154 added_count++; | 124 added_count++; |
155 | 125 |
156 // Give ownership to |client_list| | 126 // Give ownership to |session_list| |
157 client_list.Append(window_list.release()); | 127 session_list.Append(window_list.release()); |
158 } | 128 } |
159 dom_ui_->CallJavascriptFunction(L"foreignSessions", client_list); | 129 dom_ui_->CallJavascriptFunction(L"foreignSessions", session_list); |
| 130 } |
| 131 |
| 132 void ForeignSessionHandler::HandleOpenForeignSession( |
| 133 const ListValue* args) { |
| 134 size_t num_args = args->GetSize(); |
| 135 if (num_args > 3U || num_args == 0) { |
| 136 LOG(ERROR) << "openForeignWindow called with only " << args->GetSize() |
| 137 << " arguments."; |
| 138 return; |
| 139 } |
| 140 |
| 141 // Extract the machine tag (always provided) |
| 142 std::string session_string_value; |
| 143 if (!args->GetString(0, &session_string_value)) { |
| 144 LOG(ERROR) << "Failed to extract session tag."; |
| 145 return; |
| 146 } |
| 147 |
| 148 // Extract window number. |
| 149 std::string window_num_str; |
| 150 int window_num = kInvalidId; |
| 151 if (num_args >= 2 && (!args->GetString(1, &window_num_str) || |
| 152 !base::StringToInt(window_num_str, &window_num))) { |
| 153 LOG(ERROR) << "Failed to extract window number."; |
| 154 return; |
| 155 } |
| 156 |
| 157 // Extract tab id. |
| 158 std::string tab_id_str; |
| 159 SessionID::id_type tab_id = kInvalidId; |
| 160 if (num_args == 3 && (!args->GetString(2, &tab_id_str) || |
| 161 !base::StringToInt(tab_id_str, &tab_id))) { |
| 162 LOG(ERROR) << "Failed to extract tab SessionID."; |
| 163 return; |
| 164 } |
| 165 |
| 166 SessionModelAssociator* associator = GetModelAssociator(); |
| 167 |
| 168 if (tab_id != kInvalidId) { |
| 169 // We don't actually care about |window_num|, this is just a sanity check. |
| 170 DCHECK_LT(kInvalidId, window_num); |
| 171 const SessionTab* tab; |
| 172 if (!associator->GetForeignTab(session_string_value, tab_id, &tab)) { |
| 173 LOG(ERROR) << "Failed to load foreign tab."; |
| 174 return; |
| 175 } |
| 176 SessionRestore::RestoreForeignSessionTab(dom_ui_->GetProfile(), *tab); |
| 177 } else { |
| 178 std::vector<SessionWindow*> windows; |
| 179 // Note: we don't own the ForeignSessions themselves. |
| 180 if (!associator->GetForeignSession(session_string_value, &windows)) { |
| 181 LOG(ERROR) << "ForeignSessionHandler failed to get session data from" |
| 182 "SessionModelAssociator."; |
| 183 return; |
| 184 } |
| 185 std::vector<SessionWindow*>::const_iterator iter_begin = windows.begin() + |
| 186 ((window_num == kInvalidId) ? 0 : window_num); |
| 187 std::vector<SessionWindow*>::const_iterator iter_end = |
| 188 ((window_num == kInvalidId) ? |
| 189 std::vector<SessionWindow*>::const_iterator(windows.end()) : |
| 190 iter_begin+1); |
| 191 SessionRestore::RestoreForeignSessionWindows(dom_ui_->GetProfile(), |
| 192 iter_begin, |
| 193 iter_end); |
| 194 } |
| 195 } |
| 196 |
| 197 bool ForeignSessionHandler::SessionTabToValue( |
| 198 const SessionTab& tab, |
| 199 DictionaryValue* dictionary) { |
| 200 if (tab.navigations.empty()) |
| 201 return false; |
| 202 int selected_index = tab.current_navigation_index; |
| 203 selected_index = std::max( |
| 204 0, |
| 205 std::min(selected_index, |
| 206 static_cast<int>(tab.navigations.size() - 1))); |
| 207 const TabNavigation& current_navigation = |
| 208 tab.navigations.at(selected_index); |
| 209 if (current_navigation.virtual_url() == GURL(chrome::kChromeUINewTabURL)) |
| 210 return false; |
| 211 NewTabUI::SetURLTitleAndDirection(dictionary, current_navigation.title(), |
| 212 current_navigation.virtual_url()); |
| 213 dictionary->SetString("type", "tab"); |
| 214 dictionary->SetReal("timestamp", |
| 215 static_cast<double>(tab.timestamp.ToInternalValue())); |
| 216 dictionary->SetInteger("sessionId", tab.tab_id.id()); |
| 217 return true; |
| 218 } |
| 219 |
| 220 bool ForeignSessionHandler::SessionWindowToValue( |
| 221 const SessionWindow& window, |
| 222 DictionaryValue* dictionary) { |
| 223 if (window.tabs.empty()) { |
| 224 NOTREACHED(); |
| 225 return false; |
| 226 } |
| 227 scoped_ptr<ListValue> tab_values(new ListValue()); |
| 228 for (size_t i = 0; i < window.tabs.size(); ++i) { |
| 229 scoped_ptr<DictionaryValue> tab_value(new DictionaryValue()); |
| 230 if (SessionTabToValue(*window.tabs[i], tab_value.get())) |
| 231 tab_values->Append(tab_value.release()); |
| 232 } |
| 233 if (tab_values->GetSize() == 0) |
| 234 return false; |
| 235 dictionary->SetString("type", "window"); |
| 236 dictionary->SetReal("timestamp", |
| 237 static_cast<double>(window.timestamp.ToInternalValue())); |
| 238 dictionary->SetInteger("sessionId", window.window_id.id()); |
| 239 dictionary->Set("tabs", tab_values.release()); |
| 240 return true; |
160 } | 241 } |
161 | 242 |
162 } // namespace browser_sync | 243 } // namespace browser_sync |
OLD | NEW |