Chromium Code Reviews

Side by Side Diff: chrome/browser/android/foreign_session_helper.cc

Issue 19874002: [Android] Expose foreign session sync related funtionalities through JNI. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed Patch Set 7's comments Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « chrome/browser/android/foreign_session_helper.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 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/android/foreign_session_helper.h"
6
7 #include <jni.h>
8
9 #include "base/android/jni_string.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/prefs/scoped_user_pref_update.h"
12 #include "chrome/browser/profiles/profile_android.h"
13 #include "chrome/browser/sync/glue/session_model_associator.h"
14 #include "chrome/browser/sync/profile_sync_service.h"
15 #include "chrome/browser/sync/profile_sync_service_factory.h"
16 #include "chrome/browser/ui/android/tab_model/tab_model.h"
17 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/common/url_constants.h"
20 #include "content/public/browser/notification_source.h"
21 #include "content/public/browser/user_metrics.h"
22 #include "content/public/browser/web_contents.h"
23 #include "jni/ForeignSessionHelper_jni.h"
24
25 using base::android::ScopedJavaGlobalRef;
26 using base::android::ScopedJavaLocalRef;
27 using base::android::AttachCurrentThread;
28 using base::android::ConvertUTF16ToJavaString;
29 using base::android::ConvertUTF8ToJavaString;
30 using base::android::ConvertJavaStringToUTF8;
31 using browser_sync::SessionModelAssociator;
32 using browser_sync::SyncedSession;
33
34 namespace {
35
36 SessionModelAssociator* GetSessionModelAssociator(Profile* profile) {
37 ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()->
38 GetForProfile(profile);
39
40 // Only return the associator if it exists and it is done syncing sessions.
41 if (!service || !service->ShouldPushChanges())
42 return NULL;
43
44 return service->GetSessionModelAssociator();
45 }
46
47 void CopyTabsToJava(
48 JNIEnv* env,
49 const SessionWindow* window,
50 ScopedJavaLocalRef<jobject>& j_window) {
51 for (std::vector<SessionTab*>::const_iterator tab_it = window->tabs.begin();
52 tab_it != window->tabs.end(); ++tab_it) {
53 const SessionTab &tab = **tab_it;
54
55 if (tab.navigations.empty())
56 continue;
57
58 const ::sessions::SerializedNavigationEntry& current_navigation =
59 tab.navigations.at(tab.current_navigation_index);
60
61 GURL tab_url = current_navigation.virtual_url();
62 if (tab_url == GURL(chrome::kChromeUINewTabURL))
newt (away) 2013/07/29 22:16:39 is this the behavior we want? this will exclude ch
Kibeom Kim (inactive) 2013/07/29 22:32:21 Done.
63 continue;
64
65 Java_ForeignSessionHelper_pushTab(
66 env, j_window.obj(),
67 ConvertUTF8ToJavaString(env, tab_url.spec()).Release(),
68 ConvertUTF16ToJavaString(env, current_navigation.title()).Release(),
69 tab.timestamp.ToInternalValue(), tab.tab_id.id());
70 }
71 }
72
73 void CopyWindowsToJava(
74 JNIEnv* env,
75 const SyncedSession* session,
76 ScopedJavaLocalRef<jobject>& j_session) {
77 for (SyncedSession::SyncedWindowMap::const_iterator it =
78 session->windows.begin(); it != session->windows.end(); ++it) {
79 const SessionWindow* window = it->second;
80
81 ScopedJavaLocalRef<jobject> last_pushed_window;
82 last_pushed_window.Reset(
83 Java_ForeignSessionHelper_pushWindow(
84 env, j_session.obj(), window->timestamp.ToInternalValue(),
85 window->window_id.id()));
86
87 CopyTabsToJava(env, window, last_pushed_window);
88 }
89 }
90
91 } // namespace
92
93 static jint Init(JNIEnv* env, jclass clazz, jobject profile) {
94 ForeignSessionHelper* foreign_session_helper = new ForeignSessionHelper(
95 ProfileAndroid::FromProfileAndroid(profile));
96 return reinterpret_cast<jint>(foreign_session_helper);
97 }
98
99 ForeignSessionHelper::ForeignSessionHelper(Profile* profile)
100 : profile_(profile) {
101 ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()->
102 GetForProfile(profile);
103
104 registrar_.Add(this, chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
105 content::Source<ProfileSyncService>(service));
106 registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
107 content::Source<Profile>(profile));
108 registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED,
109 content::Source<Profile>(profile));
110 }
111
112 ForeignSessionHelper::~ForeignSessionHelper() {
113 }
114
115 void ForeignSessionHelper::Destroy(JNIEnv* env, jobject obj) {
116 delete this;
117 }
118
119 jboolean ForeignSessionHelper::IsTabSyncEnabled(JNIEnv* env, jobject obj) {
120 ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()->
121 GetForProfile(profile_);
122 return service && service->GetActiveDataTypes().Has(syncer::PROXY_TABS);
123 }
124
125 void ForeignSessionHelper::SetOnForeignSessionCallback(JNIEnv* env,
126 jobject obj,
127 jobject callback) {
128 callback_.Reset(env, callback);
129 }
130
131 void ForeignSessionHelper::Observe(
132 int type, const content::NotificationSource& source,
133 const content::NotificationDetails& details) {
134 if (callback_.is_null())
135 return;
136
137 JNIEnv* env = AttachCurrentThread();
138
139 switch (type) {
140 case chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED:
141 // Tab sync is disabled, so clean up data about collapsed sessions.
142 profile_->GetPrefs()->ClearPref(
143 prefs::kNtpCollapsedForeignSessions);
144 // Purposeful fall through.
145 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE:
146 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED:
147 Java_ForeignSessionCallback_onUpdated(env, callback_.obj());
148 break;
149 default:
150 NOTREACHED();
151 }
152 }
153
154 jboolean ForeignSessionHelper::GetForeignSessions(JNIEnv* env,
155 jobject obj,
156 jobject result) {
157 SessionModelAssociator* associator = GetSessionModelAssociator(profile_);
158 if (!associator)
159 return false;
160
161 std::vector<const browser_sync::SyncedSession*> sessions;
162 if (!associator->GetAllForeignSessions(&sessions))
163 return false;
164
165 // Use a pref to keep track of sessions that were collapsed by the user.
166 // To prevent the pref from accumulating stale sessions, clear it each time
167 // and only add back sessions that are still current.
168 DictionaryPrefUpdate pref_update(profile_->GetPrefs(),
169 prefs::kNtpCollapsedForeignSessions);
170 DictionaryValue* pref_collapsed_sessions = pref_update.Get();
171 scoped_ptr<DictionaryValue> collapsed_sessions(
172 pref_collapsed_sessions->DeepCopy());
173 pref_collapsed_sessions->Clear();
174
175 ScopedJavaLocalRef<jobject> last_pushed_session;
176 ScopedJavaLocalRef<jobject> last_pushed_window;
177
178 // Note: we don't own the SyncedSessions themselves.
179 for (size_t i = 0; i < sessions.size(); ++i) {
180 const browser_sync::SyncedSession* session = sessions[i];
181
182 const bool is_collapsed = collapsed_sessions->HasKey(session->session_tag);
183
184 if (is_collapsed)
185 pref_collapsed_sessions->SetBoolean(session->session_tag, true);
186
187 last_pushed_session.Reset(
188 Java_ForeignSessionHelper_pushSession(
189 env,
190 result,
191 ConvertUTF8ToJavaString(env, session->session_tag).Release(),
192 ConvertUTF8ToJavaString(env, session->session_name).Release(),
193 ConvertUTF8ToJavaString(env,
194 session->DeviceTypeAsString()).Release(),
195 session->modified_time.ToInternalValue()));
196
197 CopyWindowsToJava(env, session, last_pushed_session);
198 }
199
200 return true;
201 }
202
203 jboolean ForeignSessionHelper::OpenForeignSessionTab(JNIEnv* env,
204 jobject obj,
205 jstring session_tag,
206 jint tab_id) {
207 SessionModelAssociator* associator = GetSessionModelAssociator(profile_);
208 if (!associator) {
209 LOG(ERROR) << "Null SessionModelAssociator returned.";
210 return false;
211 }
212
213 const SessionTab* tab;
214
215 if (!associator->GetForeignTab(ConvertJavaStringToUTF8(env, session_tag),
216 tab_id, &tab)) {
217 LOG(ERROR) << "Failed to load foreign tab.";
218 return false;
219 }
220
221 if (tab->navigations.empty()) {
222 LOG(ERROR) << "Foreign tab no longer has valid navigations.";
223 return false;
224 }
225
226 TabModel* tab_model = TabModelList::GetTabModelWithProfile(profile_);
227 DCHECK(tab_model);
228 if (!tab_model)
229 return false;
230
231 std::vector<content::NavigationEntry*> entries =
232 sessions::SerializedNavigationEntry::ToNavigationEntries(
233 tab->navigations, profile_);
234 content::WebContents* new_web_contents = content::WebContents::Create(
235 content::WebContents::CreateParams(profile_));
236 int selected_index = tab->normalized_navigation_index();
237 new_web_contents->GetController().Restore(
238 selected_index,
239 content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY,
240 &entries);
241 tab_model->CreateTab(new_web_contents);
242
243 return true;
244 }
245
246 void ForeignSessionHelper::SetForeignSessionCollapsed(JNIEnv* env, jobject obj,
247 jstring session_tag,
248 jboolean is_collapsed) {
249 // Store session tags for collapsed sessions in a preference so that the
250 // collapsed state persists.
251 PrefService* prefs = profile_->GetPrefs();
252 DictionaryPrefUpdate update(prefs, prefs::kNtpCollapsedForeignSessions);
253 if (is_collapsed)
254 update.Get()->SetBoolean(ConvertJavaStringToUTF8(env, session_tag), true);
255 else
256 update.Get()->Remove(ConvertJavaStringToUTF8(env, session_tag), NULL);
257 }
258
259 void ForeignSessionHelper::DeleteForeignSession(JNIEnv* env, jobject obj,
260 jstring session_tag) {
261 SessionModelAssociator* associator = GetSessionModelAssociator(profile_);
262 if (associator)
263 associator->DeleteForeignSession(ConvertJavaStringToUTF8(env, session_tag));
264 }
265
266 // static
267 bool ForeignSessionHelper::RegisterForeignSessionHelper(JNIEnv* env) {
268 return RegisterNativesImpl(env);
269 }
OLDNEW
« no previous file with comments | « chrome/browser/android/foreign_session_helper.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine