Index: chrome/browser/resources/file_manager/js/background.js |
diff --git a/chrome/browser/resources/file_manager/js/background.js b/chrome/browser/resources/file_manager/js/background.js |
deleted file mode 100644 |
index f531f3b00bb9f85bb9fbc7238235f1f28cecd247..0000000000000000000000000000000000000000 |
--- a/chrome/browser/resources/file_manager/js/background.js |
+++ /dev/null |
@@ -1,607 +0,0 @@ |
-// Copyright (c) 2012 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'; |
- |
-/** |
- * Number of runtime errors catched in the background page. |
- * @type {number} |
- */ |
-var JSErrorCount = 0; |
- |
-/** |
- * Map of all currently open app window. The key is an app id. |
- * @type {Object.<string, AppWindow>} |
- */ |
-var appWindows = {}; |
- |
-/** |
- * Synchronous queue for asynchronous calls. |
- * @type {AsyncUtil.Queue} |
- */ |
-var queue = new AsyncUtil.Queue(); |
- |
-/** |
- * Type of a Files.app's instance launch. |
- * @enum {number} |
- */ |
-var LaunchType = Object.freeze({ |
- ALWAYS_CREATE: 0, |
- FOCUS_ANY_OR_CREATE: 1, |
- FOCUS_SAME_OR_CREATE: 2 |
-}); |
- |
-/** |
- * Wrapper for an app window. |
- * |
- * Expects the following from the app scripts: |
- * 1. The page load handler should initialize the app using |window.appState| |
- * and call |util.platform.saveAppState|. |
- * 2. Every time the app state changes the app should update |window.appState| |
- * and call |util.platform.saveAppState| . |
- * 3. The app may have |unload| function to persist the app state that does not |
- * fit into |window.appState|. |
- * |
- * @param {string} url App window content url. |
- * @param {string} id App window id. |
- * @param {Object} options Options object to create it. |
- * @constructor |
- */ |
-function AppWindowWrapper(url, id, options) { |
- this.url_ = url; |
- this.id_ = id; |
- // Do deep copy for the template of options to assign own ID to the option |
- // params. |
- this.options_ = JSON.parse(JSON.stringify(options)); |
- this.options_.id = url; // This is to make Chrome reuse window geometries. |
- this.window_ = null; |
- this.appState_ = null; |
- this.openingOrOpened_ = false; |
- this.queue = new AsyncUtil.Queue(); |
- Object.seal(this); |
-} |
- |
-/** |
- * Shift distance to avoid overlapping windows. |
- * @type {number} |
- * @const |
- */ |
-AppWindowWrapper.SHIFT_DISTANCE = 40; |
- |
-/** |
- * Gets similar windows, it means with the same initial url. |
- * @return {Array.<AppWindow>} List of similar windows. |
- * @private |
- */ |
-AppWindowWrapper.prototype.getSimilarWindows_ = function() { |
- var result = []; |
- for (var appID in appWindows) { |
- if (appWindows[appID].contentWindow.appInitialURL == this.url_) |
- result.push(appWindows[appID]); |
- } |
- return result; |
-}; |
- |
-/** |
- * Opens the window. |
- * |
- * @param {Object} appState App state. |
- * @param {function()=} opt_callback Completion callback. |
- */ |
-AppWindowWrapper.prototype.launch = function(appState, opt_callback) { |
- // Check if the window is opened or not. |
- if (this.openingOrOpened_) { |
- console.error('The window is already opened.'); |
- if (opt_callback) |
- opt_callback(); |
- return; |
- } |
- this.openingOrOpened_ = true; |
- |
- // Save application state. |
- this.appState_ = appState; |
- |
- // Get similar windows, it means with the same initial url, eg. different |
- // main windows of Files.app. |
- var similarWindows = this.getSimilarWindows_(); |
- |
- // Restore maximized windows, to avoid hiding them to tray, which can be |
- // confusing for users. |
- this.queue.run(function(nextStep) { |
- for (var index = 0; index < similarWindows.length; index++) { |
- if (similarWindows[index].isMaximized()) { |
- var createWindowAndRemoveListener = function() { |
- similarWindows[index].onRestored.removeListener( |
- createWindowAndRemoveListener); |
- nextStep(); |
- }; |
- similarWindows[index].onRestored.addListener( |
- createWindowAndRemoveListener); |
- similarWindows[index].restore(); |
- return; |
- } |
- } |
- // If no maximized windows, then create the window immediately. |
- nextStep(); |
- }); |
- |
- // Closure creating the window, once all preprocessing tasks are finished. |
- this.queue.run(function(nextStep) { |
- chrome.app.window.create(this.url_, this.options_, function(appWindow) { |
- this.window_ = appWindow; |
- nextStep(); |
- }.bind(this)); |
- }.bind(this)); |
- |
- // After creating. |
- this.queue.run(function(nextStep) { |
- var appWindow = this.window_; |
- if (similarWindows.length) { |
- // If we have already another window of the same kind, then shift this |
- // window to avoid overlapping with the previous one. |
- |
- var bounds = appWindow.getBounds(); |
- appWindow.moveTo(bounds.left + AppWindowWrapper.SHIFT_DISTANCE, |
- bounds.top + AppWindowWrapper.SHIFT_DISTANCE); |
- } |
- |
- appWindows[this.id_] = appWindow; |
- var contentWindow = appWindow.contentWindow; |
- contentWindow.appID = this.id_; |
- contentWindow.appState = this.appState_; |
- contentWindow.appInitialURL = this.url_; |
- if (window.IN_TEST) |
- contentWindow.IN_TEST = true; |
- |
- appWindow.onClosed.addListener(function() { |
- if (contentWindow.unload) |
- contentWindow.unload(); |
- if (contentWindow.saveOnExit) { |
- contentWindow.saveOnExit.forEach(function(entry) { |
- util.AppCache.update(entry.key, entry.value); |
- }); |
- } |
- delete appWindows[this.id_]; |
- chrome.storage.local.remove(this.id_); // Forget the persisted state. |
- this.window_ = null; |
- this.openingOrOpened_ = false; |
- maybeCloseBackgroundPage(); |
- }.bind(this)); |
- |
- if (opt_callback) |
- opt_callback(); |
- |
- nextStep(); |
- }.bind(this)); |
-}; |
- |
-/** |
- * Wrapper for a singleton app window. |
- * |
- * In addition to the AppWindowWrapper requirements the app scripts should |
- * have |reload| method that re-initializes the app based on a changed |
- * |window.appState|. |
- * |
- * @param {string} url App window content url. |
- * @param {Object|function()} options Options object or a function to return it. |
- * @constructor |
- */ |
-function SingletonAppWindowWrapper(url, options) { |
- AppWindowWrapper.call(this, url, url, options); |
-} |
- |
-/** |
- * Inherits from AppWindowWrapper. |
- */ |
-SingletonAppWindowWrapper.prototype = {__proto__: AppWindowWrapper.prototype}; |
- |
-/** |
- * Open the window. |
- * |
- * Activates an existing window or creates a new one. |
- * |
- * @param {Object} appState App state. |
- * @param {function()=} opt_callback Completion callback. |
- */ |
-SingletonAppWindowWrapper.prototype.launch = function(appState, opt_callback) { |
- // If the window is not opened yet, just call the parent method. |
- if (!this.openingOrOpened_) { |
- AppWindowWrapper.prototype.launch.call(this, appState, opt_callback); |
- return; |
- } |
- |
- // If the window is already opened, reload the window. |
- // The queue is used to wait until the window is opened. |
- this.queue.run(function(nextStep) { |
- this.window_.contentWindow.appState = appState; |
- this.window_.contentWindow.reload(); |
- this.window_.focus(); |
- if (opt_callback) |
- opt_callback(); |
- nextStep(); |
- }.bind(this)); |
-}; |
- |
-/** |
- * Reopen a window if its state is saved in the local storage. |
- */ |
-SingletonAppWindowWrapper.prototype.reopen = function() { |
- chrome.storage.local.get(this.id_, function(items) { |
- var value = items[this.id_]; |
- if (!value) |
- return; // No app state persisted. |
- |
- try { |
- var appState = JSON.parse(value); |
- } catch (e) { |
- console.error('Corrupt launch data for ' + this.id_, value); |
- return; |
- } |
- this.launch(appState); |
- }.bind(this)); |
-}; |
- |
-/** |
- * Prefix for the file manager window ID. |
- */ |
-var FILES_ID_PREFIX = 'files#'; |
- |
-/** |
- * Regexp matching a file manager window ID. |
- */ |
-var FILES_ID_PATTERN = new RegExp('^' + FILES_ID_PREFIX + '(\\d*)$'); |
- |
-/** |
- * Value of the next file manager window ID. |
- */ |
-var nextFileManagerWindowID = 0; |
- |
-/** |
- * File manager window create options. |
- * @type {Object} |
- * @const |
- */ |
-var FILE_MANAGER_WINDOW_CREATE_OPTIONS = Object.freeze({ |
- defaultLeft: Math.round(window.screen.availWidth * 0.1), |
- defaultTop: Math.round(window.screen.availHeight * 0.1), |
- defaultWidth: Math.round(window.screen.availWidth * 0.8), |
- defaultHeight: Math.round(window.screen.availHeight * 0.8), |
- minWidth: 320, |
- minHeight: 240, |
- frame: 'none', |
- hidden: true, |
- transparentBackground: true, |
- singleton: false |
-}); |
- |
-/** |
- * @param {Object=} opt_appState App state. |
- * @param {number=} opt_id Window id. |
- * @param {LaunchType=} opt_type Launch type. Default: ALWAYS_CREATE. |
- * @param {function(string)=} opt_callback Completion callback with the App ID. |
- */ |
-function launchFileManager(opt_appState, opt_id, opt_type, opt_callback) { |
- var type = opt_type || LaunchType.ALWAYS_CREATE; |
- |
- // Wait until all windows are created. |
- queue.run(function(onTaskCompleted) { |
- // Check if there is already a window with the same path. If so, then |
- // reuse it instead of opening a new one. |
- if (type == LaunchType.FOCUS_SAME_OR_CREATE || |
- type == LaunchType.FOCUS_ANY_OR_CREATE) { |
- if (opt_appState && opt_appState.defaultPath) { |
- for (var key in appWindows) { |
- var contentWindow = appWindows[key].contentWindow; |
- if (contentWindow.appState && |
- opt_appState.defaultPath == contentWindow.appState.defaultPath) { |
- appWindows[key].focus(); |
- if (opt_callback) |
- opt_callback(key); |
- onTaskCompleted(); |
- return; |
- } |
- } |
- } |
- } |
- |
- // Focus any window if none is focused. Try restored first. |
- if (type == LaunchType.FOCUS_ANY_OR_CREATE) { |
- // If there is already a focused window, then finish. |
- for (var key in appWindows) { |
- // The isFocused() method should always be available, but in case |
- // Files.app's failed on some error, wrap it with try catch. |
- try { |
- if (appWindows[key].contentWindow.isFocused()) { |
- if (opt_callback) |
- opt_callback(key); |
- onTaskCompleted(); |
- return; |
- } |
- } catch (e) { |
- console.error(e.message); |
- } |
- } |
- // Try to focus the first non-minimized window. |
- for (var key in appWindows) { |
- if (!appWindows[key].isMinimized()) { |
- appWindows[key].focus(); |
- if (opt_callback) |
- opt_callback(key); |
- onTaskCompleted(); |
- return; |
- } |
- } |
- // Restore and focus any window. |
- for (var key in appWindows) { |
- appWindows[key].focus(); |
- if (opt_callback) |
- opt_callback(key); |
- onTaskCompleted(); |
- return; |
- } |
- } |
- |
- // Create a new instance in case of ALWAYS_CREATE type, or as a fallback |
- // for other types. |
- |
- var id = opt_id || nextFileManagerWindowID; |
- nextFileManagerWindowID = Math.max(nextFileManagerWindowID, id + 1); |
- var appId = FILES_ID_PREFIX + id; |
- |
- var appWindow = new AppWindowWrapper( |
- 'main.html', |
- appId, |
- FILE_MANAGER_WINDOW_CREATE_OPTIONS); |
- appWindow.launch(opt_appState || {}, function() { |
- if (opt_callback) |
- opt_callback(appId); |
- onTaskCompleted(); |
- }); |
- }); |
-} |
- |
-/** |
- * Relaunch file manager windows based on the persisted state. |
- */ |
-function reopenFileManagers() { |
- chrome.storage.local.get(function(items) { |
- for (var key in items) { |
- if (items.hasOwnProperty(key)) { |
- var match = key.match(FILES_ID_PATTERN); |
- if (match) { |
- var id = Number(match[1]); |
- try { |
- var appState = JSON.parse(items[key]); |
- launchFileManager(appState, id); |
- } catch (e) { |
- console.error('Corrupt launch data for ' + id); |
- } |
- } |
- } |
- } |
- }); |
-} |
- |
-/** |
- * Executes a file browser task. |
- * |
- * @param {string} action Task id. |
- * @param {Object} details Details object. |
- */ |
-function onExecute(action, details) { |
- var urls = details.entries.map(function(e) { return e.toURL(); }); |
- |
- switch (action) { |
- case 'play': |
- launchAudioPlayer({items: urls, position: 0}); |
- break; |
- |
- case 'watch': |
- launchVideoPlayer(urls[0]); |
- break; |
- |
- default: |
- var launchEnable = null; |
- var queue = new AsyncUtil.Queue(); |
- queue.run(function(nextStep) { |
- // If it is not auto-open (triggered by mounting external devices), we |
- // always launch Files.app. |
- if (action != 'auto-open') { |
- launchEnable = true; |
- nextStep(); |
- return; |
- } |
- // If the disable-default-apps flag is on, Files.app is not opened |
- // automatically on device mount because it obstculs the manual test. |
- chrome.commandLinePrivate.hasSwitch('disable-default-apps', |
- function(flag) { |
- launchEnable = !flag; |
- nextStep(); |
- }); |
- }); |
- queue.run(function(nextStep) { |
- if (!launchEnable) { |
- nextStep(); |
- return; |
- } |
- |
- // Every other action opens a Files app window. |
- var appState = { |
- params: { |
- action: action |
- }, |
- defaultPath: details.entries[0].fullPath |
- }; |
- // For mounted devices just focus any Files.app window. The mounted |
- // volume will appear on the navigation list. |
- var type = action == 'auto-open' ? LaunchType.FOCUS_ANY_OR_CREATE : |
- LaunchType.FOCUS_SAME_OR_CREATE; |
- launchFileManager(appState, /* App ID */ undefined, type, nextStep); |
- }); |
- break; |
- } |
-} |
- |
-/** |
- * Audio player window create options. |
- * @type {Object} |
- * @const |
- */ |
-var AUDIO_PLAYER_CREATE_OPTIONS = Object.freeze({ |
- type: 'panel', |
- hidden: true, |
- minHeight: 35 + 58, |
- minWidth: 280, |
- height: 35 + 58, |
- width: 280, |
- singleton: false |
-}); |
- |
-var audioPlayer = new SingletonAppWindowWrapper('mediaplayer.html', |
- AUDIO_PLAYER_CREATE_OPTIONS); |
- |
-/** |
- * Launch the audio player. |
- * @param {Object} playlist Playlist. |
- */ |
-function launchAudioPlayer(playlist) { |
- audioPlayer.launch(playlist); |
-} |
- |
-var videoPlayer = new SingletonAppWindowWrapper('video_player.html', |
- {hidden: true}); |
- |
-/** |
- * Launch the video player. |
- * @param {string} url Video url. |
- */ |
-function launchVideoPlayer(url) { |
- videoPlayer.launch({url: url}); |
-} |
- |
-/** |
- * Launches the app. |
- */ |
-function onLaunched() { |
- if (nextFileManagerWindowID == 0) { |
- // The app just launched. Remove window state records that are not needed |
- // any more. |
- chrome.storage.local.get(function(items) { |
- for (var key in items) { |
- if (items.hasOwnProperty(key)) { |
- if (key.match(FILES_ID_PATTERN)) |
- chrome.storage.local.remove(key); |
- } |
- } |
- }); |
- } |
- |
- launchFileManager(); |
-} |
- |
-/** |
- * Restarted the app, restore windows. |
- */ |
-function onRestarted() { |
- reopenFileManagers(); |
- audioPlayer.reopen(); |
- videoPlayer.reopen(); |
-} |
- |
-/** |
- * Handles clicks on a custom item on the launcher context menu. |
- * @param {OnClickData} info Event details. |
- */ |
-function onContextMenuClicked(info) { |
- if (info.menuItemId == 'new-window') { |
- // Find the focused window (if any) and use it's current path for the |
- // new window. If not found, then launch with the default path. |
- for (var key in appWindows) { |
- try { |
- if (appWindows[key].contentWindow.isFocused()) { |
- var appState = { |
- defaultPath: appWindows[key].contentWindow.appState.defaultPath |
- }; |
- launchFileManager(appState); |
- return; |
- } |
- } catch (ignore) { |
- // The isFocused method may not be defined during initialization. |
- // Therefore, wrapped with a try-catch block. |
- } |
- } |
- |
- // Launch with the default path. |
- launchFileManager(); |
- } |
-} |
- |
-/** |
- * Closes the background page, if it is not needed. |
- */ |
-function maybeCloseBackgroundPage() { |
- if (Object.keys(appWindows).length === 0 && |
- !FileOperationManager.getInstance().hasQueuedTasks()) |
- close(); |
-} |
- |
-/** |
- * Initializes the context menu. Recreates if already exists. |
- * @param {Object} strings Hash array of strings. |
- */ |
-function initContextMenu(strings) { |
- try { |
- chrome.contextMenus.remove('new-window'); |
- } catch (ignore) { |
- // There is no way to detect if the context menu is already added, therefore |
- // try to recreate it every time. |
- } |
- chrome.contextMenus.create({ |
- id: 'new-window', |
- contexts: ['launcher'], |
- title: strings['NEW_WINDOW_BUTTON_LABEL'] |
- }); |
-} |
- |
-/** |
- * Initializes the background page of Files.app. |
- */ |
-function initApp() { |
- // Initialize handlers. |
- chrome.fileBrowserHandler.onExecute.addListener(onExecute); |
- chrome.app.runtime.onLaunched.addListener(onLaunched); |
- chrome.app.runtime.onRestarted.addListener(onRestarted); |
- chrome.contextMenus.onClicked.addListener(onContextMenuClicked); |
- |
- // Fetch strings and initialize the context menu. |
- queue.run(function(callback) { |
- chrome.fileBrowserPrivate.getStrings(function(strings) { |
- loadTimeData.data = strings; |
- initContextMenu(strings); |
- chrome.storage.local.set({strings: strings}, callback); |
- }); |
- }); |
- |
- // Count runtime JavaScript errors. |
- window.onerror = function() { |
- JSErrorCount++; |
- }; |
-} |
- |
-// Initialize Files.app. |
-initApp(); |
- |
-/** |
- * Progress center of the background page. |
- * @type {ProgressCenter} |
- */ |
-window.progressCenter = new ProgressCenter(); |
- |
-/** |
- * Event handler for progress center. |
- * @type {ProgressCenter} |
- */ |
-var progressCenterHandler = new ProgressCenterHandler( |
- FileOperationManager.getInstance(), |
- window.progressCenter); |