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 package org.chromium.chrome.browser; 6 7 import org.chromium.base.CalledByNative; 8 import org.chromium.chrome.browser.profiles.Profile; 9 10 import java.util.ArrayList; 11 import java.util.Collections; 12 import java.util.Comparator; 13 import java.util.List; 14 15 /** 16 * This class exposes to Java information about sessions, windows, and tabs on the user's synced 17 * devices. 18 */ 19 public class ForeignSessionHelper { 20 private long mNativeForeignSessionHelper; 21 22 /** 23 * Callback interface for getting notified when foreign session sync is updated. 24 */ 25 public interface ForeignSessionCallback { 26 /** 27 * This method will be called every time foreign session sync is updated. 28 * 29 * It's a good place to call {@link ForeignSessionHelper#getForeignSessions()} to get the 30 * updated information. 31 */ 32 @CalledByNative("ForeignSessionCallback") 33 public void onUpdated(); 34 } 35 36 /** 37 * Represents synced foreign session. 38 */ 39 public static class ForeignSession { 40 // Please keep in sync with synced_session.h 41 public static final int DEVICE_TYPE_UNSET = 0; 42 public static final int DEVICE_TYPE_WIN = 1; 43 public static final int DEVICE_TYPE_MACOSX = 2; 44 public static final int DEVICE_TYPE_LINUX = 3; 45 public static final int DEVICE_TYPE_CHROMEOS = 4; 46 public static final int DEVICE_TYPE_OTHER = 5; 47 public static final int DEVICE_TYPE_PHONE = 6; 48 public static final int DEVICE_TYPE_TABLET = 7; 49 50 public final String tag; 51 public final String name; 52 public final int deviceType; 53 public final long modifiedTime; 54 public final List<ForeignSessionWindow> windows = new ArrayList<ForeignSessionWindow>(); 55 56 private ForeignSession(String tag, String name, int deviceType, long modifiedTime) { 57 this.tag = tag; 58 this.name = name; 59 this.deviceType = deviceType; 60 this.modifiedTime = modifiedTime; 61 } 62 } 63 64 /** 65 * Represents synced foreign window. Note that desktop Chrome can have multiple windows in a 66 * session. 67 */ 68 public static class ForeignSessionWindow { 69 public final long timestamp; 70 public final int sessionId; 71 public final List<ForeignSessionTab> tabs = new ArrayList<ForeignSessionTab>(); 72 73 private ForeignSessionWindow(long timestamp, int sessionId) { 74 this.timestamp = timestamp; 75 this.sessionId = sessionId; 76 } 77 } 78 79 /** 80 * Represents synced foreign tab. 81 */ 82 public static class ForeignSessionTab { 83 public final String url; 84 public final String title; 85 public final long timestamp; 86 public final int id; 87 88 private ForeignSessionTab(String url, String title, long timestamp, int id) { 89 this.url = url; 90 this.title = title; 91 this.timestamp = timestamp; 92 this.id = id; 93 } 94 } 95 96 @CalledByNative 97 private static ForeignSession pushSession( 98 List<ForeignSession> sessions, String tag, String name, int deviceType, 99 long modifiedTime) { 100 ForeignSession session = new ForeignSession(tag, name, deviceType, modifiedTime); 101 sessions.add(session); 102 return session; 103 } 104 105 @CalledByNative 106 private static ForeignSessionWindow pushWindow( 107 ForeignSession session, long timestamp, int sessionId) { 108 ForeignSessionWindow window = new ForeignSessionWindow(timestamp, sessionId); 109 session.windows.add(window); 110 return window; 111 } 112 113 @CalledByNative 114 private static void pushTab( 115 ForeignSessionWindow window, String url, String title, long timestamp, int sessionId) { 116 ForeignSessionTab tab = new ForeignSessionTab(url, title, timestamp, sessionId); 117 window.tabs.add(tab); 118 } 119 120 /** 121 * Initialize this class with the given profile. 122 * @param profile Profile that will be used for syncing. 123 */ 124 public ForeignSessionHelper(Profile profile) { 125 mNativeForeignSessionHelper = nativeInit(profile); 126 } 127 128 /** 129 * Clean up the C++ side of this class. After the call, this class instance shouldn't be used. 130 */ 131 public void destroy() { 132 assert mNativeForeignSessionHelper != 0; 133 nativeDestroy(mNativeForeignSessionHelper); 134 mNativeForeignSessionHelper = 0; 135 } 136 137 @Override 138 protected void finalize() { 139 // Just to make sure that we called destroy() before the java garbage collection picks up. 140 assert mNativeForeignSessionHelper == 0; 141 } 142 143 /** 144 * @return {@code True} iff Tab sync is enabled. 145 */ 146 public boolean isTabSyncEnabled() { 147 return nativeIsTabSyncEnabled(mNativeForeignSessionHelper); 148 } 149 150 /** 151 * Sets callback instance that will be called on every foreign session sync update. 152 * @param callback The callback to be invoked. 153 */ 154 public void setOnForeignSessionCallback(ForeignSessionCallback callback) { 155 nativeSetOnForeignSessionCallback(mNativeForeignSessionHelper, callback); 156 } 157 158 /** 159 * @return The list of synced foreign sessions. {@code null} iff it fails to get them for some 160 * reason. 161 */ 162 public List<ForeignSession> getForeignSessions() { 163 List<ForeignSession> result = new ArrayList<ForeignSession>(); 164 boolean received = nativeGetForeignSessions(mNativeForeignSessionHelper, result); 165 if (received) { 166 // Sort sessions from most recent to least recent. 167 Collections.sort(result, new Comparator<ForeignSession>() { 168 @Override 169 public int compare(ForeignSession lhs, ForeignSession rhs) { 170 return lhs.modifiedTime < rhs.modifiedTime ? 1 : 171 (lhs.modifiedTime == rhs.modifiedTime ? 0 : -1); 172 } 173 }); 174 } else { 175 result = null; 176 } 177 178 return result; 179 } 180 181 /** 182 * Opens the given foreign tab in a new tab. 183 * @param tab Tab to load the session into. 184 * @param session Session that the target tab belongs to. 185 * @param foreignTab Target tab to open. 186 * @param windowOpenDisposition The WindowOpenDisposition flag. 187 * @return {@code True} iff the tab is successfully opened. 188 */ 189 public boolean openForeignSessionTab(Tab tab, ForeignSession session, 190 ForeignSessionTab foreignTab, int windowOpenDisposition) { 191 return nativeOpenForeignSessionTab(mNativeForeignSessionHelper, tab, session.tag, 192 foreignTab.id, windowOpenDisposition); 193 } 194 195 /** 196 * Remove Foreign session to display. Note that it will be reappear on the next sync. 197 * 198 * This is mainly for when user wants to delete very old session that won't be used or syned in 199 * the future. 200 * @param session Session to be deleted. 201 */ 202 public void deleteForeignSession(ForeignSession session) { 203 nativeDeleteForeignSession(mNativeForeignSessionHelper, session.tag); 204 } 205 206 private static native long nativeInit(Profile profile); 207 private static native void nativeDestroy(long nativeForeignSessionHelper); 208 private static native boolean nativeIsTabSyncEnabled(long nativeForeignSessionHelper); 209 private static native void nativeSetOnForeignSessionCallback( 210 long nativeForeignSessionHelper, ForeignSessionCallback callback); 211 private static native boolean nativeGetForeignSessions(long nativeForeignSessionHelper, 212 List<ForeignSession> resultSessions); 213 private static native boolean nativeOpenForeignSessionTab( 214 long nativeForeignSessionHelper, Tab tab, String sessionTag, int tabId, 215 int disposition); 216 private static native void nativeDeleteForeignSession( 217 long nativeForeignSessionHelper, String sessionTag); 218 } 219