Javascript  |  218行  |  6.38 KB

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

/**
 * @param {Object.<string, string>} stringData String data.
 * @param {VolumeManager} volumeManager Volume manager.
 */
function BackgroundComponents(stringData, volumeManager) {
  /**
   * String data.
   * @type {Object.<string, string>}
   */
  this.stringData = stringData;

  /**
   * Volume manager.
   * @type {VolumeManager}
   */
  this.volumeManager = volumeManager;

  Object.freeze(this);
}

/**
 * Loads background component.
 * @return {Promise} Promise fulfilled with BackgroundComponents.
 */
BackgroundComponents.load = function() {
  var stringDataPromise = new Promise(function(fulfill) {
    chrome.fileManagerPrivate.getStrings(function(stringData) {
      loadTimeData.data = stringData;
      fulfill(stringData);
    });
  });

  // VolumeManager should be obtained after stringData initialized.
  var volumeManagerPromise = stringDataPromise.then(function() {
    return new Promise(function(fulfill) {
      VolumeManager.getInstance(fulfill);
    });
  });

  return Promise.all([stringDataPromise, volumeManagerPromise]).then(
      function(args) {
        return new BackgroundComponents(args[0], args[1]);
      });
};

/**
 * Promise to be fulfilled with singleton instance of background components.
 * @type {Promise}
 */
var backgroundComponentsPromise = BackgroundComponents.load();

/**
 * Resolves file system names and obtains entries.
 * @param {Array.<FileEntry>} entries Names of isolated file system.
 * @return {Promise} Promise to be fulfilled with an entry array.
 */
function resolveEntries(entries) {
  return new Promise(function(fulfill, reject) {
    chrome.fileManagerPrivate.resolveIsolatedEntries(
        entries, function(externalEntries) {
          if (!chrome.runtime.lastError)
            fulfill(externalEntries);
          else
            reject(chrome.runtime.lastError);
        });
  });
}

/**
 * Obtains child entries.
 * @param {DirectoryEntry} entry Directory entry.
 * @return {Promise} Promise to be fulfilled with child entries.
 */
function getChildren(entry) {
  var reader = entry.createReader();
  var readEntries = function() {
    return new Promise(reader.readEntries.bind(reader)).then(function(entries) {
      if (entries.length === 0)
        return [];
      return readEntries().then(function(nextEntries) {
        return entries.concat(nextEntries);
      });
    });
  };
  return readEntries().then(function(entries) {
    return entries.sort(function(a, b) {
      return a.name.localeCompare(b.name);
    });
  });
}

/**
 * Promise to be fulfilled with single application window.
 * This can be null when the window is not opened.
 * @type {Promise}
 */
var appWindowPromise = null;

/**
 * Promise to be fulfilled with entries that are used for reopening the
 * application window.
 * @type {Promise}
 */
var reopenEntriesPromsie = null;

/**
 * Launches the application with entries.
 *
 * @param {Promise} selectedEntriesPromise Promise to be fulfilled with the
 *     entries that are stored in the external file system (not in the isolated
 *     file system).
 * @return {Promise} Promise to be fulfilled after the application is launched.
 */
function launch(selectedEntriesPromise) {
  // If there is the previous window, close the window.
  if (appWindowPromise) {
    reopenEntriesPromsie = selectedEntriesPromise;
    appWindowPromise.then(function(appWindow) {
      appWindow.close();
    });
    return Promise.reject('The window has already opened.');
  }
  reopenEntriesPromsie = null;

  // Create a new window.
  appWindowPromise = new Promise(function(fulfill) {
    chrome.app.window.create(
        'gallery.html',
        {
          id: 'gallery',
          innerBounds: {
            minWidth: 820,
            minHeight: 544
          },
          frame: 'none'
        },
        function(appWindow) {
          appWindow.contentWindow.addEventListener(
              'load', fulfill.bind(null, appWindow));
          appWindow.onClosed.addListener(function() {
            appWindowPromise = null;
            if (reopenEntriesPromsie)
              launch(reopenEntriesPromsie);
          });
        });
  });

  // If only 1 entry is selected, retrieve entries in the same directory.
  // Otherwise, just use the selectedEntries as an entry set.
  var allEntriesPromise = selectedEntriesPromise.then(function(entries) {
    if (entries.length === 1) {
      var parentPromise = new Promise(entries[0].getParent.bind(entries[0]));
      return parentPromise.then(getChildren).then(function(entries) {
        return entries.filter(FileType.isImage);
      });
    } else {
      return entries;
    }
  });

  // Initialize the window document.
  return Promise.all([
    appWindowPromise,
    backgroundComponentsPromise,
  ]).then(function(args) {
    args[0].contentWindow.initialize(args[1]);
    return Promise.all([
      allEntriesPromise,
      selectedEntriesPromise
    ]).then(function(entries) {
      args[0].contentWindow.loadEntries(entries[0], entries[1]);
    });
  });
}

chrome.app.runtime.onLaunched.addListener(function(launchData) {
  // Skip if files are not selected.
  if (!launchData || !launchData.items || launchData.items.length === 0)
    return;

  // Obtains entries in non-isolated file systems.
  // The entries in launchData are stored in the isolated file system.
  // We need to map the isolated entries to the normal entries to retrieve their
  // parent directory.
  var isolatedEntries = launchData.items.map(function(item) {
    return item.entry;
  });
  var selectedEntriesPromise = backgroundComponentsPromise.then(function() {
    return resolveEntries(isolatedEntries);
  });

  launch(selectedEntriesPromise).catch(function(error) {
    console.error(error.stack || error);
  });
});

// If is is run in the browser test, wait for the test resources are installed
// as a component extension, and then load the test resources.
if (chrome.test) {
  /** @type {string} */
  window.testExtensionId = 'ejhcmmdhhpdhhgmifplfmjobgegbibkn';
  chrome.runtime.onMessageExternal.addListener(function(message) {
    if (message.name !== 'testResourceLoaded')
      return;
    var script = document.createElement('script');
    script.src =
        'chrome-extension://' + window.testExtensionId +
        '/common/test_loader.js';
    document.documentElement.appendChild(script);
  });
}