blob: e32cde0df0d381ccea34fa8a731a830a7a2cd621 [file] [log] [blame]
// 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.
#include "chrome/browser/chromeos/file_manager/open_util.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/file_manager/app_id.h"
#include "chrome/browser/chromeos/file_manager/file_tasks.h"
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/chromeos/file_manager/url_util.h"
#include "chrome/browser/extensions/api/file_handlers/mime_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/user_metrics.h"
#include "storage/browser/fileapi/file_system_backend.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
using storage::FileSystemURL;
namespace file_manager {
namespace util {
namespace {
// Shows a warning message box saying that the file could not be opened.
void ShowWarningMessageBox(Profile* profile,
const base::FilePath& file_path,
int message_id) {
Browser* browser = chrome::FindTabbedBrowser(
profile, false, chrome::HOST_DESKTOP_TYPE_ASH);
chrome::ShowMessageBox(
browser ? browser->window()->GetNativeWindow() : NULL,
l10n_util::GetStringFUTF16(
IDS_FILE_BROWSER_ERROR_VIEWING_FILE_TITLE,
base::UTF8ToUTF16(file_path.BaseName().AsUTF8Unsafe())),
l10n_util::GetStringUTF16(message_id),
chrome::MESSAGE_BOX_TYPE_WARNING);
}
// Executes the |task| for the file specified by |url|.
void ExecuteFileTaskForUrl(Profile* profile,
const file_tasks::TaskDescriptor& task,
const GURL& url) {
storage::FileSystemContext* file_system_context =
GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
file_tasks::ExecuteFileTask(
profile,
GetFileManagerMainPageUrl(), // Executing the task on behalf of Files.app.
task,
std::vector<FileSystemURL>(1, file_system_context->CrackURL(url)),
file_tasks::FileTaskFinishedCallback());
}
// Opens the file manager for the specified |url|. Used to implement
// internal handlers of special action IDs:
//
// "open" - Open the file manager for the given folder.
// "auto-open" - Open the file manager for the given removal drive and close
// the file manager when the removal drive is unmounted.
// "select" - Open the file manager for the given file. The folder containing
// the file will be opened with the file selected.
void OpenFileManagerWithInternalActionId(Profile* profile,
const GURL& url,
const std::string& action_id) {
DCHECK(action_id == "auto-open" ||
action_id == "open" ||
action_id == "select");
content::RecordAction(base::UserMetricsAction("ShowFileBrowserFullTab"));
file_tasks::TaskDescriptor task(kFileManagerAppId,
file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
action_id);
ExecuteFileTaskForUrl(profile, task, url);
}
// Opens the file with fetched MIME type and calls the callback.
void OpenFileWithMimeType(Profile* profile,
const base::FilePath& path,
const GURL& url,
const base::Callback<void(bool)>& callback,
const std::string& mime_type) {
extensions::app_file_handler_util::PathAndMimeTypeSet path_mime_set;
path_mime_set.insert(std::make_pair(path, mime_type));
std::vector<GURL> file_urls;
file_urls.push_back(url);
std::vector<file_tasks::FullTaskDescriptor> tasks;
file_tasks::FindAllTypesOfTasks(
profile,
drive::util::GetDriveAppRegistryByProfile(profile),
path_mime_set,
file_urls,
&tasks);
if (tasks.empty()) {
callback.Run(false);
return;
}
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;
}
}
ExecuteFileTaskForUrl(profile, chosen_task->task_descriptor(), url);
callback.Run(true);
}
// Opens the file specified by |url| by finding and executing a file task for
// the file. In case of success, calls |callback| with true. Otherwise the
// returned value is false.
void OpenFile(Profile* profile,
const base::FilePath& path,
const GURL& url,
const base::Callback<void(bool)>& callback) {
extensions::app_file_handler_util::GetMimeTypeForLocalPath(
profile,
path,
base::Bind(&OpenFileWithMimeType, profile, path, url, callback));
}
// Called when execution of ContinueOpenItem() is completed.
void OnContinueOpenItemCompleted(Profile* profile,
const base::FilePath& file_path,
bool result) {
if (!result) {
int message;
if (file_path.Extension() == FILE_PATH_LITERAL(".dmg"))
message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE_FOR_DMG;
else if (file_path.Extension() == FILE_PATH_LITERAL(".exe") ||
file_path.Extension() == FILE_PATH_LITERAL(".msi"))
message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE_FOR_EXECUTABLE;
else
message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE;
ShowWarningMessageBox(profile, file_path, message);
}
}
// Used to implement OpenItem().
void ContinueOpenItem(Profile* profile,
const base::FilePath& file_path,
const GURL& url,
base::File::Error error) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (error == base::File::FILE_OK) {
// A directory exists at |url|. Open it with the file manager.
OpenFileManagerWithInternalActionId(profile, url, "open");
} else {
// |url| should be a file. Open it.
OpenFile(profile,
file_path,
url,
base::Bind(&OnContinueOpenItemCompleted, profile, file_path));
}
}
// Converts the |path| passed from external callers to the filesystem URL
// that the file manager can correctly handle.
//
// When conversion fails, it shows a warning dialog UI and returns false.
bool ConvertPath(Profile* profile, const base::FilePath& path, GURL* url) {
if (!ConvertAbsoluteFilePathToFileSystemUrl(
profile, path, kFileManagerAppId, url)) {
ShowWarningMessageBox(profile, path,
IDS_FILE_BROWSER_ERROR_UNRESOLVABLE_FILE);
return false;
}
return true;
}
} // namespace
void OpenRemovableDrive(Profile* profile, const base::FilePath& file_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GURL url;
if (!ConvertPath(profile, file_path, &url))
return;
OpenFileManagerWithInternalActionId(profile, url, "auto-open");
}
void OpenItem(Profile* profile, const base::FilePath& file_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GURL url;
if (!ConvertPath(profile, file_path, &url))
return;
CheckIfDirectoryExists(
GetFileSystemContextForExtensionId(profile, kFileManagerAppId),
url,
base::Bind(&ContinueOpenItem, profile, file_path, url));
}
void ShowItemInFolder(Profile* profile, const base::FilePath& file_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GURL url;
if (!ConvertPath(profile, file_path, &url))
return;
// This action changes the selection so we do not reuse existing tabs.
OpenFileManagerWithInternalActionId(profile, url, "select");
}
} // namespace util
} // namespace file_manager