Commit 479878c1 authored by yoshiki's avatar yoshiki Committed by Commit bot

Files.app: Split background.js

This patch splits the background.js into the 3 files (background_base.js, app_window_wrapper.js, background.js), extracting the common classes.

This patch itself doesn't change any functionality, but the extracted files will be used in the separated audio player app in near future.

BUG=375039
TEST=browser_test passes

Review URL: https://codereview.chromium.org/562103002

Cr-Commit-Position: refs/heads/master@{#294998}
parent 0a24cfc9
// 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';
/**
* 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.saveAppState|.
* 2. Every time the app state changes the app should update |window.appState|
* and call |util.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 customized params later.
this.options_ = JSON.parse(JSON.stringify(options));
this.window_ = null;
this.appState_ = null;
this.openingOrOpened_ = false;
this.queue = new AsyncUtil.Queue();
Object.seal(this);
}
AppWindowWrapper.prototype = {
/**
* @return {AppWindow} Wrapped application window.
*/
get rawAppWindow() {
return this.window_;
}
};
/**
* Key for getting and storing the last window state (maximized or not).
* @const
* @private
*/
AppWindowWrapper.MAXIMIZED_KEY_ = 'isMaximized';
/**
* Make a key of window geometry preferences for the given initial URL.
* @param {string} url Initialize URL that the window has.
* @return {string} Key of window geometry preferences.
*/
AppWindowWrapper.makeGeometryKey = function(url) {
return 'windowGeometry' + ':' + url;
};
/**
* Focuses the window on the specified desktop.
* @param {AppWindow} appWindow Application window.
* @param {string=} opt_profileId The profiled ID of the target window. If it is
* dropped, the window is focused on the current window.
*/
AppWindowWrapper.focusOnDesktop = function(appWindow, opt_profileId) {
new Promise(function(onFulfilled, onRejected) {
if (opt_profileId) {
onFulfilled(opt_profileId);
} else {
chrome.fileManagerPrivate.getProfiles(function(profiles,
currentId,
displayedId) {
onFulfilled(currentId);
});
}
}).then(function(profileId) {
appWindow.contentWindow.chrome.fileManagerPrivate.visitDesktop(
profileId, function() {
appWindow.focus();
});
});
};
/**
* Shift distance to avoid overlapping windows.
* @type {number}
* @const
*/
AppWindowWrapper.SHIFT_DISTANCE = 40;
/**
* Sets the icon of the window.
* @param {string} iconPath Path of the icon.
*/
AppWindowWrapper.prototype.setIcon = function(iconPath) {
this.window_.setIcon(iconPath);
};
/**
* Opens the window.
*
* @param {Object} appState App state.
* @param {boolean} reopen True if the launching is triggered automatically.
* False otherwise.
* @param {function()=} opt_callback Completion callback.
*/
AppWindowWrapper.prototype.launch = function(appState, reopen, 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 = background.getSimilarWindows(this.url_);
// Restore maximized windows, to avoid hiding them to tray, which can be
// confusing for users.
this.queue.run(function(callback) {
for (var index = 0; index < similarWindows.length; index++) {
if (similarWindows[index].isMaximized()) {
var createWindowAndRemoveListener = function() {
similarWindows[index].onRestored.removeListener(
createWindowAndRemoveListener);
callback();
};
similarWindows[index].onRestored.addListener(
createWindowAndRemoveListener);
similarWindows[index].restore();
return;
}
}
// If no maximized windows, then create the window immediately.
callback();
});
// Obtains the last geometry and window state (maximized or not).
var lastBounds;
var isMaximized = false;
this.queue.run(function(callback) {
var boundsKey = AppWindowWrapper.makeGeometryKey(this.url_);
var maximizedKey = AppWindowWrapper.MAXIMIZED_KEY_;
chrome.storage.local.get([boundsKey, maximizedKey], function(preferences) {
if (!chrome.runtime.lastError) {
lastBounds = preferences[boundsKey];
isMaximized = preferences[maximizedKey];
}
callback();
});
}.bind(this));
// Closure creating the window, once all preprocessing tasks are finished.
this.queue.run(function(callback) {
// Apply the last bounds.
if (lastBounds)
this.options_.bounds = lastBounds;
if (isMaximized)
this.options_.state = 'maximized';
// Create a window.
chrome.app.window.create(this.url_, this.options_, function(appWindow) {
this.window_ = appWindow;
callback();
}.bind(this));
}.bind(this));
// After creating.
this.queue.run(function(callback) {
// If there is another window in the same position, shift the window.
var makeBoundsKey = function(bounds) {
return bounds.left + '/' + bounds.top;
};
var notAvailablePositions = {};
for (var i = 0; i < similarWindows.length; i++) {
var key = makeBoundsKey(similarWindows[i].getBounds());
notAvailablePositions[key] = true;
}
var candidateBounds = this.window_.getBounds();
while (true) {
var key = makeBoundsKey(candidateBounds);
if (!notAvailablePositions[key])
break;
// Make the position available to avoid an infinite loop.
notAvailablePositions[key] = false;
var nextLeft = candidateBounds.left + AppWindowWrapper.SHIFT_DISTANCE;
var nextRight = nextLeft + candidateBounds.width;
candidateBounds.left = nextRight >= screen.availWidth ?
nextRight % screen.availWidth : nextLeft;
var nextTop = candidateBounds.top + AppWindowWrapper.SHIFT_DISTANCE;
var nextBottom = nextTop + candidateBounds.height;
candidateBounds.top = nextBottom >= screen.availHeight ?
nextBottom % screen.availHeight : nextTop;
}
this.window_.moveTo(candidateBounds.left, candidateBounds.top);
// Save the properties.
var appWindow = this.window_;
background.appWindows[this.id_] = appWindow;
var contentWindow = appWindow.contentWindow;
contentWindow.appID = this.id_;
contentWindow.appState = this.appState_;
contentWindow.appReopen = reopen;
contentWindow.appInitialURL = this.url_;
if (window.IN_TEST)
contentWindow.IN_TEST = true;
// Register event listeners.
appWindow.onBoundsChanged.addListener(this.onBoundsChanged_.bind(this));
appWindow.onClosed.addListener(this.onClosed_.bind(this));
// Callback.
if (opt_callback)
opt_callback();
callback();
}.bind(this));
};
/**
* Handles the onClosed extension API event.
* @private
*/
AppWindowWrapper.prototype.onClosed_ = function() {
// Remember the last window state (maximized or normal).
var preferences = {};
preferences[AppWindowWrapper.MAXIMIZED_KEY_] = this.window_.isMaximized();
chrome.storage.local.set(preferences);
// Unload the window.
var appWindow = this.window_;
var contentWindow = this.window_.contentWindow;
if (contentWindow.unload)
contentWindow.unload();
this.window_ = null;
this.openingOrOpened_ = false;
// Updates preferences.
if (contentWindow.saveOnExit) {
contentWindow.saveOnExit.forEach(function(entry) {
util.AppCache.update(entry.key, entry.value);
});
}
chrome.storage.local.remove(this.id_); // Forget the persisted state.
// Remove the window from the set.
delete background.appWindows[this.id_];
// If there is no application window, reset window ID.
if (!Object.keys(background.appWindows).length)
nextFileManagerWindowID = 0;
background.tryClose();
};
/**
* Handles onBoundsChanged extension API event.
* @private
*/
AppWindowWrapper.prototype.onBoundsChanged_ = function() {
if (!this.window_.isMaximized()) {
var preferences = {};
preferences[AppWindowWrapper.makeGeometryKey(this.url_)] =
this.window_.getBounds();
chrome.storage.local.set(preferences);
}
};
/**
* 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 {boolean} reopen True if the launching is triggered automatically.
* False otherwise.
* @param {function()=} opt_callback Completion callback.
*/
SingletonAppWindowWrapper.prototype.launch =
function(appState, reopen, opt_callback) {
// If the window is not opened yet, just call the parent method.
if (!this.openingOrOpened_) {
AppWindowWrapper.prototype.launch.call(
this, appState, reopen, 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.appReopen = reopen;
this.window_.contentWindow.reload();
if (opt_callback)
opt_callback();
nextStep();
}.bind(this));
};
/**
* Reopen a window if its state is saved in the local storage.
* @param {function()=} opt_callback Completion callback.
*/
SingletonAppWindowWrapper.prototype.reopen = function(opt_callback) {
chrome.storage.local.get(this.id_, function(items) {
var value = items[this.id_];
if (!value) {
opt_callback && opt_callback();
return; // No app state persisted.
}
try {
var appState = JSON.parse(value);
} catch (e) {
console.error('Corrupt launch data for ' + this.id_, value);
opt_callback && opt_callback();
return;
}
this.launch(appState, true, opt_callback);
}.bind(this));
};
......@@ -17,13 +17,10 @@ var LaunchType = Object.freeze({
/**
* Root class of the background page.
* @constructor
* @extends {BackgroundBase}
*/
function Background() {
/**
* Map of all currently open app windows. The key is an app ID.
* @type {Object.<string, AppWindow>}
*/
this.appWindows = {};
function FileBrowserBackground() {
BackgroundBase.call(this);
/**
* Map of all currently open file dialogs. The key is an app ID.
......@@ -143,43 +140,32 @@ function Background() {
* @const
* @private
*/
Background.CLOSE_DELAY_MS_ = 5000;
FileBrowserBackground.CLOSE_DELAY_MS_ = 5000;
/**
* Make a key of window geometry preferences for the given initial URL.
* @param {string} url Initialize URL that the window has.
* @return {string} Key of window geometry preferences.
*/
Background.makeGeometryKey = function(url) {
return 'windowGeometry' + ':' + url;
FileBrowserBackground.prototype = {
__proto__: BackgroundBase.prototype
};
/**
* Key for getting and storing the last window state (maximized or not).
* @const
* @private
*/
Background.MAXIMIZED_KEY_ = 'isMaximized';
/**
* Register callback to be invoked after initialization.
* If the initialization is already done, the callback is invoked immediately.
*
* @param {function()} callback Initialize callback to be registered.
*/
Background.prototype.ready = function(callback) {
FileBrowserBackground.prototype.ready = function(callback) {
this.stringDataPromise.then(callback);
};
/**
* Checks the current condition of background page and closes it if possible.
* Checks the current condition of background page.
* @return {boolean} True if the background page is closable, false if not.
*/
Background.prototype.tryClose = function() {
FileBrowserBackground.prototype.canClose = function() {
// If the file operation is going, the background page cannot close.
if (this.fileOperationManager.hasQueuedTasks() ||
this.driveSyncHandler_.syncing) {
this.lastTimeCanClose_ = null;
return;
return false;
}
var views = chrome.extension.getViews();
......@@ -189,7 +175,7 @@ Background.prototype.tryClose = function() {
// closing, the background page cannot close.
if (views[i] !== window && !views[i].closing) {
this.lastTimeCanClose_ = null;
return;
return false;
}
closing = closing || views[i].closing;
}
......@@ -198,36 +184,23 @@ Background.prototype.tryClose = function() {
// 5 seconds ago, We need more time for sure.
if (closing ||
this.lastTimeCanClose_ === null ||
Date.now() - this.lastTimeCanClose_ < Background.CLOSE_DELAY_MS_) {
(Date.now() - this.lastTimeCanClose_ <
FileBrowserBackground.CLOSE_DELAY_MS_)) {
if (this.lastTimeCanClose_ === null)
this.lastTimeCanClose_ = Date.now();
setTimeout(this.tryClose.bind(this), Background.CLOSE_DELAY_MS_);
return;
setTimeout(this.tryClose.bind(this), FileBrowserBackground.CLOSE_DELAY_MS_);
return false;
}
// Otherwise we can close the background page.
close();
};
/**
* Gets similar windows, it means with the same initial url.
* @param {string} url URL that the obtained windows have.
* @return {Array.<AppWindow>} List of similar windows.
*/
Background.prototype.getSimilarWindows = function(url) {
var result = [];
for (var appID in this.appWindows) {
if (this.appWindows[appID].contentWindow.appInitialURL === url)
result.push(this.appWindows[appID]);
}
return result;
return true;
};
/**
* Opens the root directory of the volume in Files.app.
* @param {string} volumeId ID of a volume to be opened.
*/
Background.prototype.navigateToVolume = function(volumeId) {
FileBrowserBackground.prototype.navigateToVolume = function(volumeId) {
VolumeManager.getInstance().then(function(volumeManager) {
var volumeInfoList = volumeManager.volumeInfoList;
var index = volumeInfoList.findIndex(volumeId);
......@@ -243,331 +216,6 @@ Background.prototype.navigateToVolume = function(volumeId) {
});
};
/**
* 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.saveAppState|.
* 2. Every time the app state changes the app should update |window.appState|
* and call |util.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 customized params later.
this.options_ = JSON.parse(JSON.stringify(options));
this.window_ = null;
this.appState_ = null;
this.openingOrOpened_ = false;
this.queue = new AsyncUtil.Queue();
Object.seal(this);
}
AppWindowWrapper.prototype = {
/**
* @return {AppWindow} Wrapped application window.
*/
get rawAppWindow() {
return this.window_;
}
};
/**
* Focuses the window on the specified desktop.
* @param {AppWindow} appWindow Application window.
* @param {string=} opt_profileId The profiled ID of the target window. If it is
* dropped, the window is focused on the current window.
*/
AppWindowWrapper.focusOnDesktop = function(appWindow, opt_profileId) {
new Promise(function(onFulfilled, onRejected) {
if (opt_profileId) {
onFulfilled(opt_profileId);
} else {
chrome.fileManagerPrivate.getProfiles(function(profiles,
currentId,
displayedId) {
onFulfilled(currentId);
});
}
}).then(function(profileId) {
appWindow.contentWindow.chrome.fileManagerPrivate.visitDesktop(
profileId, function() {
appWindow.focus();
});
});
};
/**
* Shift distance to avoid overlapping windows.
* @type {number}
* @const
*/
AppWindowWrapper.SHIFT_DISTANCE = 40;
/**
* Sets the icon of the window.
* @param {string} iconPath Path of the icon.
*/
AppWindowWrapper.prototype.setIcon = function(iconPath) {
this.window_.setIcon(iconPath);
};
/**
* Opens the window.
*
* @param {Object} appState App state.
* @param {boolean} reopen True if the launching is triggered automatically.
* False otherwise.
* @param {function()=} opt_callback Completion callback.
*/
AppWindowWrapper.prototype.launch = function(appState, reopen, 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 = background.getSimilarWindows(this.url_);
// Restore maximized windows, to avoid hiding them to tray, which can be
// confusing for users.
this.queue.run(function(callback) {
for (var index = 0; index < similarWindows.length; index++) {
if (similarWindows[index].isMaximized()) {
var createWindowAndRemoveListener = function() {
similarWindows[index].onRestored.removeListener(
createWindowAndRemoveListener);
callback();
};
similarWindows[index].onRestored.addListener(
createWindowAndRemoveListener);
similarWindows[index].restore();
return;
}
}
// If no maximized windows, then create the window immediately.
callback();
});
// Obtains the last geometry and window state (maximized or not).
var lastBounds;
var isMaximized = false;
this.queue.run(function(callback) {
var boundsKey = Background.makeGeometryKey(this.url_);
var maximizedKey = Background.MAXIMIZED_KEY_;
chrome.storage.local.get([boundsKey, maximizedKey], function(preferences) {
if (!chrome.runtime.lastError) {
lastBounds = preferences[boundsKey];
isMaximized = preferences[maximizedKey];
}
callback();
});
}.bind(this));
// Closure creating the window, once all preprocessing tasks are finished.
this.queue.run(function(callback) {
// Apply the last bounds.
if (lastBounds)
this.options_.bounds = lastBounds;
if (isMaximized)
this.options_.state = 'maximized';
// Create a window.
chrome.app.window.create(this.url_, this.options_, function(appWindow) {
this.window_ = appWindow;
callback();
}.bind(this));
}.bind(this));
// After creating.
this.queue.run(function(callback) {
// If there is another window in the same position, shift the window.
var makeBoundsKey = function(bounds) {
return bounds.left + '/' + bounds.top;
};
var notAvailablePositions = {};
for (var i = 0; i < similarWindows.length; i++) {
var key = makeBoundsKey(similarWindows[i].getBounds());
notAvailablePositions[key] = true;
}
var candidateBounds = this.window_.getBounds();
while (true) {
var key = makeBoundsKey(candidateBounds);
if (!notAvailablePositions[key])
break;
// Make the position available to avoid an infinite loop.
notAvailablePositions[key] = false;
var nextLeft = candidateBounds.left + AppWindowWrapper.SHIFT_DISTANCE;
var nextRight = nextLeft + candidateBounds.width;
candidateBounds.left = nextRight >= screen.availWidth ?
nextRight % screen.availWidth : nextLeft;
var nextTop = candidateBounds.top + AppWindowWrapper.SHIFT_DISTANCE;
var nextBottom = nextTop + candidateBounds.height;
candidateBounds.top = nextBottom >= screen.availHeight ?
nextBottom % screen.availHeight : nextTop;
}
this.window_.moveTo(candidateBounds.left, candidateBounds.top);
// Save the properties.
var appWindow = this.window_;
background.appWindows[this.id_] = appWindow;
var contentWindow = appWindow.contentWindow;
contentWindow.appID = this.id_;
contentWindow.appState = this.appState_;
contentWindow.appReopen = reopen;
contentWindow.appInitialURL = this.url_;
if (window.IN_TEST)
contentWindow.IN_TEST = true;
// Register event listeners.
appWindow.onBoundsChanged.addListener(this.onBoundsChanged_.bind(this));
appWindow.onClosed.addListener(this.onClosed_.bind(this));
// Callback.
if (opt_callback)
opt_callback();
callback();
}.bind(this));
};
/**
* Handles the onClosed extension API event.
* @private
*/
AppWindowWrapper.prototype.onClosed_ = function() {
// Remember the last window state (maximized or normal).
var preferences = {};
preferences[Background.MAXIMIZED_KEY_] = this.window_.isMaximized();
chrome.storage.local.set(preferences);
// Unload the window.
var appWindow = this.window_;
var contentWindow = this.window_.contentWindow;
if (contentWindow.unload)
contentWindow.unload();
this.window_ = null;
this.openingOrOpened_ = false;
// Updates preferences.
if (contentWindow.saveOnExit) {
contentWindow.saveOnExit.forEach(function(entry) {
util.AppCache.update(entry.key, entry.value);
});
}
chrome.storage.local.remove(this.id_); // Forget the persisted state.
// Remove the window from the set.
delete background.appWindows[this.id_];
// If there is no application window, reset window ID.
if (!Object.keys(background.appWindows).length)
nextFileManagerWindowID = 0;
background.tryClose();
};
/**
* Handles onBoundsChanged extension API event.
* @private
*/
AppWindowWrapper.prototype.onBoundsChanged_ = function() {
if (!this.window_.isMaximized()) {
var preferences = {};
preferences[Background.makeGeometryKey(this.url_)] =
this.window_.getBounds();
chrome.storage.local.set(preferences);
}
};
/**
* 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 {boolean} reopen True if the launching is triggered automatically.
* False otherwise.
* @param {function()=} opt_callback Completion callback.
*/
SingletonAppWindowWrapper.prototype.launch =
function(appState, reopen, opt_callback) {
// If the window is not opened yet, just call the parent method.
if (!this.openingOrOpened_) {
AppWindowWrapper.prototype.launch.call(
this, appState, reopen, 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.appReopen = reopen;
this.window_.contentWindow.reload();
if (opt_callback)
opt_callback();
nextStep();
}.bind(this));
};
/**
* Reopen a window if its state is saved in the local storage.
* @param {function()=} opt_callback Completion callback.
*/
SingletonAppWindowWrapper.prototype.reopen = function(opt_callback) {
chrome.storage.local.get(this.id_, function(items) {
var value = items[this.id_];
if (!value) {
opt_callback && opt_callback();
return; // No app state persisted.
}
try {
var appState = JSON.parse(value);
} catch (e) {
console.error('Corrupt launch data for ' + this.id_, value);
opt_callback && opt_callback();
return;
}
this.launch(appState, true, opt_callback);
}.bind(this));
};
/**
* Prefix for the file manager window ID.
* @type {string}
......@@ -754,7 +402,7 @@ function registerDialog(dialogWindow) {
* @param {Object} details Details object.
* @private
*/
Background.prototype.onExecute_ = function(action, details) {
FileBrowserBackground.prototype.onExecute_ = function(action, details) {
switch (action) {
case 'play':
var urls = util.entriesToURLs(details.entries);
......@@ -839,7 +487,7 @@ function launchAudioPlayer(playlist, opt_displayedId) {
* Launches the app.
* @private
*/
Background.prototype.onLaunched_ = function() {
FileBrowserBackground.prototype.onLaunched_ = function() {
if (nextFileManagerWindowID == 0) {
// The app just launched. Remove window state records that are not needed
// any more.
......@@ -859,7 +507,7 @@ Background.prototype.onLaunched_ = function() {
* Restarted the app, restore windows.
* @private
*/
Background.prototype.onRestarted_ = function() {
FileBrowserBackground.prototype.onRestarted_ = function() {
// Reopen file manager windows.
chrome.storage.local.get(function(items) {
for (var key in items) {
......@@ -895,7 +543,7 @@ Background.prototype.onRestarted_ = function() {
* @param {OnClickData} info Event details.
* @private
*/
Background.prototype.onContextMenuClicked_ = function(info) {
FileBrowserBackground.prototype.onContextMenuClicked_ = function(info) {
if (info.menuItemId == 'new-window') {
// Find the focused window (if any) and use it's current url for the
// new window. If not found, then launch with the default url.
......@@ -925,7 +573,7 @@ Background.prototype.onContextMenuClicked_ = function(info) {
* Initializes the context menu. Recreates if already exists.
* @private
*/
Background.prototype.initContextMenu_ = function() {
FileBrowserBackground.prototype.initContextMenu_ = function() {
try {
// According to the spec [1], the callback is optional. But no callback
// causes an error for some reason, so we call it with null-callback to
......@@ -945,6 +593,6 @@ Background.prototype.initContextMenu_ = function() {
/**
* Singleton instance of Background.
* @type {Background}
* @type {FileBrowserBackground}
*/
window.background = new Background();
window.background = new FileBrowserBackground();
// 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';
/**
* Root class of the background page.
* @constructor
*/
function BackgroundBase() {
/**
* Map of all currently open app windows. The key is an app ID.
* @type {Object.<string, AppWindow>}
*/
this.appWindows = {};
}
/**
* Checks the current condition of background page.
* @return {boolean} True if the background page can be closed. False if not.
*/
BackgroundBase.prototype.canClose = function() {
return true;
};
/**
* Checks the current condition of background page and closes it if possible.
*/
BackgroundBase.prototype.tryClose = function() {
if (this.canClose())
window.close();
};
/**
* Gets similar windows, it means with the same initial url.
* @param {string} url URL that the obtained windows have.
* @return {Array.<AppWindow>} List of similar windows.
*/
BackgroundBase.prototype.getSimilarWindows = function(url) {
var result = [];
for (var appID in this.appWindows) {
if (this.appWindows[appID].contentWindow.appInitialURL === url)
result.push(this.appWindows[appID]);
}
return result;
};
......@@ -41,20 +41,6 @@
"webview"
],
"file_browser_handlers": [
{
"id": "play",
"default_title": "__MSG_PLAY_MEDIA__",
"default_icon": "common/images/file_types/200/audio.png",
"file_filters": [
"filesystem:*.amr",
"filesystem:*.flac",
"filesystem:*.m4a",
"filesystem:*.mp3",
"filesystem:*.oga",
"filesystem:*.ogg",
"filesystem:*.wav"
]
},
{
"id": "mount-archive",
"default_title": "__MSG_MOUNT_ARCHIVE__",
......@@ -156,6 +142,8 @@
// enough that anything is passed to web_accessible_resources. If there is
// at least any file, then all files are allowed. http://crbug.com/179127.
"web_accessible_resources": [
"background/js/app_window_wrapper.js",
"background/js/background_base.js",
"background/js/test_util.js",
"background/js/volume_manager.js",
"common/js/async_util.js",
......@@ -187,6 +175,8 @@
"common/js/progress_center_common.js",
"common/js/util.js",
"common/js/volume_manager_common.js",
"background/js/app_window_wrapper.js",
"background/js/background_base.js",
"background/js/device_handler.js",
"background/js/drive_sync_handler.js",
"background/js/file_operation_handler.js",
......
......@@ -17,19 +17,23 @@
<include name="IDR_FILE_MANAGER_MAIN_JS" file="file_manager/foreground/js/main_scripts.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_FILE_MANAGER_BKGND_JS" file="file_manager/background/js/background.js" type="BINDATA" />
<!-- Scripts working in background page. -->
<!-- Commone Scripts. -->
<include name="IDR_FILE_MANAGER_ERROR_UTIL_JS" file="file_manager/common/js/error_util.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_ASYNC_UTIL_JS" file="file_manager/common/js/async_util.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_PROGRESS_CENTER_COMMON_JS" file="file_manager/common/js/progress_center_common.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_UTIL_JS" file="file_manager/common/js/util.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_VOLUME_MANAGER_COMMON_JS" file="file_manager/common/js/volume_manager_common.js" flattenhtml="false" type="BINDATA" />
<!-- Scripts working in background page. -->
<include name="IDR_FILE_MANAGER_DEVICE_APP_WINDOW_WRAPPER_JS" file="file_manager/background/js/app_window_wrapper.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_DEVICE_BACKGROUND_BASE_JS" file="file_manager/background/js/background_base.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_DEVICE_HANDLER_JS" file="file_manager/background/js/device_handler.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_DRIVE_SYNC_HANDLER_JS" file="file_manager/background/js/drive_sync_handler.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_FILE_OPERATION_HANDLER_JS" file="file_manager/background/js/file_operation_handler.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_FILE_OPERATION_MANAGER_JS" file="file_manager/background/js/file_operation_manager.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_PROGRESS_CENTER_COMMON_JS" file="file_manager/common/js/progress_center_common.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_PROGRESS_CENTER_JS" file="file_manager/background/js/progress_center.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_TEST_UTIL_JS" file="file_manager/background/js/test_util.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_UTIL_JS" file="file_manager/common/js/util.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_VOLUME_MANAGER_JS" file="file_manager/background/js/volume_manager.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_FILE_MANAGER_VOLUME_MANAGER_COMMON_JS" file="file_manager/common/js/volume_manager_common.js" flattenhtml="false" type="BINDATA" />
<!-- Scripts referred by the gallery app. -->
<include name="IDR_FILE_MANAGER_FILE_TYPE_JS" file="file_manager/foreground/js/file_type.js" flattenhtml="false" type="BINDATA" />
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment