Commit 69091a6e authored by satorux@chromium.org's avatar satorux@chromium.org

file_manager: Unify the file task selection logic

Previously, open_util.cc and file_tasks.cc had two separate
implementations of file task selection logic. The one in open_util.cc
was unclean had an issue with the download shelf (issue 279771).
Not to mention, having two separate implementations for doing the
same thing is not good for code health.

This patch replaces the unclean logic in open_util.cc with the one
in file_tasks.cc (FindAllTypesOfTasks()).

BUG=279771,278037,284194
TEST=See steps described in issue 279771
R=kinaba@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221336 0039d316-1c4b-4281-b951-d872f2087c98
parent a7079fa0
......@@ -527,51 +527,7 @@ bool IsFallbackFileBrowserHandler(const file_tasks::TaskDescriptor& task) {
task.app_id == extension_misc::kQuickOfficeExtensionId));
}
FileBrowserHandlerList FindDefaultFileBrowserHandlers(
const PrefService& pref_service,
const std::vector<base::FilePath>& file_list,
const FileBrowserHandlerList& common_handlers) {
FileBrowserHandlerList default_handlers;
std::set<std::string> default_ids;
for (std::vector<base::FilePath>::const_iterator it = file_list.begin();
it != file_list.end(); ++it) {
std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
pref_service, "", it->Extension());
if (!task_id.empty())
default_ids.insert(task_id);
}
const FileBrowserHandler* fallback_handler = NULL;
// Convert the default task IDs collected above to one of the handler pointers
// from common_handlers.
for (size_t i = 0; i < common_handlers.size(); ++i) {
const FileBrowserHandler* handler = common_handlers[i];
const file_tasks::TaskDescriptor task_descriptor(
handler->extension_id(),
file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
handler->id());
const std::string task_id =
file_tasks::TaskDescriptorToId(task_descriptor);
std::set<std::string>::iterator default_iter = default_ids.find(task_id);
if (default_iter != default_ids.end()) {
default_handlers.push_back(handler);
continue;
}
// Remember the first fallback handler.
if (!fallback_handler && IsFallbackFileBrowserHandler(task_descriptor))
fallback_handler = handler;
}
// If there are no default handlers found, use fallback as default.
if (fallback_handler && default_handlers.empty())
default_handlers.push_back(fallback_handler);
return default_handlers;
}
FileBrowserHandlerList FindCommonFileBrowserHandlers(
FileBrowserHandlerList FindFileBrowserHandlers(
Profile* profile,
const std::vector<GURL>& file_list) {
FileBrowserHandlerList common_handlers;
......@@ -622,39 +578,5 @@ FileBrowserHandlerList FindCommonFileBrowserHandlers(
return common_handlers;
}
const FileBrowserHandler* FindFileBrowserHandlerForURLAndPath(
Profile* profile,
const GURL& url,
const base::FilePath& file_path) {
std::vector<GURL> file_urls;
file_urls.push_back(url);
FileBrowserHandlerList common_handlers =
FindCommonFileBrowserHandlers(profile, file_urls);
if (common_handlers.empty())
return NULL;
std::vector<base::FilePath> file_paths;
file_paths.push_back(file_path);
FileBrowserHandlerList default_handlers =
FindDefaultFileBrowserHandlers(*profile->GetPrefs(),
file_paths,
common_handlers);
// If there's none, or more than one, then we don't have a canonical default.
if (!default_handlers.empty()) {
// There should not be multiple default handlers for a single URL.
DCHECK_EQ(1u, default_handlers.size());
return *default_handlers.begin();
}
// If there are no default handlers, use first handler in the list (file
// manager does the same in this situation). TODO(tbarzic): This is not so
// optimal behaviour.
return *common_handlers.begin();
}
} // namespace file_browser_handlers
} // namespace file_manager
......@@ -43,30 +43,12 @@ typedef std::vector<const FileBrowserHandler*> FileBrowserHandlerList;
// extensions.
bool IsFallbackFileBrowserHandler(const file_tasks::TaskDescriptor& task);
// Finds file browser handlers set as default from |common_tasks| for
// |file_list|. If no handlers are set as default, choose the the firstly
// found fallback handler as default.
FileBrowserHandlerList FindDefaultFileBrowserHandlers(
const PrefService& pref_service,
const std::vector<base::FilePath>& file_list,
const FileBrowserHandlerList& common_tasks);
// Returns the list of file browser handlers that can open all files in
// |file_list|.
FileBrowserHandlerList FindCommonFileBrowserHandlers(
FileBrowserHandlerList FindFileBrowserHandlers(
Profile* profile,
const std::vector<GURL>& file_list);
// Finds a file browser handler for a file whose URL is |url| and whose path
// is |path|. Returns the default handler if one is defined (The default
// handler is the one that is assigned to the file manager task button by
// default). If the default handler is not found, tries to match the url with
// one of the file browser handlers.
const FileBrowserHandler* FindFileBrowserHandlerForURLAndPath(
Profile* profile,
const GURL& url,
const base::FilePath& path);
// Executes a file browser handler specified by |extension| of the given
// action ID for |file_urls|. Returns false if undeclared handlers are
// found. |done| is on completion. See also the comment at ExecuteFileTask()
......
......@@ -431,7 +431,7 @@ void FindFileBrowserHandlerTasks(
DCHECK(result_list);
file_browser_handlers::FileBrowserHandlerList common_tasks =
file_browser_handlers::FindCommonFileBrowserHandlers(profile, file_urls);
file_browser_handlers::FindFileBrowserHandlers(profile, file_urls);
if (common_tasks.empty())
return;
......
......@@ -134,129 +134,42 @@ void OpenFileManagerWithInternalActionId(const base::FilePath& file_path,
ExecuteFileTaskForUrl(profile, task, url);
}
// Opens the file specified by |file_path| and |url| with a file handler,
// preferably the default handler for the type of the file. Returns false if
// no file handler is found.
bool OpenFileWithFileHandler(Profile* profile,
const base::FilePath& file_path,
const GURL& url,
const std::string& mime_type,
const std::string& default_task_id) {
ExtensionService* service = profile->GetExtensionService();
if (!service)
return false;
PathAndMimeTypeSet files;
files.insert(std::make_pair(file_path, mime_type));
const extensions::FileHandlerInfo* first_handler = NULL;
const extensions::Extension* extension_for_first_handler = NULL;
// If we find the default handler, we execute it immediately, but otherwise,
// we remember the first handler, and if there was no default handler, simply
// execute the first one.
for (ExtensionSet::const_iterator iter = service->extensions()->begin();
iter != service->extensions()->end();
++iter) {
const Extension* extension = iter->get();
// We don't support using hosted apps to open files.
if (!extension->is_platform_app())
continue;
// We only support apps that specify "incognito: split" if in incognito
// mode.
if (profile->IsOffTheRecord() &&
!service->IsIncognitoEnabled(extension->id()))
continue;
typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList;
FileHandlerList file_handlers = FindFileHandlersForFiles(*extension, files);
for (FileHandlerList::iterator i = file_handlers.begin();
i != file_handlers.end(); ++i) {
const extensions::FileHandlerInfo* handler = *i;
std::string task_id = file_tasks::MakeTaskID(
extension->id(),
file_tasks::TASK_TYPE_FILE_HANDLER,
handler->id);
if (task_id == default_task_id) {
file_tasks::TaskDescriptor task(extension->id(),
file_tasks::TASK_TYPE_FILE_HANDLER,
handler->id);
ExecuteFileTaskForUrl(profile, task, url);
return true;
} else if (!first_handler) {
first_handler = handler;
extension_for_first_handler = extension;
}
}
}
if (first_handler) {
file_tasks::TaskDescriptor task(extension_for_first_handler->id(),
file_tasks::TASK_TYPE_FILE_HANDLER,
first_handler->id);
ExecuteFileTaskForUrl(profile, task, url);
return true;
}
return false;
}
// Opens the file specified by |file_path| and |url| with the file browser
// handler specified by |handler|. Returns false if failed to open the file.
bool OpenFileWithFileBrowserHandler(Profile* profile,
const base::FilePath& file_path,
const FileBrowserHandler& handler,
const GURL& url) {
file_tasks::TaskDescriptor task(handler.extension_id(),
file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
handler.id());
ExecuteFileTaskForUrl(profile, task, url);
return true;
}
// Opens the file specified by |file_path| with a handler (either of file
// browser handler or file handler, preferably the default handler for the
// type of the file), or opens the file with the browser. Returns false if
// failed to open the file.
bool OpenFileWithHandler(Profile* profile, const base::FilePath& file_path) {
// Opens the file specified by |file_path| by finding and executing a file
// task for the file. Returns false if failed to open the file (i.e. no file
// task is found).
bool OpenFile(Profile* profile, const base::FilePath& file_path) {
GURL url;
if (!ConvertAbsoluteFilePathToFileSystemUrl(
profile, file_path, kFileManagerAppId, &url))
return false;
// The file is opened per the file extension, hence extension-less files
// cannot be opened properly.
std::string mime_type = GetMimeTypeForPath(file_path);
std::string default_task_id = file_tasks::GetDefaultTaskIdFromPrefs(
*profile->GetPrefs(), mime_type, file_path.Extension());
// We choose the file handler from the following in decreasing priority or
// fail if none support the file type:
// 1. default file browser handler
// 2. default file handler
// 3. a fallback handler (e.g. opening in the browser)
// 4. non-default file handler
// 5. non-default file browser handler
// Note that there can be at most one of default extension and default app.
const FileBrowserHandler* handler =
file_browser_handlers::FindFileBrowserHandlerForURLAndPath(
profile, url, file_path);
if (!handler) {
return OpenFileWithFileHandler(
profile, file_path, url, mime_type, default_task_id);
}
extensions::app_file_handler_util::PathAndMimeTypeSet path_mime_set;
path_mime_set.insert(std::make_pair(file_path, mime_type));
std::vector<GURL> file_urls;
file_urls.push_back(url);
std::vector<file_tasks::FullTaskDescriptor> tasks;
file_tasks::FindAllTypesOfTasks(profile,
path_mime_set,
file_urls,
&tasks);
if (tasks.empty())
return false;
const file_tasks::TaskDescriptor task_descriptor(
handler->extension_id(),
file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
handler->id());
const std::string handler_task_id =
file_tasks::TaskDescriptorToId(task_descriptor);
if (handler_task_id != default_task_id &&
!file_browser_handlers::IsFallbackFileBrowserHandler(task_descriptor) &&
OpenFileWithFileHandler(
profile, file_path, url, mime_type, default_task_id)) {
return true;
const file_tasks::FullTaskDescriptor* chosen_task = &tasks[0];
for (size_t i = 0; i < tasks.size(); ++i) {
if (tasks[i].is_default()) {
chosen_task = &tasks[i];
break;
}
}
return OpenFileWithFileBrowserHandler(profile, file_path, *handler, url);
ExecuteFileTaskForUrl(profile, chosen_task->task_descriptor(), url);
return true;
}
// Used to implement OpenItem().
......@@ -269,8 +182,8 @@ void ContinueOpenItem(Profile* profile,
// A directory exists at |file_path|. Open it with the file manager.
OpenFileManagerWithInternalActionId(file_path, "open");
} else {
// |file_path| should be a file. Open it with a handler.
if (!OpenFileWithHandler(profile, file_path))
// |file_path| should be a file. Open it.
if (!OpenFile(profile, file_path))
ShowWarningMessageBox(profile, file_path);
}
}
......
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