Home | History | Annotate | Download | only in browser
      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