summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzvorygin@chromium.org <zvorygin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-24 16:00:13 +0000
committerzvorygin@chromium.org <zvorygin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-24 16:00:13 +0000
commitd16e704e8f6e0fd8e71f68408bc50dabd427d83d (patch)
tree3a9c484b2d0e75cecc2bca39245e6d1278865fbd
parent8f3482ada9ad9b9e3c28ad24e8f922642623b50b (diff)
downloadchromium_src-d16e704e8f6e0fd8e71f68408bc50dabd427d83d.zip
chromium_src-d16e704e8f6e0fd8e71f68408bc50dabd427d83d.tar.gz
chromium_src-d16e704e8f6e0fd8e71f68408bc50dabd427d83d.tar.bz2
[FileBrowser] Added DefaultAction dialog to choose default action.
BUG=126927 TEST= Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=138476 Review URL: https://chromiumcodereview.appspot.com/10411018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138806 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/extensions/file_browser_private_api.cc20
-rw-r--r--chrome/browser/chromeos/extensions/file_browser_private_api.h13
-rw-r--r--chrome/browser/chromeos/extensions/file_handler_util.cc26
-rw-r--r--chrome/browser/chromeos/extensions/file_handler_util.h2
-rw-r--r--chrome/browser/extensions/extension_function_registry.cc1
-rw-r--r--chrome/browser/resources/file_manager/css/file_manager.css41
-rw-r--r--chrome/browser/resources/file_manager/js/combobutton.js7
-rw-r--r--chrome/browser/resources/file_manager/js/default_action_dialog.js137
-rw-r--r--chrome/browser/resources/file_manager/js/file_manager.js60
-rw-r--r--chrome/browser/resources/file_manager/js/main_scripts.js2
-rw-r--r--chrome/browser/resources/file_manager/main.html1
-rw-r--r--chrome/common/extensions/api/file_browser_private.json17
12 files changed, 305 insertions, 22 deletions
diff --git a/chrome/browser/chromeos/extensions/file_browser_private_api.cc b/chrome/browser/chromeos/extensions/file_browser_private_api.cc
index 7a597f8..9e60661 100644
--- a/chrome/browser/chromeos/extensions/file_browser_private_api.cc
+++ b/chrome/browser/chromeos/extensions/file_browser_private_api.cc
@@ -632,6 +632,26 @@ void ExecuteTasksFileBrowserFunction::OnTaskExecuted(bool success) {
SendResponse(success);
}
+SetDefaultTaskFileBrowserFunction::SetDefaultTaskFileBrowserFunction() {}
+
+SetDefaultTaskFileBrowserFunction::~SetDefaultTaskFileBrowserFunction() {}
+
+bool SetDefaultTaskFileBrowserFunction::RunImpl() {
+ // First param is task id that was to the extension with setDefaultTask call.
+ std::string task_id;
+ if (!args_->GetString(0, &task_id) || !task_id.size())
+ return false;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &file_handler_util::UpdateFileHandlerUsageStats,
+ profile_, task_id));
+
+ result_.reset(new base::FundamentalValue(true));
+ return true;
+}
+
FileBrowserFunction::FileBrowserFunction() {
}
diff --git a/chrome/browser/chromeos/extensions/file_browser_private_api.h b/chrome/browser/chromeos/extensions/file_browser_private_api.h
index e252894..f1a38fd 100644
--- a/chrome/browser/chromeos/extensions/file_browser_private_api.h
+++ b/chrome/browser/chromeos/extensions/file_browser_private_api.h
@@ -113,6 +113,19 @@ class ExecuteTasksFileBrowserFunction : public AsyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.executeTask");
};
+// Implements the chrome.fileBrowserPrivate.setDefaultTask method.
+class SetDefaultTaskFileBrowserFunction : public SyncExtensionFunction {
+ public:
+ SetDefaultTaskFileBrowserFunction();
+ virtual ~SetDefaultTaskFileBrowserFunction();
+
+ protected:
+ // AsyncExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.setDefaultTask");
+};
+
// Parent class for the chromium extension APIs for the file dialog.
class FileBrowserFunction
: public AsyncExtensionFunction {
diff --git a/chrome/browser/chromeos/extensions/file_handler_util.cc b/chrome/browser/chromeos/extensions/file_handler_util.cc
index 9802c25..6aab112 100644
--- a/chrome/browser/chromeos/extensions/file_handler_util.cc
+++ b/chrome/browser/chromeos/extensions/file_handler_util.cc
@@ -76,18 +76,6 @@ int ExtractProcessFromExtensionId(const std::string& extension_id,
return process->GetID();
}
-// Update file handler usage stats.
-void UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id) {
- if (!profile || !profile->GetPrefs())
- return;
- DictionaryPrefUpdate prefs_usage_update(profile->GetPrefs(),
- prefs::kLastUsedFileBrowserHandlers);
- prefs_usage_update->SetWithoutPathExpansion(task_id,
- new base::FundamentalValue(
- static_cast<int>(base::Time::Now().ToInternalValue()/
- base::Time::kMicrosecondsPerSecond)));
-}
-
URLPatternSet GetAllMatchingPatterns(const FileBrowserHandler* handler,
const std::vector<GURL>& files_list) {
URLPatternSet matching_patterns;
@@ -201,6 +189,18 @@ void SortLastUsedHandlerList(LastUsedHandlerList *list) {
} // namespace
+// Update file handler usage stats.
+void UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id) {
+ if (!profile || !profile->GetPrefs())
+ return;
+ DictionaryPrefUpdate prefs_usage_update(profile->GetPrefs(),
+ prefs::kLastUsedFileBrowserHandlers);
+ prefs_usage_update->SetWithoutPathExpansion(task_id,
+ new base::FundamentalValue(
+ static_cast<int>(base::Time::Now().ToInternalValue()/
+ base::Time::kMicrosecondsPerSecond)));
+}
+
int GetReadWritePermissions() {
return kReadWriteFilePermissions;
}
@@ -635,8 +635,6 @@ void FileTaskExecutor::SetupPermissionsAndDispatchEvent(
details->SetInteger("tab_id", ExtensionTabUtil::GetTabId(contents));
}
- UpdateFileHandlerUsageStats(profile_, MakeTaskID(extension_id_, action_id_));
-
std::string json_args;
base::JSONWriter::Write(event_args.get(), &json_args);
event_router->DispatchEventToExtension(
diff --git a/chrome/browser/chromeos/extensions/file_handler_util.h b/chrome/browser/chromeos/extensions/file_handler_util.h
index 6ef6760..84b0e2f 100644
--- a/chrome/browser/chromeos/extensions/file_handler_util.h
+++ b/chrome/browser/chromeos/extensions/file_handler_util.h
@@ -20,6 +20,8 @@ class Profile;
namespace file_handler_util {
+void UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id);
+
// Gets read-write file access permission flags.
int GetReadWritePermissions();
// Gets read-only file access permission flags.
diff --git a/chrome/browser/extensions/extension_function_registry.cc b/chrome/browser/extensions/extension_function_registry.cc
index e60a7ff..4e29f7e 100644
--- a/chrome/browser/extensions/extension_function_registry.cc
+++ b/chrome/browser/extensions/extension_function_registry.cc
@@ -338,6 +338,7 @@ void ExtensionFunctionRegistry::ResetFunctions() {
// the extension-based file picker on Aura. crbug.com/97424
RegisterFunction<CancelFileDialogFunction>();
RegisterFunction<ExecuteTasksFileBrowserFunction>();
+ RegisterFunction<SetDefaultTaskFileBrowserFunction>();
RegisterFunction<FileDialogStringsFunction>();
RegisterFunction<GetFileTasksFileBrowserFunction>();
RegisterFunction<GetVolumeMetadataFunction>();
diff --git a/chrome/browser/resources/file_manager/css/file_manager.css b/chrome/browser/resources/file_manager/css/file_manager.css
index ba926e0..653e289 100644
--- a/chrome/browser/resources/file_manager/css/file_manager.css
+++ b/chrome/browser/resources/file_manager/css/file_manager.css
@@ -571,33 +571,61 @@ div.img-container > img {
position: absolute;
}
+/* Padding counterweights negative margins of items, thus eliminating scroll
+ bar when it's not needed. Max height is set to fit 8 items before showing
+ scroll bar. */
+#default-actions-list {
+ max-height: 328px;
+ padding: 1px 0;
+}
+
+#default-actions-list > li {
+ display: -webkit-box;
+}
+
+#default-actions-list > li > * {
+ display: block;
+ padding: 0 5px;
+}
+
+#default-actions-list > li > img {
+ height: 16px;
+ padding-top: 12px;
+}
+
+
#list-container list > *,
-#list-container grid > * {
+#list-container grid > *,
+#default-actions-list > * {
background-image: none;
border-radius: 0;
line-height: 30px;
}
#list-container list > [selected],
-#list-container grid > [selected] {
+#list-container grid > [selected],
+#default-actions-list > [selected] {
background-color: rgb(203, 219, 241);
}
-#list-container list > li.table-row[selected] {
+#list-container list > li.table-row[selected],
+#default-actions-list > li[selected] {
border-top: 1px solid rgb(224, 233, 247);
}
#list-container list > .accepts[selected],
#list-container grid > .accepts[selected],
#list-container list > [selected]:hover,
-#list-container grid > [selected]:hover {
+#list-container grid > [selected]:hover,
+#default-actions-list > [selected]:hover {
background-color: rgb(193, 211, 236);
}
#list-container list > .accepts,
#list-container grid > .accepts,
#list-container list > :hover,
-#list-container grid > :hover {
+#list-container grid > :hover,
+#default-actions-list > :hover {
background-color: #f1f1f1;
}
@@ -845,7 +873,8 @@ input.rename {
opacity: 1 !important;
}
-#list-container li.table-row {
+#list-container li.table-row,
+#default-actions-list li {
border: none;
border-top: 1px solid transparent;
line-height: 39px;
diff --git a/chrome/browser/resources/file_manager/js/combobutton.js b/chrome/browser/resources/file_manager/js/combobutton.js
index 62ee57d..7c2fcf1 100644
--- a/chrome/browser/resources/file_manager/js/combobutton.js
+++ b/chrome/browser/resources/file_manager/js/combobutton.js
@@ -35,6 +35,13 @@ cr.define('cr.ui', function() {
},
/**
+ * Adds separator to drop-down list.
+ */
+ addSeparator: function() {
+ this.menu.addSeparator();
+ },
+
+ /**
* Default item to fire on combobox click
*/
get defaultItem() {
diff --git a/chrome/browser/resources/file_manager/js/default_action_dialog.js b/chrome/browser/resources/file_manager/js/default_action_dialog.js
new file mode 100644
index 0000000..348ac4a
--- /dev/null
+++ b/chrome/browser/resources/file_manager/js/default_action_dialog.js
@@ -0,0 +1,137 @@
+// 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.
+
+
+/**
+ * DefaultActionDialog contains a message, a list box, an ok button, and a
+ * cancel button.
+ * This dialog should be used as action picker for file operations.
+ */
+cr.define('cr.filebrowser', function() {
+
+ /**
+ * Creates dialog in DOM tree.
+ *
+ * @param {HTMLElement} parentNode Node to be parent for this dialog.
+ */
+ function DefaultActionDialog(parentNode) {
+ cr.ui.dialogs.BaseDialog.call(this, parentNode);
+
+ this.list_ = new cr.ui.List();
+ this.list_.id = 'default-actions-list';
+ this.frame_.insertBefore(this.list_, this.text_.nextSibling);
+
+ this.selectionModel_ = this.list_.selectionModel =
+ new cr.ui.ListSingleSelectionModel();
+ this.dataModel_ = this.list_.dataModel = new cr.ui.ArrayDataModel([]);
+
+ // List has max-height defined at css, so that list grows automatically,
+ // but doesn't exceed predefined size.
+ this.list_.autoExpands = true;
+ this.list_.activateItemAtIndex = this.activateItemAtIndex_.bind(this);
+
+ this.initialFocusElement_ = this.list_;
+
+ var self = this;
+
+ // Binding stuff doesn't work with constructors, so we have to create
+ // closure here.
+ this.list_.itemConstructor = function(item) {
+ return self.renderItem(item);
+ }
+ }
+
+ DefaultActionDialog.prototype = {
+ __proto__: cr.ui.dialogs.BaseDialog.prototype
+ };
+
+ /**
+ * Overrides BaseDialog::onInputFocus
+ */
+ DefaultActionDialog.prototype.onInputFocus = function() {
+ this.list_.select();
+ };
+
+ /**
+ * Renders item for list.
+ * @param {Object} item Item to render.
+ */
+ DefaultActionDialog.prototype.renderItem = function(item) {
+ var result = this.document_.createElement('li');
+
+ var iconNode = this.document_.createElement('img');
+ iconNode.src = item.iconUrl;
+ result.appendChild(iconNode);
+
+ var labelNode = this.document_.createElement('span');
+ labelNode.textContent = item.label;
+ result.appendChild(labelNode);
+
+ cr.defineProperty(result, 'lead', cr.PropertyKind.BOOL_ATTR);
+ cr.defineProperty(result, 'selected', cr.PropertyKind.BOOL_ATTR);
+
+ return result;
+ }
+
+ /**
+ * Shows dialog.
+ *
+ * @param {String} message Message in dialog caption.
+ * @param {Array} items Items to render in list
+ * @param {int} defaultIndex Item to select by default.
+ * @param {Function} onOk Callback function.
+ * @param {Function} onCancel Callback function.
+ * @param {Function} onShow Callback function.
+ */
+ DefaultActionDialog.prototype.show = function(message, items, defaultIndex,
+ onOk, onCancel, onShow) {
+
+ cr.ui.dialogs.BaseDialog.prototype.show.apply(this,
+ [message, onOk, onCancel, onShow]);
+
+ this.list_.startBatchUpdates();
+
+ this.dataModel_.splice(0, this.dataModel_.length);
+
+ for (var i = 0; i < items.length; i++) {
+ this.dataModel_.push(items[i]);
+ }
+
+ this.selectionModel_.selectedIndex = defaultIndex;
+
+ this.list_.endBatchUpdates();
+ };
+
+ /**
+ * List activation handler. Closes dialog and calls 'ok' callback.
+ *
+ * @param {int} index Activated index.
+ */
+ DefaultActionDialog.prototype.activateItemAtIndex_ = function(index) {
+ this.hide();
+ if (this.onOk_)
+ this.onOk_(this.dataModel_.item(index).task);
+ }
+
+ /**
+ * Closes dialog and invokes callback with currently-selected item.
+ */
+ DefaultActionDialog.prototype.onOkClick_ = function() {
+ this.activateItemAtIndex_(this.selectionModel_.selectedIndex);
+ };
+
+ // Overrides BaseDialog::onContainerKeyDown_;
+ DefaultActionDialog.prototype.onContainerKeyDown_ = function(event) {
+ // Handle Escape.
+ if (event.keyCode == 27) {
+ this.onCancelClick_(event);
+ event.preventDefault();
+ } else if (event.keyCode == 32 || event.keyCode == 13) {
+ this.onOkClick_();
+ event.preventDefault();
+ }
+ };
+
+ return {DefaultActionDialog: DefaultActionDialog};
+});
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 7425dac..ba499c5 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -590,6 +590,8 @@ FileManager.prototype = {
this.alert = new d.AlertDialog(this.dialogDom_);
this.confirm = new d.ConfirmDialog(this.dialogDom_);
this.prompt = new d.PromptDialog(this.dialogDom_);
+ this.defaultTaskPicker =
+ new cr.filebrowser.DefaultActionDialog(this.dialogDom_);
};
/**
@@ -2591,6 +2593,7 @@ FileManager.prototype = {
}
}
+ var defaultIdx = 0;
this.taskItems_.hidden = dropDownItems.length == 0;
if (dropDownItems.length > 1) {
@@ -2600,7 +2603,17 @@ FileManager.prototype = {
for (var j = 0; j < dropDownItems.length; j++) {
this.taskItems_.addDropDownItem(dropDownItems[j]);
+ if (dropDownItems[j].task.taskId == defaultTask.taskId) {
+ defaultIdx = j;
+ }
}
+
+ this.taskItems_.addSeparator();
+ this.taskItems_.addDropDownItem({
+ label: str('CHANGE_DEFAULT_MENU_ITEM'),
+ items: dropDownItems,
+ defaultIdx: defaultIdx
+ });
}
selection.tasksList = tasksList;
@@ -2622,10 +2635,55 @@ FileManager.prototype = {
}
};
+ /**
+ * Task combobox handler.
+ *
+ * @param {Object} event Event containing task which was clicked.
+ */
FileManager.prototype.onTaskItemClicked_ = function(event) {
- this.dispatchFileTask_(event.item.task.taskId, this.selection.urls);
+ if (event.item.task) {
+ // Task field doesn't exist on change-default dropdown item.
+ this.dispatchFileTask_(event.item.task.taskId, this.selection.urls);
+ } else {
+ var extensions = [];
+
+ for (var i = 0; i < this.selection.urls.length; i++) {
+ var match = /\.(\w+)$/g.exec(this.selection.urls[i]);
+ if (match) {
+ var ext = match[1].toUpperCase();
+ if (extensions.indexOf(ext) == -1) {
+ extensions.push(ext);
+ }
+ }
+ }
+
+ var format = '';
+
+ if (extensions.length != 1) {
+ format = extensions[0];
+ }
+
+ // Change default was clicked. We should open "change default" dialog.
+ this.defaultTaskPicker.show(
+ strf('CHANGE_DEFAULT_CAPTION', format),
+ event.item.items, event.item.defaultIdx,
+ this.onDefaultTaskDone_.bind(this));
+ }
};
+
+ /**
+ * Set's given task as default, when this task is applicable.
+ * @param {Object} task Task to set as default.
+ */
+ FileManager.prototype.onDefaultTaskDone_ = function(task) {
+ chrome.fileBrowserPrivate.setDefaultTask(task.taskId);
+
+ chrome.fileBrowserPrivate.getFileTasks(
+ this.selection.urls,
+ this.onTasksFound_.bind(this, this.selection));
+ }
+
/**
* Dispatches default task for the current selection. If tasks are not ready
* yet, dispatches after task are available.
diff --git a/chrome/browser/resources/file_manager/js/main_scripts.js b/chrome/browser/resources/file_manager/js/main_scripts.js
index 09b3c46..7fecb37 100644
--- a/chrome/browser/resources/file_manager/js/main_scripts.js
+++ b/chrome/browser/resources/file_manager/js/main_scripts.js
@@ -46,7 +46,6 @@
//<include src="../../shared/js/cr/ui/menu.js"/>
//<include src="../../shared/js/cr/ui/menu_button.js"/>
//<include src="../../shared/js/cr/ui/context_menu_handler.js"/>
-//
//<include src="combobutton.js"/>
//
//<include src="util.js"/>
@@ -58,6 +57,7 @@
//<include src="file_type.js"/>
//<include src="file_transfer_controller.js"/>
//<include src="metadata/metadata_cache.js"/>
+//<include src="default_action_dialog.js"/>
// // For accurate load performance tracking place main.js should be
// // the last include to include.
//<include src="main.js"/>
diff --git a/chrome/browser/resources/file_manager/main.html b/chrome/browser/resources/file_manager/main.html
index 13bc8ae..410f9ee 100644
--- a/chrome/browser/resources/file_manager/main.html
+++ b/chrome/browser/resources/file_manager/main.html
@@ -76,6 +76,7 @@
<script src="js/file_transfer_controller.js"></script>
<script src="js/file_type.js"></script>
<script src="js/metadata/metadata_cache.js"></script>
+ <script src="js/default_action_dialog.js"></script>
<!-- For accurate load performance tracking main.js should be
the last script to include. -->
<script src="js/main.js"></script>
diff --git a/chrome/common/extensions/api/file_browser_private.json b/chrome/common/extensions/api/file_browser_private.json
index 3b28fd8..fefcc25 100644
--- a/chrome/common/extensions/api/file_browser_private.json
+++ b/chrome/common/extensions/api/file_browser_private.json
@@ -388,6 +388,23 @@
]
},
{
+ "name": "setDefaultTask",
+ "description": "Sets default task.",
+ "parameters": [
+ {
+ "name": "taskId",
+ "type": "string",
+ "description": "The unique identifier of task to mark as default."
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": true,
+ "parameters": []
+ }
+ ]
+ },
+ {
"name": "getFileTasks",
"description": "Gets the list of tasks that can be performed over selected files.",
"parameters": [