15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'use strict';
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @suppress {duplicate} */
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var remoting = remoting || {};
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @type {remoting.HostSession} */ remoting.hostSession = null;
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @type {base.EventSource} An event source object for handling global events.
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *    This is an interim hack.  Eventually, we should move functionalities
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *    away from the remoting namespace and into smaller objects.
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) */
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)remoting.testEvents;
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch/**
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Show the authorization consent UI and register a one-shot event handler to
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * continue the authorization process.
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {function():void} authContinue Callback to invoke when the user
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *     clicks "Continue".
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function consentRequired_(authContinue) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /** @type {HTMLElement} */
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var dialog = document.getElementById('auth-dialog');
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /** @type {HTMLElement} */
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var button = document.getElementById('auth-button');
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var consentGranted = function(event) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dialog.hidden = true;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    button.removeEventListener('click', consentGranted, false);
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    authContinue();
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dialog.hidden = false;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  button.addEventListener('click', consentGranted, false);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Entry point for app initialization.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.init = function() {
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (base.isAppsV2()) {
452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    var htmlNode = /** @type {HTMLElement} */ (document.body.parentNode);
462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    htmlNode.classList.add('apps-v2');
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  } else {
4858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    migrateLocalToChromeStorage_();
4958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
5058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  console.log(remoting.getExtensionInfo());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  l10n.localize();
5358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create global objects.
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  remoting.ClientPlugin.factory = new remoting.DefaultClientPluginFactory();
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  remoting.SessionConnector.factory =
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new remoting.DefaultSessionConnectorFactory();
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.settings = new remoting.Settings();
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (base.isAppsV2()) {
6058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    remoting.identity = new remoting.Identity(consentRequired_);
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    remoting.fullscreen = new remoting.FullscreenAppsV2();
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    remoting.windowFrame = new remoting.WindowFrame(
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        document.getElementById('title-bar'));
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    remoting.optionsMenu = remoting.windowFrame.createOptionsMenu();
6558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  } else {
6658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    remoting.oauth2 = new remoting.OAuth2();
6758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    if (!remoting.oauth2.isAuthenticated()) {
6858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      document.getElementById('auth-dialog').hidden = false;
6958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    }
7058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    remoting.identity = remoting.oauth2;
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    remoting.fullscreen = new remoting.FullscreenAppsV1();
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    remoting.toolbar = new remoting.Toolbar(
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        document.getElementById('session-toolbar'));
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    remoting.optionsMenu = remoting.toolbar.createOptionsMenu();
7558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.stats = new remoting.ConnectionStats(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.getElementById('statistics'));
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.formatIq = new remoting.FormatIq();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.hostList = new remoting.HostList(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.getElementById('host-list'),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.getElementById('host-list-empty'),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.getElementById('host-list-error-message'),
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      document.getElementById('host-list-refresh-failed-button'),
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      document.getElementById('host-list-loading-indicator'));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.clipboard = new remoting.Clipboard();
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var sandbox = /** @type {HTMLIFrameElement} */
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      document.getElementById('wcs-sandbox');
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.wcsSandbox = new remoting.WcsSandboxContainer(sandbox.contentWindow);
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var homeFeedback = new remoting.MenuButton(
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      document.getElementById('help-feedback-main'));
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var toolbarFeedback = new remoting.MenuButton(
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      document.getElementById('help-feedback-toolbar'));
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  remoting.manageHelpAndFeedback(
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      document.getElementById('title-bar'));
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  remoting.manageHelpAndFeedback(
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      document.getElementById('help-feedback-toolbar'));
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  remoting.manageHelpAndFeedback(
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      document.getElementById('help-feedback-main'));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  /** @param {remoting.Error} error */
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  var onGetEmailError = function(error) {
102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // No need to show the error message for NOT_AUTHENTICATED
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // because we will show "auth-dialog".
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (error != remoting.Error.NOT_AUTHENTICATED) {
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      remoting.showErrorMessage(error);
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  remoting.identity.getEmail(remoting.onEmail, onGetEmailError);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.showOrHideIT2MeUi();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.showOrHideMe2MeUi();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The plugin's onFocus handler sends a paste command to |window|, because
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it can't send one to the plugin element itself.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window.addEventListener('paste', pluginGotPaste_, false);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window.addEventListener('copy', pluginGotCopy_, false);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.initModalDialogs();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (isHostModeSupported_()) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var noShare = document.getElementById('chrome-os-no-share');
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    noShare.parentNode.removeChild(noShare);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var button = document.getElementById('share-button');
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    button.disabled = true;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  /**
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   * @return {Promise} A promise that resolves to the id of the current
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   * containing tab/window.
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   */
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  var getCurrentId = function () {
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (base.isAppsV2()) {
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return Promise.resolve(chrome.app.window.current().id);
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    /**
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * @param {function(*=):void} resolve
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * @param {function(*=):void} reject
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     */
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return new Promise(function(resolve, reject) {
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      /** @param {chrome.Tab} tab */
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      chrome.tabs.getCurrent(function(tab){
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (tab) {
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          resolve(String(tab.id));
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        reject('Cannot retrieve the current tab.');
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      });
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    });
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  };
1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var onLoad = function() {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Parse URL parameters.
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var urlParams = getUrlParameters_();
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ('mode' in urlParams) {
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (urlParams['mode'] === 'me2me') {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        var hostId = urlParams['hostId'];
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        remoting.connectMe2Me(hostId);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      } else if (urlParams['mode'] === 'hangout') {
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        /** @param {*} id */
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        getCurrentId().then(function(id) {
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          /** @type {string} */
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          var accessCode = urlParams['accessCode'];
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          remoting.ensureSessionConnector_();
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          remoting.connector.connectIT2Me(accessCode);
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          document.body.classList.add('hangout-remote-desktop');
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          var senderId = /** @type {string} */ String(id);
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          var hangoutSession = new remoting.HangoutSession(senderId);
1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          hangoutSession.init();
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        });
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // No valid URL parameters, start up normally.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remoting.initHomeScreenUi();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.hostList.load(onLoad);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // For Apps v1, check the tab type to warn the user if they are not getting
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // the best keyboard experience.
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!base.isAppsV2() && !remoting.platformIsMac()) {
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    /** @param {boolean} isWindowed */
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    var onIsWindowed = function(isWindowed) {
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (!isWindowed) {
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        document.getElementById('startup-mode-box-me2me').hidden = false;
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        document.getElementById('startup-mode-box-it2me').hidden = false;
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    };
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    isWindowed_(onIsWindowed);
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  remoting.testEvents = new base.EventSource();
196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  /** @enum {string} */
198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  remoting.testEvents.Names = {
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uiModeChanged: 'uiModeChanged'
200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  };
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  remoting.testEvents.defineEvents(base.values(remoting.testEvents.Names));
2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  remoting.ClientPlugin.factory.preloadPlugin();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Returns whether or not IT2Me is supported via the host NPAPI plugin.
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @return {boolean}
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function isIT2MeSupported_() {
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Currently, IT2Me on Chromebooks is not supported.
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return !remoting.runningOnChromeOS();
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/**
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Returns true if the current platform is fully supported. It's only used when
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * we detect that host native messaging components are not installed. In that
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * case the result of this function determines if the webapp should show the
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * controls that allow to install and enable Me2Me host.
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @return {boolean}
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)remoting.isMe2MeInstallable = function() {
225a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // The chromoting host is currently not installable on ChromeOS.
226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // For Linux, we have a install package for Ubuntu but not other distros.
227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Since we cannot tell from javascript alone the Linux distro the client is
228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // on, we don't show the daemon-control UI for Linux unless the host is
229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // installed.
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return remoting.platformIsWindows() || remoting.platformIsMac();
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/**
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Display the user's email address and allow access to the rest of the app,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * including parsing URL parameters.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} email The user's email address.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.onEmail = function(email) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  document.getElementById('current-email').innerText = email;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  document.getElementById('get-started-it2me').disabled = false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  document.getElementById('get-started-me2me').disabled = false;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * initHomeScreenUi is called if the app is not starting up in session mode,
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * and also if the user cancels pin entry or the connection in session mode.
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.initHomeScreenUi = function() {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.hostController = new remoting.HostController();
252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  document.getElementById('share-button').disabled = !isIT2MeSupported_();
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.setMode(remoting.AppMode.HOME);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.hostSetupDialog =
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new remoting.HostSetupDialog(remoting.hostController);
256a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  var dialog = document.getElementById('paired-clients-list');
257a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  var message = document.getElementById('paired-client-manager-message');
258a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  var deleteAll = document.getElementById('delete-all-paired-clients');
259a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  var close = document.getElementById('close-paired-client-manager-dialog');
260a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  var working = document.getElementById('paired-client-manager-dialog-working');
261a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  var error = document.getElementById('paired-client-manager-dialog-error');
262a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  var noPairedClients = document.getElementById('no-paired-clients');
263a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  remoting.pairedClientManager =
264a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      new remoting.PairedClientManager(remoting.hostController, dialog, message,
265a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                                       deleteAll, close, noPairedClients,
266a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                                       working, error);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Display the cached host list, then asynchronously update and re-display it.
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.updateLocalHostState();
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.hostList.refresh(remoting.updateLocalHostState);
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  remoting.butterBar = new remoting.ButterBar();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
274a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * Fetches local host state and updates the DOM accordingly.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.updateLocalHostState = function() {
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /**
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   * @param {remoting.HostController.State} state Host state.
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  var onHostState = function(state) {
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (state == remoting.HostController.State.STARTED) {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      remoting.hostController.getLocalHostId(onHostId.bind(null, state));
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      onHostId(state, null);
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   * @param {remoting.HostController.State} state Host state.
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   * @param {string?} hostId Host id.
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   */
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  var onHostId = function(state, hostId) {
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    remoting.hostList.setLocalHostStateAndId(state, hostId);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remoting.hostList.display();
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
297a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  /**
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)   * @param {boolean} response True if the feature is present.
299a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   */
300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  var onHasFeatureResponse = function(response) {
301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    /**
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)     * @param {remoting.Error} error
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)     */
304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    var onError = function(error) {
305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      console.error('Failed to get pairing status: ' + error);
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      remoting.pairedClientManager.setPairedClients([]);
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    };
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (response) {
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      remoting.hostController.getPairedClients(
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          remoting.pairedClientManager.setPairedClients.bind(
312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              remoting.pairedClientManager),
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          onError);
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    } else {
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      console.log('Pairing registry not supported by host.');
316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      remoting.pairedClientManager.setPairedClients([]);
317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
319a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  remoting.hostController.hasFeature(
321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      remoting.HostController.Feature.PAIRING_REGISTRY, onHasFeatureResponse);
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  remoting.hostController.getLocalHostState(onHostState);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
326a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch * @return {string} Information about the current extension.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
328a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochremoting.getExtensionInfo = function() {
32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  var v2OrLegacy = base.isAppsV2() ? " (v2)" : " (legacy)";
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var manifest = chrome.runtime.getManifest();
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (manifest && manifest.version) {
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var name = chrome.i18n.getMessage('PRODUCT_NAME');
333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return name + ' version: ' + manifest.version + v2OrLegacy;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
335a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return 'Failed to get product version. Corrupt manifest?';
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Returns Chrome version.
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {string?}
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)remoting.getChromeVersion = function() {
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  var match = new RegExp('Chrome/([0-9.]*)').exec(navigator.userAgent);
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (match && (match.length >= 2)) {
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return match[1];
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return null;
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/**
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * If an IT2Me client or host is active then prompt the user before closing.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If a Me2Me client is active then don't bother, since closing the window is
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the more intuitive way to end a Me2Me session, and re-connecting is easy.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.promptClose = function() {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!remoting.clientSession ||
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      remoting.clientSession.getMode() == remoting.ClientSession.Mode.ME2ME) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return null;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (remoting.currentMode) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case remoting.AppMode.CLIENT_CONNECTING:
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case remoting.AppMode.HOST_WAITING_FOR_CODE:
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case remoting.AppMode.HOST_WAITING_FOR_CONNECTION:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case remoting.AppMode.HOST_SHARED:
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case remoting.AppMode.IN_SESSION:
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT');
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return null;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Sign the user out of Chromoting by clearing (and revoking, if possible) the
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OAuth refresh token.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Also clear all local storage, to avoid leaking information.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.signOut = function() {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.oauth2.clear();
3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  chrome.storage.local.clear();
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.setMode(remoting.AppMode.HOME);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  document.getElementById('auth-dialog').hidden = false;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns whether the app is running on ChromeOS.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if the app is running on ChromeOS.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.runningOnChromeOS = function() {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !!navigator.userAgent.match(/\bCrOS\b/);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Callback function called when the browser window gets a paste operation.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} eventUncast
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function pluginGotPaste_(eventUncast) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var event = /** @type {remoting.ClipboardEvent} */ eventUncast;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event && event.clipboardData) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remoting.clipboard.toHost(event.clipboardData);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Callback function called when the browser window gets a copy operation.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} eventUncast
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function pluginGotCopy_(eventUncast) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var event = /** @type {remoting.ClipboardEvent} */ eventUncast;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event && event.clipboardData) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (remoting.clipboard.toOs(event.clipboardData)) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The default action may overwrite items that we added to clipboardData.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.preventDefault();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns whether Host mode is supported on this platform.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if Host mode is supported.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function isHostModeSupported_() {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently, sharing on Chromebooks is not supported.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !remoting.runningOnChromeOS();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Object.<string, string>} The URL parameters.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function getUrlParameters_() {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var result = {};
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var parts = window.location.search.substring(1).split('&');
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var i = 0; i < parts.length; i++) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var pair = parts[i].split('=');
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result[pair[0]] = decodeURIComponent(pair[1]);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} jsonString A JSON-encoded string.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {*} The decoded object, or undefined if the string cannot be parsed.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function jsonParseSafe(jsonString) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  try {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return JSON.parse(jsonString);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } catch (err) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return undefined;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the current time as a formatted string suitable for logging.
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} The current time, formatted as [mmdd/hhmmss.xyz]
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.timestamp = function() {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} num A number.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} len The required length of the answer.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {string} The number, formatted as a string of the specified length
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     by prepending zeroes as necessary.
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var pad = function(num, len) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var result = num.toString();
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result.length < len) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = new Array(len - result.length + 1).join('0') + result;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var now = new Date();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var timestamp = pad(now.getMonth() + 1, 2) + pad(now.getDate(), 2) + '/' +
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pad(now.getHours(), 2) + pad(now.getMinutes(), 2) +
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pad(now.getSeconds(), 2) + '.' + pad(now.getMilliseconds(), 3);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return '[' + timestamp + ']';
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Show an error message, optionally including a short-cut for signing in to
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Chromoting again.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {remoting.Error} error
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.showErrorMessage = function(error) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  l10n.localizeElementFromTag(
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.getElementById('token-refresh-error-message'),
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var auth_failed = (error == remoting.Error.AUTHENTICATION_FAILED);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  document.getElementById('token-refresh-auth-failed').hidden = !auth_failed;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  document.getElementById('token-refresh-other-error').hidden = auth_failed;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.setMode(remoting.AppMode.TOKEN_REFRESH_FAILED);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Determine whether or not the app is running in a window.
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {function(boolean):void} callback Callback to receive whether or not
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *     the current tab is running in windowed mode.
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function isWindowed_(callback) {
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /** @param {chrome.Window} win The current window. */
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var windowCallback = function(win) {
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback(win.type == 'popup');
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /** @param {chrome.Tab} tab The current tab. */
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var tabCallback = function(tab) {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (tab.pinned) {
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback(false);
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome.windows.get(tab.windowId, null, windowCallback);
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (chrome.tabs) {
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome.tabs.getCurrent(tabCallback);
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    console.error('chome.tabs is not available.');
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Migrate settings in window.localStorage to chrome.storage.local so that
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * users of older web-apps that used the former do not lose their settings.
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function migrateLocalToChromeStorage_() {
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The OAuth2 class still uses window.localStorage, so don't migrate any of
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // those settings.
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var oauthSettings = [
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      'oauth2-refresh-token',
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      'oauth2-refresh-token-revokable',
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      'oauth2-access-token',
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      'oauth2-xsrf-token',
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      'remoting-email'
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ];
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (var setting in window.localStorage) {
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (oauthSettings.indexOf(setting) == -1) {
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      var copy = {}
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      copy[setting] = window.localStorage.getItem(setting);
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome.storage.local.set(copy);
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window.localStorage.removeItem(setting);
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Generate a nonce, to be used as an xsrf protection token.
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return {string} A URL-Safe Base64-encoded 128-bit random value. */
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)remoting.generateXsrfToken = function() {
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var random = new Uint8Array(16);
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  window.crypto.getRandomValues(random);
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var base64Token = window.btoa(String.fromCharCode.apply(null, random));
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base64Token.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Tests whether we are running on Mac.
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *
5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {boolean} True if the platform is Mac.
5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)remoting.platformIsMac = function() {
5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return navigator.platform.indexOf('Mac') != -1;
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Tests whether we are running on Windows.
5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {boolean} True if the platform is Windows.
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)remoting.platformIsWindows = function() {
57703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return (navigator.platform.indexOf('Win32') != -1) ||
57803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         (navigator.platform.indexOf('Win64') != -1);
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Tests whether we are running on Linux.
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {boolean} True if the platform is Linux.
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)remoting.platformIsLinux = function() {
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (navigator.platform.indexOf('Linux') != -1) &&
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         !remoting.platformIsChromeOS();
5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Tests whether we are running on ChromeOS.
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {boolean} True if the platform is ChromeOS.
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)remoting.platformIsChromeOS = function() {
5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return navigator.userAgent.match(/\bCrOS\b/) != null;
5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
599