X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fchrome%2Fbrowser%2Fresources%2Ffile_manager%2Fforeground%2Fjs%2Ffile_manager.js;h=7d645d43f435dd30ead60754abf2658f1bfbd9fa;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=a1cfe96b4d024a2672b35b7d6e0d2276bcd7a200;hpb=7338fba38ba696536d1cc9d389afd716a6ab2fe6;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/chrome/browser/resources/file_manager/foreground/js/file_manager.js b/src/chrome/browser/resources/file_manager/foreground/js/file_manager.js index a1cfe96..7d645d4 100644 --- a/src/chrome/browser/resources/file_manager/foreground/js/file_manager.js +++ b/src/chrome/browser/resources/file_manager/foreground/js/file_manager.js @@ -46,17 +46,6 @@ function FileManager() { this.currentVolumeInfo_ = null; } -/** - * Maximum delay in milliseconds for updating thumbnails in the bottom panel - * to mitigate flickering. If images load faster then the delay they replace - * old images smoothly. On the other hand we don't want to keep old images - * too long. - * - * @type {number} - * @const - */ -FileManager.THUMBNAIL_SHOW_DELAY = 100; - FileManager.prototype = { __proto__: cr.EventTarget.prototype, get directoryModel() { @@ -76,6 +65,9 @@ FileManager.prototype = { }, get volumeManager() { return this.volumeManager_; + }, + get ui() { + return this.ui_; } }; @@ -227,9 +219,6 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; }.bind(this)); }.bind(this)); - // TODO(yoshiki): Remove the flag when the feature is launched. - this.enableExperimentalWebstoreIntegration_ = true; - group.run(callback); }; @@ -376,8 +365,8 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; * @private */ FileManager.prototype.initDataTransferOperations_ = function() { - this.fileOperationManager_ = FileOperationManagerWrapper.getInstance( - this.backgroundPage_); + this.fileOperationManager_ = + this.backgroundPage_.background.fileOperationManager; // CopyManager are required for 'Delete' operation in // Open and Save dialogs. But drag-n-drop and copy-paste are not needed. @@ -410,6 +399,26 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; this.blinkSelection.bind(this)); controller.addEventListener('selection-cut', this.blinkSelection.bind(this)); + controller.addEventListener('source-not-found', + this.onSourceNotFound_.bind(this)); + }; + + /** + * Handles an error that the source entry of file operation is not found. + * @private + */ + FileManager.prototype.onSourceNotFound_ = function(event) { + // Ensure this.sourceNotFoundErrorCount_ is integer. + this.sourceNotFoundErrorCount_ = ~~this.sourceNotFoundErrorCount_; + var item = new ProgressCenterItem(); + item.id = 'source-not-found-' + this.sourceNotFoundErrorCount_; + if (event.progressType === ProgressItemType.COPY) + item.message = strf('COPY_SOURCE_NOT_FOUND_ERROR', event.fileName); + else if (event.progressType === ProgressItemType.MOVE) + item.message = strf('MOVE_SOURCE_NOT_FOUND_ERROR', event.fileName); + item.state = ProgressItemState.ERROR; + this.backgroundPage_.background.progressCenter.updateItem(item); + this.sourceNotFoundErrorCount_++; }; /** @@ -445,9 +454,14 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; this.gearButton_.addEventListener('menushow', this.refreshRemainingSpace_.bind(this, false /* Without loading caption. */)); - this.gearButton_.addEventListener( - 'menushow', + chrome.fileBrowserPrivate.onDesktopChanged.addListener(function() { + this.updateVisitDesktopMenus_(); + this.ui_.updateProfileBadge(); + }.bind(this)); + chrome.fileBrowserPrivate.onProfileAdded.addListener( this.updateVisitDesktopMenus_.bind(this)); + this.updateVisitDesktopMenus_(); + this.dialogDom_.querySelector('#gear-menu').menuItemSelector = 'menuitem, hr'; cr.ui.decorate(this.gearButton_, cr.ui.MenuButton); @@ -482,7 +496,6 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; }; FileManager.prototype.onMaximize = function() { - this.document_.activeElement.blur(); var appWindow = chrome.app.window.current(); if (appWindow.isMaximized()) appWindow.restore(); @@ -586,14 +599,20 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; */ FileManager.prototype.initGeneral_ = function(callback) { // Initialize the application state. + // TODO(mtomasz): Unify window.appState with location.search format. if (window.appState) { this.params_ = window.appState.params || {}; - this.defaultPath = window.appState.defaultPath; + this.initCurrentDirectoryURL_ = window.appState.currentDirectoryURL; + this.initSelectionURL_ = window.appState.selectionURL; + this.initTargetName_ = window.appState.targetName; } else { + // Used by the select dialog only. this.params_ = location.search ? JSON.parse(decodeURIComponent(location.search.substr(1))) : {}; - this.defaultPath = this.params_.defaultPath; + this.initCurrentDirectoryURL_ = this.params_.currentDirectoryURL; + this.initSelectionURL_ = this.params_.selectionURL; + this.initTargetName_ = this.params_.targetName; } // Initialize the member variables that depend this.params_. @@ -653,7 +672,9 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; * @private */ FileManager.prototype.initEssentialUI_ = function(callback) { - // Optional list of file types. + // Record stats of dialog types. New values must NOT be inserted into the + // array enumerating the types. It must be in sync with + // FileDialogType enum in tools/metrics/histograms/histogram.xml. metrics.recordEnum('Create', this.dialogType, [DialogType.SELECT_FOLDER, DialogType.SELECT_UPLOAD_FOLDER, @@ -976,7 +997,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; this.updateStartupPrefs_.bind(this)); // Restore preferences. - this.directoryModel_.sortFileList( + this.directoryModel_.getFileList().sort( this.viewOptions_.sortField || 'modificationTime', this.viewOptions_.sortDirection || 'desc'); if (this.viewOptions_.columns) { @@ -1396,12 +1417,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; }; /** - * Restores current directory and may be a selected item after page load (or - * reload) or popping a state (after click on back/forward). defaultPath - * primarily is used with save/open dialogs. - * Default path may also contain a file name. Freshly opened file manager - * window has neither. - * + * Sets up the current directory during initialization. * @private */ FileManager.prototype.setupCurrentDirectory_ = function() { @@ -1414,138 +1430,117 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; this.volumeManager_.ensureInitialized(callback); }.bind(this)); - // Obtains the fallback path. - var defaultDisplayRoot; + var nextCurrentDirEntry; + var selectionEntry; + + // Resolve the selectionURL to selectionEntry or to currentDirectoryEntry + // in case of being a display root. queue.run(function(callback) { - this.volumeManager_.getDefaultDisplayRoot(function(displayRoot) { - defaultDisplayRoot = displayRoot; + if (!this.initSelectionURL_) { callback(); - }.bind(this)); + return; + } + webkitResolveLocalFileSystemURL( + this.initSelectionURL_, + function(inEntry) { + var locationInfo = this.volumeManager_.getLocationInfo(inEntry); + // If location information is not available, then the volume is + // no longer (or never) available. + if (!locationInfo) { + callback(); + return; + } + // If the selection is root, then use it as a current directory + // instead. This is because, selecting a root entry is done as + // opening it. + if (locationInfo.isRootEntry) + nextCurrentDirEntry = inEntry; + else + selectionEntry = inEntry; + callback(); + }.bind(this), callback); }.bind(this)); - - // Resolve the default path. - var defaultFullPath; - var candidateFullPath; - var candidateEntry; + // Resolve the currentDirectoryURL to currentDirectoryEntry (if not done + // by the previous step). queue.run(function(callback) { - // Cancel this sequence if the current directory has already changed. - if (tracker.hasChanged) { + if (nextCurrentDirEntry || !this.initCurrentDirectoryURL_) { callback(); return; } - - // Resolve the absolute path in case only the file name or an empty string - // is passed. - if (!this.defaultPath) { - // TODO(mtomasz): that in this case we can directly jump to #1540 - // and avoid fullPath conversion -> Entry. - defaultFullPath = defaultDisplayRoot.fullPath; - } else if (this.defaultPath.indexOf('/') === -1) { - // Path is a file name. - defaultFullPath = defaultDisplayRoot.fullPath + '/' + this.defaultPath; - } else { - defaultFullPath = this.defaultPath; - } - - // If Drive is disabled but the path points to Drive's entry, fallback to - // defaultDisplayRootPath. - if (PathUtil.isDriveBasedPath(defaultFullPath) && - !this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE)) { - candidateFullPath = defaultDisplayRoot.fullPath + '/' + - PathUtil.basename(defaultFullPath); - } else { - candidateFullPath = defaultFullPath; - } - - // If the path points a fake entry, use the entry directly. - // TODO(hirono): Obtains proper volume. - var volumeInfo = this.volumeManager_.getCurrentProfileVolumeInfo( - util.VolumeType.DRIVE); - if (volumeInfo) { - for (var name in volumeInfo.fakeEntries) { - var fakeEntry = volumeInfo.fakeEntries[name]; - // Skip the drive root fake entry, because we can need actual drive - // root to list its files. - if (fakeEntry.rootType === RootType.DRIVE) - continue; - if (candidateFullPath === fakeEntry.fullPath) { - candidateEntry = fakeEntry; + webkitResolveLocalFileSystemURL( + this.initCurrentDirectoryURL_, + function(inEntry) { + var locationInfo = this.volumeManager_.getLocationInfo(inEntry); + if (!locationInfo) { + callback(); + return; + } + nextCurrentDirEntry = inEntry; callback(); - return; - } - } - } + }.bind(this), callback); + // TODO(mtomasz): Implement reopening on special search, when fake + // entries are converted to directory providers. + }.bind(this)); - // Convert the path to the directory entry and an optional selection - // entry. - // TODO(hirono): There may be a race here. The path on Drive, may not - // be available yet. - this.volumeManager_.resolveAbsolutePath(candidateFullPath, - function(inEntry) { - candidateEntry = inEntry; + // If the directory to be changed to is not available, then first fallback + // to the parent of the selection entry. + queue.run(function(callback) { + if (nextCurrentDirEntry || !selectionEntry) { callback(); - }, function() { + return; + } + selectionEntry.getParent(function(inEntry) { + nextCurrentDirEntry = inEntry; callback(); - }); + }.bind(this)); }.bind(this)); - // Check the obtained entry. - var nextCurrentDirEntry; - var selectionEntry = null; - var suggestedName = null; - var error = null; + // If the directory to be changed to is still not resolved, then fallback + // to the default display root. queue.run(function(callback) { - // Cancel this sequence if the current directory has already changed. - if (tracker.hasChanged) { + if (nextCurrentDirEntry) { callback(); return; } + this.volumeManager_.getDefaultDisplayRoot(function(displayRoot) { + nextCurrentDirEntry = displayRoot; + callback(); + }.bind(this)); + }.bind(this)); - if (candidateEntry) { - // The entry is directory. Use it. - if (candidateEntry.isDirectory) { - nextCurrentDirEntry = candidateEntry; - callback(); - return; - } - // The entry exists, but it is not a directory. Therefore use a - // parent. - candidateEntry.getParent(function(parentEntry) { - nextCurrentDirEntry = parentEntry; - selectionEntry = candidateEntry; - callback(); - }, function() { - error = new Error('Unable to resolve parent for: ' + - candidateEntry.fullPath); - callback(); - }); + // If selection failed to be resolved (eg. didn't exist, in case of saving + // a file, or in case of a fallback of the current directory, then try to + // resolve again using the target name. + queue.run(function(callback) { + if (selectionEntry || !nextCurrentDirEntry || !this.initTargetName_) { + callback(); return; } - - // If the entry doesn't exist, most probably because the path contains a - // suggested name. Therefore try to open its parent. However, the parent - // may also not exist. In such situation, fallback. - var pathNodes = candidateFullPath.split('/'); - var baseName = pathNodes.pop(); - var parentPath = pathNodes.join('/'); - this.volumeManager_.resolveAbsolutePath( - parentPath, - function(parentEntry) { - nextCurrentDirEntry = parentEntry; - suggestedName = baseName; + // Try to resolve as a file first. If it fails, then as a directory. + nextCurrentDirEntry.getFile( + this.initTargetName_, + {}, + function(targetEntry) { + selectionEntry = targetEntry; callback(); - }, - callback); // In case of an error, continue. + }, function() { + // Failed to resolve as a file + nextCurrentDirEntry.getDirectory( + this.initTargetName_, + {}, + function(targetEntry) { + selectionEntry = targetEntry; + callback(); + }, function() { + // Failed to resolve as either file or directory. + callback(); + }); + }.bind(this)); }.bind(this)); - // If the directory is not set at this stage, fallback to the default - // mount point. + + // Finalize. queue.run(function(callback) { - // Check error. - if (error) { - callback(); - throw error; - } // Check directory change. tracker.stop(); if (tracker.hasChanged) { @@ -1554,9 +1549,9 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; } // Finish setup current directory. this.finishSetupCurrentDirectory_( - nextCurrentDirEntry || defaultDisplayRoot, + nextCurrentDirEntry, selectionEntry, - suggestedName); + this.initTargetName_); callback(); }.bind(this)); }; @@ -1581,13 +1576,15 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; } if (this.dialogType === DialogType.FULL_PAGE) { - // In the FULL_PAGE mode if the restored path points to a file we might + // In the FULL_PAGE mode if the restored URL points to a file we might // have to invoke a task after selecting it. if (this.params_.action === 'select') return; var task = null; // Handle restoring after crash, or the gallery action. + // TODO(mtomasz): Use the gallery action instead of just the gallery + // field. if (this.params_.gallery || this.params_.action === 'gallery') { if (!opt_selectionEntry) { // Non-existent file or a directory. @@ -1599,7 +1596,6 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; } else { // The file or the directory exists. task = function() { - // TODO(mtomasz): Replace the url with an entry. new FileTasks(this, this.params_).openGallery([opt_selectionEntry]); }.bind(this); } @@ -1611,6 +1607,12 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; // If there is a task to be run, run it after the scan is completed. if (task) { var listener = function() { + if (!util.isSameEntry(this.directoryModel_.getCurrentDirEntry(), + directoryEntry)) { + // Opened on a different URL. Probably fallbacked. Therefore, + // do not invoke a task. + return; + } this.directoryModel_.removeEventListener( 'scan-completed', listener); task(); @@ -1619,7 +1621,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; } } else if (this.dialogType === DialogType.SELECT_SAVEAS_FILE) { this.filenameInput_.value = opt_suggestedName || ''; - this.selectDefaultPathInFilenameInput_(); + this.selectTargetNameInFilenameInput_(); } }; @@ -2046,7 +2048,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; /** * @private */ - FileManager.prototype.selectDefaultPathInFilenameInput_ = function() { + FileManager.prototype.selectTargetNameInFilenameInput_ = function() { var input = this.filenameInput_; input.focus(); var selectionEnd = input.value.lastIndexOf('.'); @@ -2056,8 +2058,6 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; input.selectionStart = 0; input.selectionEnd = selectionEnd; } - // Clear, so we never do this again. - this.defaultPath = ''; }; /** @@ -2257,18 +2257,16 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; cr.ui.MenuItem.decorate(item); gearMenu.insertBefore(item, insertingPosition); item.className = 'visit-desktop'; - item.label = - strf('VISIT_DESKTOP_OF_USER', profile.displayName); + item.label = strf('VISIT_DESKTOP_OF_USER', + profile.displayName, + profile.profileId); item.addEventListener('activate', function(inProfile, event) { // Stop propagate and hide the menu manually, in order to prevent the // focus from being back to the button. (cf. http://crbug.com/248479) event.stopPropagation(); this.gearButton_.hideMenu(); this.gearButton_.blur(); - chrome.fileBrowserPrivate.visitDesktop(inProfile.profileId, - function() { - this.ui_.updateProfileBatch(); - }.bind(this)); + chrome.fileBrowserPrivate.visitDesktop(inProfile.profileId); }.bind(this, profile)); } }.bind(this)); @@ -2299,7 +2297,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; var currentVolumeInfo = this.currentVolumeInfo_; chrome.fileBrowserPrivate.getSizeStats( - currentVolumeInfo.root.toURL(), function(result) { + currentVolumeInfo.volumeId, function(result) { var volumeInfo = this.volumeManager_.getVolumeInfo( this.directoryModel_.getCurrentDirEntry()); if (currentVolumeInfo !== this.currentVolumeInfo_) @@ -2318,18 +2316,6 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; * @private */ FileManager.prototype.onDirectoryChanged_ = function(event) { - this.selectionHandler_.onFileSelectionChanged(); - this.ui_.searchBox.clear(); - // TODO(mtomasz): Use Entry.toURL() instead of fullPath. - util.updateAppState( - this.getCurrentDirectoryEntry() && - this.getCurrentDirectoryEntry().fullPath, '' /* opt_param */); - - if (this.commandHandler) - this.commandHandler.updateAvailability(); - - this.updateUnformattedVolumeStatus_(); - this.updateTitle_(); var newCurrentVolumeInfo = this.volumeManager_.getVolumeInfo( event.newDirEntry); @@ -2342,12 +2328,27 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; this.closeOnUnmount_ = false; } + // Remember the current volume info. + this.currentVolumeInfo_ = newCurrentVolumeInfo; + + this.selectionHandler_.onFileSelectionChanged(); + this.ui_.searchBox.clear(); + // TODO(mtomasz): Consider remembering the selection. + util.updateAppState( + this.getCurrentDirectoryEntry() ? + this.getCurrentDirectoryEntry().toURL() : '', + '' /* selectionURL */, + '' /* opt_param */); + + if (this.commandHandler) + this.commandHandler.updateAvailability(); + + this.updateUnformattedVolumeStatus_(); + this.updateTitle_(); + var currentEntry = this.getCurrentDirectoryEntry(); this.previewPanel_.currentEntry = util.isFakeEntry(currentEntry) ? null : currentEntry; - - // Remember the current volume info. - this.currentVolumeInfo_ = newCurrentVolumeInfo; }; FileManager.prototype.updateUnformattedVolumeStatus_ = function() { @@ -2522,7 +2523,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; // Show error dialog. var message; if (error.name == util.FileError.PATH_EXISTS_ERR || - error.name == util.FileError.TYPE_MISMACH_ERR) { + error.name == util.FileError.TYPE_MISMATCH_ERR) { // Check the existing entry is file or not. // 1) If the entry is a file: // a) If we get PATH_EXISTS_ERR, a file exists. @@ -2534,7 +2535,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; (entry.isFile && error.name == util.FileError.PATH_EXISTS_ERR) || (!entry.isFile && error.name == - util.FileError.TYPE_MISMACH_ERR) ? + util.FileError.TYPE_MISMATCH_ERR) ? 'FILE_ALREADY_EXISTS' : 'DIRECTORY_ALREADY_EXISTS', newName); @@ -3236,7 +3237,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; selectFileAndClose(); return; } - if (error.name == util.FileError.TYPE_MISMACH_ERR) { + if (error.name == util.FileError.TYPE_MISMATCH_ERR) { // An directory is found. // Do not allow to overwrite directory. this.alert.show(strf('DIRECTORY_ALREADY_EXISTS', filename));