summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-25 05:08:45 +0000
committerzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-25 05:08:45 +0000
commit906625821f97a508d76810fba7b9641335f68b51 (patch)
tree4c477d7cc2bf16d1a19a24687d825bf9d1f0c9b3 /chrome
parent554abd90c658eb93fb078f3daca2a34b58291747 (diff)
downloadchromium_src-906625821f97a508d76810fba7b9641335f68b51.zip
chromium_src-906625821f97a508d76810fba7b9641335f68b51.tar.gz
chromium_src-906625821f97a508d76810fba7b9641335f68b51.tar.bz2
Merged already reviewed CLs for r/o zip support in ChromeOS file browser:
Re-landing http://codereview.chromium.org/7457001: Adding support for mount point different from removable devices to MountLibrary (work in progress..have to add GetMountPoints support) tested on ChromeOS with these three patches: http://gerrit.chromium.org/gerrit/#change,4447 http://gerrit.chromium.org/gerrit/#change,4449 http://gerrit.chromium.org/gerrit/#change,4544 http://codereview.chromium.org/7471039/: UI for mounting/unmounting archive files. BUG=chromium-os:17673, chromium-os:17783 TEST=Made sure mounting devices still works and that MountCompleted event gets through to file_browser_event_router (checking ui and chrome logs for mount completed entries) TBR=tbarzic, dgozman Review URL: http://codereview.chromium.org/7488044 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93838 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd19
-rw-r--r--chrome/browser/chromeos/cros/mock_mount_library.cc2
-rw-r--r--chrome/browser/chromeos/cros/mock_mount_library.h4
-rw-r--r--chrome/browser/chromeos/cros/mount_library.cc199
-rw-r--r--chrome/browser/chromeos/cros/mount_library.h37
-rw-r--r--chrome/browser/chromeos/extensions/file_browser_event_router.cc84
-rw-r--r--chrome/browser/chromeos/extensions/file_browser_event_router.h8
-rw-r--r--chrome/browser/extensions/extension_event_names.cc2
-rw-r--r--chrome/browser/extensions/extension_event_names.h1
-rw-r--r--chrome/browser/extensions/extension_file_browser_private_api.cc224
-rw-r--r--chrome/browser/extensions/extension_file_browser_private_api.h85
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc4
-rw-r--r--chrome/browser/extensions/file_manager_util.cc27
-rw-r--r--chrome/browser/extensions/file_manager_util.h8
-rw-r--r--chrome/browser/profiles/profile_impl.cc16
-rw-r--r--chrome/browser/resources/component_extension_resources.grd2
-rw-r--r--chrome/browser/resources/file_manager/images/icon_mount_archive_16x16.pngbin0 -> 3092 bytes
-rw-r--r--chrome/browser/resources/file_manager/images/icon_unmount_archive_16x16.pngbin0 -> 3207 bytes
-rw-r--r--chrome/browser/resources/file_manager/js/file_manager.js143
-rw-r--r--chrome/browser/resources/file_manager/js/main.js2
-rw-r--r--chrome/browser/resources/file_manager/js/mock_chrome.js84
-rw-r--r--chrome/browser/resources/file_manager/manifest.json16
-rw-r--r--chrome/browser/ui/webui/chromeos/imageburner/webui_handler.h4
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/extensions/api/extension_api.json118
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js2
-rw-r--r--chrome/test/data/extensions/api_test/webstore_private/common.js4
28 files changed, 943 insertions, 156 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 60a4e531..965e792 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -8817,12 +8817,15 @@ ls' lab.">
<message name="IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_LABEL" desc="/Downloads directory label.">
File Shelf
</message>
- <message name="IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_WARNING" desc="Warning displayed to user when viewing downloads folder.">
- <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Caution:<ph name="END_BOLD">&lt;/strong&gt;</ph> These files are temporary and may be automatically deleted to free up disk space. <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>Learn More<ph name="END_LINK">&lt;/a&gt;</ph>
+ <message name="IDS_FILE_BROWSER_ARCHIVE_DIRECTORY_LABEL" desc="/archive directory label.">
+ Archives
</message>
- <message name="IDS_FILE_BROWSER_MEDIA_DIRECTORY_LABEL" desc="/media directory label.">
+ <message name="IDS_FILE_BROWSER_REMOVABLE_DIRECTORY_LABEL" desc="/removable directory label.">
External Storage
</message>
+ <message name="IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_WARNING" desc="Warning displayed to user when viewing downloads folder.">
+ <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Caution:<ph name="END_BOLD">&lt;/strong&gt;</ph> These files are temporary and may be automatically deleted to free up disk space. <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>Learn More<ph name="END_LINK">&lt;/a&gt;</ph>
+ </message>
<message name="IDS_FILE_BROWSER_NAME_COLUMN_LABEL" desc="Name column label.">
Name
</message>
@@ -8880,6 +8883,16 @@ ls' lab.">
Read Only
</message>
+ <message name="IDS_FILE_BROWSER_ARCHIVE_MOUNT_FAILED" desc="Title of the error dialog when file mount operation failed.">
+ Unable to open open "$1": $2
+ </message>
+ <message name="IDS_FILE_BROWSER_MOUNT_ARCHIVE" desc="Title of the action for mounting an archive file to work with its contents.">
+ Open archive
+ </message>
+ <message name="IDS_FILE_BROWSER_UNMOUNT_ARCHIVE" desc="Title of the action for unmounting the archive file.">
+ Close archive
+ </message>
+
<message name="IDS_FILE_BROWSER_CONFIRM_OVERWRITE_FILE" desc="Asks the user if they are sure they want to overwrite an existing file with another one.">
A file named "$1" already exists. Do you want to replace it?
</message>
diff --git a/chrome/browser/chromeos/cros/mock_mount_library.cc b/chrome/browser/chromeos/cros/mock_mount_library.cc
index 3e826a3..889522d 100644
--- a/chrome/browser/chromeos/cros/mock_mount_library.cc
+++ b/chrome/browser/chromeos/cros/mock_mount_library.cc
@@ -128,7 +128,7 @@ void MockMountLibrary::SetupDefaultReplies() {
.WillRepeatedly(ReturnRef(disks_));
EXPECT_CALL(*this, RequestMountInfoRefresh())
.Times(AnyNumber());
- EXPECT_CALL(*this, MountPath(_))
+ EXPECT_CALL(*this, MountPath(_, _, _))
.Times(AnyNumber());
EXPECT_CALL(*this, UnmountPath(_))
.Times(AnyNumber());
diff --git a/chrome/browser/chromeos/cros/mock_mount_library.h b/chrome/browser/chromeos/cros/mock_mount_library.h
index c648569..5965f2c 100644
--- a/chrome/browser/chromeos/cros/mock_mount_library.h
+++ b/chrome/browser/chromeos/cros/mock_mount_library.h
@@ -25,9 +25,11 @@ class MockMountLibrary : public MountLibrary {
MOCK_METHOD1(AddObserver, void(MountLibrary::Observer*));
MOCK_METHOD1(RemoveObserver, void(MountLibrary::Observer*));
MOCK_CONST_METHOD0(disks, const MountLibrary::DiskMap&(void));
+ MOCK_CONST_METHOD0(mount_points, const MountLibrary::MountPointMap&(void));
MOCK_METHOD0(RequestMountInfoRefresh, void(void));
- MOCK_METHOD1(MountPath, void(const char*));
+ MOCK_METHOD3(MountPath, void(const char*, MountType,
+ const MountPathOptions&));
MOCK_METHOD1(UnmountPath, void(const char*));
MOCK_METHOD3(UnmountDeviceRecursive, void(const char*,
MountLibrary::UnmountDeviceRecursiveCallbackType, void*));
diff --git a/chrome/browser/chromeos/cros/mount_library.cc b/chrome/browser/chromeos/cros/mount_library.cc
index 79e723a..df0b2c0 100644
--- a/chrome/browser/chromeos/cros/mount_library.cc
+++ b/chrome/browser/chromeos/cros/mount_library.cc
@@ -16,6 +16,38 @@ const char* kDeviceNotFound = "Device could not be found";
namespace chromeos {
+// static
+std::string MountLibrary::MountTypeToString(MountType type) {
+ switch (type) {
+ case MOUNT_TYPE_DEVICE:
+ return "device";
+ case MOUNT_TYPE_ARCHIVE:
+ return "file";
+ case MOUNT_TYPE_NETWORK_STORAGE:
+ return "network";
+ case MOUNT_TYPE_INVALID:
+ return "invalid";
+ default:
+ NOTREACHED();
+ }
+ return "";
+}
+
+// static
+MountType MountLibrary::MountTypeFromString(
+ const std::string& type_str)
+ OVERRIDE {
+ if (type_str == "device") {
+ return MOUNT_TYPE_DEVICE;
+ } else if (type_str == "network") {
+ return MOUNT_TYPE_NETWORK_STORAGE;
+ } else if (type_str == "file") {
+ return MOUNT_TYPE_ARCHIVE;
+ } else {
+ return MOUNT_TYPE_INVALID;
+ }
+}
+
MountLibrary::Disk::Disk(const std::string& device_path,
const std::string& mount_path,
const std::string& system_path,
@@ -90,31 +122,27 @@ class MountLibraryImpl : public MountLibrary {
observers_.RemoveObserver(observer);
}
- virtual void MountPath(const char* device_path) OVERRIDE {
+ virtual void MountPath(const char* source_path,
+ MountType type,
+ const MountPathOptions& options) OVERRIDE {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!CrosLibrary::Get()->EnsureLoaded()) {
- OnMountRemovableDevice(device_path,
- NULL,
- MOUNT_METHOD_ERROR_LOCAL,
- kLibraryNotLoaded);
+ OnMountCompleted(MOUNT_ERROR_LIBRARY_NOT_LOADED,
+ MountPointInfo(source_path, NULL, type));
return;
}
- MountRemovableDevice(device_path,
- &MountLibraryImpl::MountRemovableDeviceCallback,
- this);
+ MountSourcePath(source_path, type, options, &MountCompletedHandler, this);
}
- virtual void UnmountPath(const char* device_path) OVERRIDE {
+ virtual void UnmountPath(const char* path) OVERRIDE {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!CrosLibrary::Get()->EnsureLoaded()) {
- OnUnmountRemovableDevice(device_path,
- MOUNT_METHOD_ERROR_LOCAL,
- kLibraryNotLoaded);
+ OnUnmountPath(path,
+ MOUNT_METHOD_ERROR_LOCAL,
+ kLibraryNotLoaded);
return;
}
- UnmountRemovableDevice(device_path,
- &MountLibraryImpl::UnmountRemovableDeviceCallback,
- this);
+ UnmountMountPoint(path, &MountLibraryImpl::UnmountMountPointCallback, this);
}
virtual void UnmountDeviceRecursive(const char* device_path,
@@ -151,9 +179,10 @@ class MountLibraryImpl : public MountLibrary {
cb_data = new UnmountDeviceRecursiveCallbackData(this, user_data,
callback, devices_to_unmount.size());
for (std::vector<const char*>::iterator it = devices_to_unmount.begin();
- it != devices_to_unmount.end();
- ++it) {
- UnmountRemovableDevice(*it,
+ it != devices_to_unmount.end();
+ ++it) {
+ UnmountMountPoint(
+ *it,
&MountLibraryImpl::UnmountDeviceRecursiveCallback,
cb_data);
}
@@ -178,39 +207,34 @@ class MountLibraryImpl : public MountLibrary {
}
const DiskMap& disks() const OVERRIDE { return disks_; }
+ const MountPointMap& mount_points() const OVERRIDE { return mount_points_; }
private:
- // Callback for MountRemovableDevice method.
- static void MountRemovableDeviceCallback(void* object,
- const char* device_path,
- const char* mount_path,
- MountMethodErrorType error,
- const char* error_message) {
+ // Callback for MountComplete signal and MountSourcePath method.
+ static void MountCompletedHandler(void* object,
+ MountError error_code,
+ const char* source_path,
+ MountType type,
+ const char* mount_path) {
DCHECK(object);
MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object);
- self->OnMountRemovableDevice(device_path,
- mount_path,
- error,
- error_message);
+ self->OnMountCompleted(static_cast<MountError>(error_code),
+ MountPointInfo(source_path, mount_path, type));
}
// Callback for UnmountRemovableDevice method.
- static void UnmountRemovableDeviceCallback(void* object,
- const char* device_path,
- const char* mount_path,
- MountMethodErrorType error,
- const char* error_message) {
+ static void UnmountMountPointCallback(void* object,
+ const char* device_path,
+ MountMethodErrorType error,
+ const char* error_message) {
DCHECK(object);
MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object);
- self->OnUnmountRemovableDevice(device_path,
- error,
- error_message);
+ self->OnUnmountPath(device_path, error, error_message);
}
// Callback for UnmountDeviceRecursive.
static void UnmountDeviceRecursiveCallback(void* object,
const char* device_path,
- const char* mount_path,
MountMethodErrorType error,
const char* error_message) {
DCHECK(object);
@@ -218,9 +242,9 @@ class MountLibraryImpl : public MountLibrary {
static_cast<UnmountDeviceRecursiveCallbackData*>(object);
// Do standard processing for Unmount event.
- cb_data->object->OnUnmountRemovableDevice(device_path,
- error,
- error_message);
+ cb_data->object->OnUnmountPath(device_path,
+ error,
+ error_message);
if (error == MOUNT_METHOD_ERROR_LOCAL) {
cb_data->success = false;
} else if (error == MOUNT_METHOD_ERROR_NONE) {
@@ -275,14 +299,26 @@ class MountLibraryImpl : public MountLibrary {
}
- void OnMountRemovableDevice(const char* device_path,
- const char* mount_path,
- MountMethodErrorType error,
- const char* error_message) {
- DCHECK(device_path);
+ void OnMountCompleted(MountError error_code,
+ const MountPointInfo& mount_info) {
+ DCHECK(!mount_info.source_path.empty());
- if (error == MOUNT_METHOD_ERROR_NONE && device_path && mount_path) {
- std::string path(device_path);
+ FireMountCompleted(MOUNTING,
+ error_code,
+ mount_info);
+
+ if (error_code == MOUNT_ERROR_NONE &&
+ mount_points_.find(mount_info.source_path) == mount_points_.end()) {
+ mount_points_.insert(MountPointMap::value_type(
+ mount_info.source_path.c_str(),
+ mount_info));
+ }
+
+ if (error_code == MOUNT_ERROR_NONE &&
+ mount_info.mount_type == MOUNT_TYPE_DEVICE &&
+ !mount_info.source_path.empty() &&
+ !mount_info.mount_path.empty()) {
+ std::string path(mount_info.source_path);
DiskMap::iterator iter = disks_.find(path);
if (iter == disks_.end()) {
// disk might have been removed by now?
@@ -290,21 +326,30 @@ class MountLibraryImpl : public MountLibrary {
}
Disk* disk = iter->second;
DCHECK(disk);
- disk->set_mount_path(mount_path);
+ disk->set_mount_path(mount_info.mount_path.c_str());
FireDiskStatusUpdate(MOUNT_DISK_MOUNTED, disk);
- } else {
- LOG(WARNING) << "Mount request failed for device "
- << device_path << ", with error: "
- << (error_message ? error_message : "Unknown");
}
}
- void OnUnmountRemovableDevice(const char* device_path,
- MountMethodErrorType error,
- const char* error_message) {
- DCHECK(device_path);
- if (error == MOUNT_METHOD_ERROR_NONE && device_path) {
- std::string path(device_path);
+ void OnUnmountPath(const char* source_path,
+ MountMethodErrorType error,
+ const char* error_message) {
+ DCHECK(source_path);
+
+ if (error == MOUNT_METHOD_ERROR_NONE && source_path) {
+ MountPointMap::iterator mount_points_it = mount_points_.find(source_path);
+ if (mount_points_it == mount_points_.end())
+ return;
+ // TODO(tbarzic): Add separate, PathUnmounted event to Observer.
+ FireMountCompleted(
+ UNMOUNTING,
+ MOUNT_ERROR_NONE,
+ MountPointInfo(mount_points_it->second.source_path.c_str(),
+ mount_points_it->second.mount_path.c_str(),
+ mount_points_it->second.mount_type));
+ mount_points_.erase(mount_points_it);
+
+ std::string path(source_path);
DiskMap::iterator iter = disks_.find(path);
if (iter == disks_.end()) {
// disk might have been removed by now?
@@ -316,7 +361,7 @@ class MountLibraryImpl : public MountLibrary {
FireDiskStatusUpdate(MOUNT_DISK_UNMOUNTED, disk);
} else {
LOG(WARNING) << "Unmount request failed for device "
- << device_path << ", with error: "
+ << source_path << ", with error: "
<< (error_message ? error_message : "Unknown");
}
}
@@ -476,16 +521,17 @@ class MountLibraryImpl : public MountLibrary {
type = MOUNT_DEVICE_SCANNED;
break;
}
- default:
+ default: {
return;
+ }
}
FireDeviceStatusUpdate(type, std::string(device_path));
}
void Init() {
// Getting the monitor status so that the daemon starts up.
- mount_status_connection_ = MonitorMountEvents(
- &MonitorMountEventsHandler, this);
+ mount_status_connection_ = MonitorAllMountEvents(
+ &MonitorMountEventsHandler, &MountCompletedHandler, this);
}
void FireDiskStatusUpdate(MountLibraryEventType evt,
@@ -504,6 +550,17 @@ class MountLibraryImpl : public MountLibrary {
Observer, observers_, DeviceChanged(evt, device_path));
}
+ void FireMountCompleted(MountEvent event_type,
+ MountError error_code,
+ const MountPointInfo& mount_info) {
+ // Make sure we run on UI thread.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ FOR_EACH_OBSERVER(
+ Observer, observers_, MountCompleted(event_type,
+ error_code,
+ mount_info));
+ }
+
// Mount event change observers.
ObserverList<Observer> observers_;
@@ -514,6 +571,8 @@ class MountLibraryImpl : public MountLibrary {
// The list of disks found.
MountLibrary::DiskMap disks_;
+ MountLibrary::MountPointMap mount_points_;
+
DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl);
};
@@ -526,9 +585,20 @@ class MountLibraryStubImpl : public MountLibrary {
virtual void AddObserver(Observer* observer) OVERRIDE {}
virtual void RemoveObserver(Observer* observer) OVERRIDE {}
virtual const DiskMap& disks() const OVERRIDE { return disks_; }
+ virtual const MountPointMap& mount_points() const OVERRIDE {
+ return mount_points_;
+ }
+ virtual std::string MountTypeToString(MountType type) const OVERRIDE {
+ return "";
+ }
+ virtual MountType MountTypeFromString(const std::string& type_str) const
+ OVERRIDE {
+ return MOUNT_TYPE_INVALID;
+ }
virtual void RequestMountInfoRefresh() OVERRIDE {}
- virtual void MountPath(const char* device_path) OVERRIDE {}
- virtual void UnmountPath(const char* device_path) OVERRIDE {}
+ virtual void MountPath(const char* source_path, MountType type,
+ const MountPathOptions& options) OVERRIDE {}
+ virtual void UnmountPath(const char* path) OVERRIDE {}
virtual void UnmountDeviceRecursive(const char* device_path,
UnmountDeviceRecursiveCallbackType callback, void* user_data)
OVERRIDE {}
@@ -536,6 +606,7 @@ class MountLibraryStubImpl : public MountLibrary {
private:
// The list of disks found.
DiskMap disks_;
+ MountPointMap mount_points_;
DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl);
};
diff --git a/chrome/browser/chromeos/cros/mount_library.h b/chrome/browser/chromeos/cros/mount_library.h
index b735d3d..8be7a8a 100644
--- a/chrome/browser/chromeos/cros/mount_library.h
+++ b/chrome/browser/chromeos/cros/mount_library.h
@@ -6,8 +6,8 @@
#define CHROME_BROWSER_CHROMEOS_CROS_MOUNT_LIBRARY_H_
#pragma once
-#include <string>
#include <map>
+#include <string>
#include "base/memory/singleton.h"
#include "base/observer_list.h"
@@ -32,6 +32,10 @@ typedef enum MountLibraryEventType {
// library class like this: chromeos::CrosLibrary::Get()->GetMountLibrary()
class MountLibrary {
public:
+ enum MountEvent {
+ MOUNTING,
+ UNMOUNTING
+ };
// Used to house an instance of each found mount device.
class Disk {
public:
@@ -97,6 +101,22 @@ class MountLibrary {
};
typedef std::map<std::string, Disk*> DiskMap;
+ // MountPointInfo: {mount_path, mount_type}.
+ struct MountPointInfo {
+ std::string source_path;
+ std::string mount_path;
+ MountType mount_type;
+
+ MountPointInfo(const char* source, const char* mount, const MountType type)
+ : source_path(source ? source : ""),
+ mount_path(mount ? mount : ""),
+ mount_type(type) {
+ }
+ };
+
+ // MountPointMap key is source_path.
+ typedef std::map<std::string, MountPointInfo> MountPointMap;
+
typedef void(*UnmountDeviceRecursiveCallbackType)(void*, bool);
class Observer {
@@ -107,21 +127,32 @@ class MountLibrary {
const Disk* disk) = 0;
virtual void DeviceChanged(MountLibraryEventType event,
const std::string& device_path ) = 0;
+ virtual void MountCompleted(MountEvent event_type,
+ MountError error_code,
+ const MountPointInfo& mount_info) = 0;
};
virtual ~MountLibrary() {}
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
virtual const DiskMap& disks() const = 0;
+ virtual const MountPointMap& mount_points() const = 0;
virtual void RequestMountInfoRefresh() = 0;
- virtual void MountPath(const char* device_path) = 0;
- virtual void UnmountPath(const char* device_path) = 0;
+ virtual void MountPath(const char* source_path,
+ MountType type,
+ const MountPathOptions& options) = 0;
+ // |path| may be source od mount path.
+ virtual void UnmountPath(const char* path) = 0;
// Unmounts device_poath and all of its known children.
virtual void UnmountDeviceRecursive(const char* device_path,
UnmountDeviceRecursiveCallbackType callback, void* user_data) = 0;
+ // Helper functions for parameter conversions.
+ static std::string MountTypeToString(MountType type);
+ static MountType MountTypeFromString(const std::string& type_str);
+
// Factory function, creates a new instance and returns ownership.
// For normal usage, access the singleton via CrosLibrary::Get().
static MountLibrary* GetImpl(bool stub);
diff --git a/chrome/browser/chromeos/extensions/file_browser_event_router.cc b/chrome/browser/chromeos/extensions/file_browser_event_router.cc
index df0d61e..91df6b3 100644
--- a/chrome/browser/chromeos/extensions/file_browser_event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_browser_event_router.cc
@@ -42,6 +42,28 @@ const char* DeviceTypeToString(chromeos::DeviceType type) {
return "undefined";
}
+const char* MountErrorToString(chromeos::MountError error) {
+ switch (error) {
+ case chromeos::MOUNT_ERROR_NONE:
+ return "success";
+ case chromeos::MOUNT_ERROR_UNKNOWN:
+ return "error_unknown";
+ case chromeos::MOUNT_ERROR_INTERNAL:
+ return "error_internal";
+ case chromeos::MOUNT_ERROR_UNKNOWN_FILESYSTEM:
+ return "error_unknown_filesystem";
+ case chromeos::MOUNT_ERROR_UNSUPORTED_FILESYSTEM:
+ return "error_unsuported_filesystem";
+ case chromeos::MOUNT_ERROR_INVALID_ARCHIVE:
+ return "error_invalid_archive";
+ case chromeos::MOUNT_ERROR_LIBRARY_NOT_LOADED:
+ return "error_libcros_missing";
+ default:
+ NOTREACHED();
+ }
+ return "";
+}
+
DictionaryValue* DiskToDictionaryValue(
const chromeos::MountLibrary::Disk* disk) {
DictionaryValue* result = new DictionaryValue();
@@ -152,6 +174,12 @@ void ExtensionFileBrowserEventRouter::DeviceChanged(
OnDeviceScanned(device_path);
}
}
+void ExtensionFileBrowserEventRouter::MountCompleted(
+ chromeos::MountLibrary::MountEvent event_type,
+ chromeos::MountError error_code,
+ const chromeos::MountLibrary::MountPointInfo& mount_info) {
+ DispatchMountCompletedEvent(event_type, error_code, mount_info);
+}
void ExtensionFileBrowserEventRouter::HandleFileWatchNotification(
const FilePath& local_path, bool got_error) {
@@ -218,6 +246,58 @@ void ExtensionFileBrowserEventRouter::DispatchMountEvent(
GURL());
}
+void ExtensionFileBrowserEventRouter::DispatchMountCompletedEvent(
+ chromeos::MountLibrary::MountEvent event,
+ chromeos::MountError error_code,
+ const chromeos::MountLibrary::MountPointInfo& mount_info) {
+ if (!profile_ || mount_info.mount_type == chromeos::MOUNT_TYPE_INVALID) {
+ NOTREACHED();
+ return;
+ }
+
+ ListValue args;
+ DictionaryValue* mount_info_value = new DictionaryValue();
+ args.Append(mount_info_value);
+ if (event == chromeos::MountLibrary::MOUNTING) {
+ mount_info_value->SetString("eventType", "mount");
+ } else {
+ mount_info_value->SetString("eventType", "unmount");
+ }
+ mount_info_value->SetString("status", MountErrorToString(error_code));
+ mount_info_value->SetString("mountType",
+ chromeos::MountLibrary::MountTypeToString(mount_info.mount_type));
+
+ if (mount_info.mount_type == chromeos::MOUNT_TYPE_ARCHIVE) {
+ GURL source_url;
+ if (FileManagerUtil::ConvertFileToFileSystemUrl(profile_,
+ FilePath(mount_info.source_path),
+ FileManagerUtil::GetFileBrowserExtensionUrl().GetOrigin(),
+ &source_url)) {
+ mount_info_value->SetString("sourceUrl", source_url.spec());
+ }
+ } else {
+ mount_info_value->SetString("sourceUrl", mount_info.source_path);
+ }
+
+ // If there were no error, add mountPath to the event.
+ if (error_code == chromeos::MOUNT_ERROR_NONE) {
+ FilePath relative_mount_path;
+ // Convert mount point path to relative path with the external file system
+ // exposed within File API.
+ if (FileManagerUtil::ConvertFileToRelativeFileSystemPath(profile_,
+ FilePath(mount_info.mount_path),
+ &relative_mount_path)) {
+ mount_info_value->SetString("mountPath", relative_mount_path.value());
+ }
+ }
+
+ std::string args_json;
+ base::JSONWriter::Write(&args, false /* pretty_print */, &args_json);
+ profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
+ extension_event_names::kOnFileBrowserMountCompleted, args_json, NULL,
+ GURL());
+}
+
void ExtensionFileBrowserEventRouter::OnDiskAdded(
const chromeos::MountLibrary::Disk* disk) {
VLOG(1) << "Disk added: " << disk->device_path();
@@ -237,7 +317,9 @@ void ExtensionFileBrowserEventRouter::OnDiskAdded(
// Initiate disk mount operation.
chromeos::MountLibrary* lib =
chromeos::CrosLibrary::Get()->GetMountLibrary();
- lib->MountPath(disk->device_path().c_str());
+ lib->MountPath(disk->device_path().c_str(),
+ chromeos::MOUNT_TYPE_DEVICE,
+ chromeos::MountPathOptions()); // Unused.
}
}
diff --git a/chrome/browser/chromeos/extensions/file_browser_event_router.h b/chrome/browser/chromeos/extensions/file_browser_event_router.h
index fb8047d..ebc7f6c 100644
--- a/chrome/browser/chromeos/extensions/file_browser_event_router.h
+++ b/chrome/browser/chromeos/extensions/file_browser_event_router.h
@@ -47,6 +47,10 @@ class ExtensionFileBrowserEventRouter
virtual void DeviceChanged(chromeos::MountLibraryEventType event,
const std::string& device_path) OVERRIDE;
+ virtual void MountCompleted(chromeos::MountLibrary::MountEvent event_type,
+ chromeos::MountError error_code,
+ const chromeos::MountLibrary::MountPointInfo& mount_info) OVERRIDE;
+
private:
typedef std::map<std::string, linked_ptr<chromeos::SystemNotification> >
NotificationMap;
@@ -103,6 +107,10 @@ class ExtensionFileBrowserEventRouter
// Sends filesystem changed extension message to all renderers.
void DispatchMountEvent(const chromeos::MountLibrary::Disk* disk, bool added);
+ void DispatchMountCompletedEvent(chromeos::MountLibrary::MountEvent event,
+ chromeos::MountError error_code,
+ const chromeos::MountLibrary::MountPointInfo& mount_info);
+
void RemoveBrowserFromVector(const std::string& path);
// Used to create a window of a standard size, and add it to a list
diff --git a/chrome/browser/extensions/extension_event_names.cc b/chrome/browser/extensions/extension_event_names.cc
index 76c0d8f..fc226f3 100644
--- a/chrome/browser/extensions/extension_event_names.cc
+++ b/chrome/browser/extensions/extension_event_names.cc
@@ -25,6 +25,8 @@ const char kOnExtensionDisabled[] = "management.onDisabled";
const char kOnFileBrowserDiskChanged[] = "fileBrowserPrivate.onDiskChanged";
const char kOnFileChanged[] = "fileBrowserPrivate.onFileChanged";
+const char kOnFileBrowserMountCompleted[] =
+ "fileBrowserPrivate.onMountCompleted";
const char kOnInputMethodChanged[] = "inputMethodPrivate.onChanged";
} // namespace extension_event_names
diff --git a/chrome/browser/extensions/extension_event_names.h b/chrome/browser/extensions/extension_event_names.h
index b6958e2..0b26e4f 100644
--- a/chrome/browser/extensions/extension_event_names.h
+++ b/chrome/browser/extensions/extension_event_names.h
@@ -33,6 +33,7 @@ extern const char kOnExtensionDisabled[];
// FileBrowser.
extern const char kOnFileBrowserDiskChanged[];
extern const char kOnFileChanged[];
+extern const char kOnFileBrowserMountCompleted[];
// InputMethod.
extern const char kOnInputMethodChanged[];
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.cc b/chrome/browser/extensions/extension_file_browser_private_api.cc
index a5f386f..95dbc0c 100644
--- a/chrome/browser/extensions/extension_file_browser_private_api.cc
+++ b/chrome/browser/extensions/extension_file_browser_private_api.cc
@@ -238,6 +238,40 @@ void UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id) {
base::Time::kMicrosecondsPerSecond)));
}
+#ifdef OS_CHROMEOS
+base::DictionaryValue* MountPointToValue(Profile* profile,
+ const chromeos::MountLibrary::MountPointInfo& mount_point_info) {
+
+ base::DictionaryValue *mount_info = new base::DictionaryValue();
+
+ mount_info->SetString("mountType",
+ chromeos::MountLibrary::MountTypeToString(mount_point_info.mount_type));
+
+ if (mount_point_info.mount_type == chromeos::MOUNT_TYPE_ARCHIVE) {
+ GURL source_url;
+ if (FileManagerUtil::ConvertFileToFileSystemUrl(profile,
+ FilePath(mount_point_info.source_path),
+ FileManagerUtil::GetFileBrowserExtensionUrl().GetOrigin(),
+ &source_url)) {
+ mount_info->SetString("sourceUrl", source_url.spec());
+ }
+ } else {
+ mount_info->SetString("sourceUrl", mount_point_info.source_path);
+ }
+
+ FilePath relative_mount_path;
+ // Convert mount point path to relative path with the external file system
+ // exposed within File API.
+ if (FileManagerUtil::ConvertFileToRelativeFileSystemPath(profile,
+ FilePath(mount_point_info.mount_path),
+ &relative_mount_path)) {
+ mount_info->SetString("mountPath", relative_mount_path.value());
+ }
+
+ return mount_info;
+}
+#endif
+
class LocalFileSystemCallbackDispatcher
: public fileapi::FileSystemCallbackDispatcher {
@@ -869,13 +903,13 @@ void ExecuteTasksFileBrowserFunction::ExecuteFileActionsOnUIThread(
SendResponse(true);
}
-FileDialogFunction::FileDialogFunction() {
+FileBrowserFunction::FileBrowserFunction() {
}
-FileDialogFunction::~FileDialogFunction() {
+FileBrowserFunction::~FileBrowserFunction() {
}
-int32 FileDialogFunction::GetTabId() const {
+int32 FileBrowserFunction::GetTabId() const {
int32 tab_id = 0;
if (!dispatcher()) {
NOTREACHED();
@@ -884,8 +918,9 @@ int32 FileDialogFunction::GetTabId() const {
// TODO(jamescook): This is going to fail when we switch to tab-modal
// dialogs. Figure out a way to find which SelectFileDialog::Listener
- // to call from inside these extension FileDialogFunctions.
- Browser* browser = const_cast<FileDialogFunction*>(this)->GetCurrentBrowser();
+ // to call from inside these extension FileBrowserFunctions.
+ Browser* browser =
+ const_cast<FileBrowserFunction*>(this)->GetCurrentBrowser();
if (browser) {
TabContents* contents = browser->GetSelectedTabContents();
if (contents)
@@ -898,8 +933,8 @@ int32 FileDialogFunction::GetTabId() const {
// so here we are. This function takes a vector of virtual paths, converts
// them to local paths and calls GetLocalPathsResponseOnUIThread with the
// result vector, on the UI thread.
-void FileDialogFunction::GetLocalPathsOnFileThread(const UrlList& file_urls,
- const std::string& task_id) {
+void FileBrowserFunction::GetLocalPathsOnFileThread(const UrlList& file_urls,
+ void* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
FilePathList selected_files;
@@ -938,13 +973,11 @@ void FileDialogFunction::GetLocalPathsOnFileThread(const UrlList& file_urls,
}
#endif
- if (!selected_files.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this,
- &FileDialogFunction::GetLocalPathsResponseOnUIThread,
- selected_files, task_id));
- }
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &FileBrowserFunction::GetLocalPathsResponseOnUIThread,
+ selected_files, context));
}
bool SelectFileFunction::RunImpl() {
@@ -960,14 +993,15 @@ bool SelectFileFunction::RunImpl() {
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(this,
&SelectFileFunction::GetLocalPathsOnFileThread,
- file_paths, std::string()));
+ file_paths, reinterpret_cast<void*>(NULL)));
return true;
}
void SelectFileFunction::GetLocalPathsResponseOnUIThread(
- const FilePathList& files, const std::string& task_id) {
+ const FilePathList& files, void* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!context);
if (files.size() != 1) {
SendResponse(false);
return;
@@ -1011,18 +1045,23 @@ bool ViewFilesFunction::RunImpl() {
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(this,
&ViewFilesFunction::GetLocalPathsOnFileThread,
- file_urls, internal_task_id));
+ file_urls,
+ reinterpret_cast<void*>(new std::string(internal_task_id))));
return true;
}
void ViewFilesFunction::GetLocalPathsResponseOnUIThread(
- const FilePathList& files, const std::string& internal_task_id) {
+ const FilePathList& files, void* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(context);
+ scoped_ptr<std::string> internal_task_id(
+ reinterpret_cast<std::string*>(context));
for (FilePathList::const_iterator iter = files.begin();
iter != files.end();
++iter) {
- FileManagerUtil::ViewItem(*iter, internal_task_id == kEnqueueTaskId);
+ FileManagerUtil::ViewItem(*iter,
+ *(internal_task_id.get()) == kEnqueueTaskId);
}
SendResponse(true);
}
@@ -1055,14 +1094,15 @@ bool SelectFilesFunction::RunImpl() {
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(this,
&SelectFilesFunction::GetLocalPathsOnFileThread,
- file_urls, std::string()));
+ file_urls, reinterpret_cast<void*>(NULL)));
return true;
}
void SelectFilesFunction::GetLocalPathsResponseOnUIThread(
- const FilePathList& files, const std::string& internal_task_id) {
+ const FilePathList& files, void* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!context);
int32 tab_id = GetTabId();
FileManagerDialog::OnMultiFilesSelected(tab_id, files);
SendResponse(true);
@@ -1075,31 +1115,150 @@ bool CancelFileDialogFunction::RunImpl() {
return true;
}
-UnmountVolumeFunction::UnmountVolumeFunction() {
+AddMountFunction::AddMountFunction() {
+}
+
+AddMountFunction::~AddMountFunction() {
+}
+
+bool AddMountFunction::RunImpl() {
+ if (args_->GetSize() != 2 && args_->GetSize() != 3) {
+ error_ = "Invalid argument count";
+ return false;
+ }
+
+ std::string file_url;
+ if (!args_->GetString(0, &file_url)) {
+ return false;
+ }
+
+ std::string mount_type_str;
+ if (!args_->GetString(1, &mount_type_str)) {
+ return false;
+ }
+
+ UrlList file_paths;
+ file_paths.push_back(GURL(file_url));
+
+ chromeos::MountPathOptions options;
+ if (args_->GetSize() == 3) {
+ DictionaryValue *dict;
+ if (!args_->GetDictionary(2, &dict)) {
+ NOTREACHED();
+ }
+
+ for (base::DictionaryValue::key_iterator it = dict->begin_keys();
+ it != dict->end_keys();
+ ++it) {
+ std::string value;
+ if (!dict->GetString(*it, &value)) {
+ NOTREACHED();
+ }
+
+ options.push_back(chromeos::MountPathOptions::value_type((*it).c_str(),
+ value.c_str()));
+ }
+ }
+
+ MountParamaters* params = new MountParamaters(mount_type_str, options);
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &AddMountFunction::GetLocalPathsOnFileThread,
+ file_paths, reinterpret_cast<void*>(params)));
+
+ return true;
+}
+
+void AddMountFunction::GetLocalPathsResponseOnUIThread(
+ const FilePathList& files, void* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(context);
+ scoped_ptr<MountParamaters> params(
+ reinterpret_cast<MountParamaters*>(context));
+
+ if (!files.size()) {
+ SendResponse(false);
+ return;
+ }
+
+ const std::string& mount_type_str = params->mount_type;
+ const chromeos::MountPathOptions& options = params->mount_options;
+ FilePath::StringType source_file = files[0].value();
+
+#ifdef OS_CHROMEOS
+ chromeos::MountLibrary *mount_lib =
+ chromeos::CrosLibrary::Get()->GetMountLibrary();
+
+ chromeos::MountType mount_type =
+ mount_lib->MountTypeFromString(mount_type_str);
+ if (mount_type == chromeos::MOUNT_TYPE_INVALID) {
+ error_ = "Invalid mount type";
+ SendResponse(false);
+ return;
+ }
+
+ mount_lib->MountPath(source_file.data(), mount_type, options);
+#endif
+
+ SendResponse(true);
+}
+
+RemoveMountFunction::RemoveMountFunction() {
}
-UnmountVolumeFunction::~UnmountVolumeFunction() {
+RemoveMountFunction::~RemoveMountFunction() {
}
-bool UnmountVolumeFunction::RunImpl() {
+bool RemoveMountFunction::RunImpl() {
if (args_->GetSize() != 1) {
return false;
}
- std::string volume_device_path;
- if (!args_->GetString(0, &volume_device_path)) {
- NOTREACHED();
+ std::string mount_path;
+ if (!args_->GetString(0, &mount_path)) {
+ return false;
}
#ifdef OS_CHROMEOS
chromeos::CrosLibrary::Get()->GetMountLibrary()->UnmountPath(
- volume_device_path.c_str());
+ mount_path.c_str());
#endif
SendResponse(true);
return true;
}
+GetMountPointsFunction::GetMountPointsFunction() {
+}
+
+GetMountPointsFunction::~GetMountPointsFunction() {
+}
+
+bool GetMountPointsFunction::RunImpl() {
+ if (args_->GetSize())
+ return false;
+
+ base::ListValue *mounts = new base::ListValue();
+ result_.reset(mounts);
+
+ #ifdef OS_CHROMEOS
+ chromeos::MountLibrary *mount_lib =
+ chromeos::CrosLibrary::Get()->GetMountLibrary();
+ chromeos::MountLibrary::MountPointMap mount_points =
+ mount_lib->mount_points();
+
+ for (chromeos::MountLibrary::MountPointMap::const_iterator it =
+ mount_points.begin();
+ it != mount_points.end();
+ ++it) {
+ mounts->Append(MountPointToValue(profile_, it->second));
+ }
+#endif
+ SendResponse(true);
+ return true;
+}
+
GetVolumeMetadataFunction::GetVolumeMetadataFunction() {
}
@@ -1141,7 +1300,6 @@ bool GetVolumeMetadataFunction::RunImpl() {
volume_info->SetBoolean("hasMedia", volume->has_media());
volume_info->SetBoolean("isOnBootDevice", volume->on_boot_device());
- SendResponse(true);
return true;
}
#endif
@@ -1178,8 +1336,8 @@ bool FileDialogStringsFunction::RunImpl() {
SET_STRING(IDS_FILE_BROWSER, ROOT_DIRECTORY_LABEL);
SET_STRING(IDS_FILE_BROWSER, DOWNLOADS_DIRECTORY_LABEL);
- SET_STRING(IDS_FILE_BROWSER, DOWNLOADS_DIRECTORY_WARNING);
- SET_STRING(IDS_FILE_BROWSER, MEDIA_DIRECTORY_LABEL);
+ SET_STRING(IDS_FILE_BROWSER, ARCHIVE_DIRECTORY_LABEL);
+ SET_STRING(IDS_FILE_BROWSER, REMOVABLE_DIRECTORY_LABEL);
SET_STRING(IDS_FILE_BROWSER, NAME_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, SIZE_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, DATE_COLUMN_LABEL);
@@ -1201,6 +1359,10 @@ bool FileDialogStringsFunction::RunImpl() {
SET_STRING(IDS_FILE_BROWSER, VOLUME_LABEL);
SET_STRING(IDS_FILE_BROWSER, READ_ONLY);
+ SET_STRING(IDS_FILE_BROWSER, ARCHIVE_MOUNT_FAILED);
+ SET_STRING(IDS_FILE_BROWSER, MOUNT_ARCHIVE);
+ SET_STRING(IDS_FILE_BROWSER, UNMOUNT_ARCHIVE);
+
SET_STRING(IDS_FILE_BROWSER, CONFIRM_OVERWRITE_FILE);
SET_STRING(IDS_FILE_BROWSER, FILE_ALREADY_EXISTS);
SET_STRING(IDS_FILE_BROWSER, DIRECTORY_ALREADY_EXISTS);
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.h b/chrome/browser/extensions/extension_file_browser_private_api.h
index 065b9e2..69bd537 100644
--- a/chrome/browser/extensions/extension_file_browser_private_api.h
+++ b/chrome/browser/extensions/extension_file_browser_private_api.h
@@ -118,24 +118,24 @@ class ExecuteTasksFileBrowserFunction : public AsyncExtensionFunction {
};
// Parent class for the chromium extension APIs for the file dialog.
-class FileDialogFunction
+class FileBrowserFunction
: public AsyncExtensionFunction {
public:
- FileDialogFunction();
+ FileBrowserFunction();
protected:
typedef std::vector<GURL> UrlList;
typedef std::vector<FilePath> FilePathList;
- virtual ~FileDialogFunction();
+ virtual ~FileBrowserFunction();
// Convert virtual paths to local paths on the file thread.
void GetLocalPathsOnFileThread(const UrlList& file_urls,
- const std::string& internal_task_id);
+ void* context);
// Callback with converted local paths.
virtual void GetLocalPathsResponseOnUIThread(const FilePathList& files,
- const std::string& internal_task_id) {}
+ void* context) { NOTREACHED(); }
// Figure out the tab_id of the hosting tab.
int32 GetTabId() const;
@@ -143,7 +143,7 @@ class FileDialogFunction
// Select a single file. Closes the dialog window.
class SelectFileFunction
- : public FileDialogFunction {
+ : public FileBrowserFunction {
public:
SelectFileFunction() {}
@@ -153,9 +153,9 @@ class SelectFileFunction
// AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE;
- // FileDialogFunction overrides.
- virtual void GetLocalPathsResponseOnUIThread(
- const FilePathList& files, const std::string& internal_task_id) OVERRIDE;
+ // FileBrowserFunction overrides.
+ virtual void GetLocalPathsResponseOnUIThread(const FilePathList& files,
+ void* context) OVERRIDE;
private:
DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.selectFile");
@@ -163,7 +163,7 @@ class SelectFileFunction
// View multiple selected files. Window stays open.
class ViewFilesFunction
- : public FileDialogFunction {
+ : public FileBrowserFunction {
public:
ViewFilesFunction();
@@ -173,9 +173,9 @@ class ViewFilesFunction
// AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE;
- // FileDialogFunction overrides.
+ // FileBrowserFunction overrides.
virtual void GetLocalPathsResponseOnUIThread(
- const FilePathList& files, const std::string& internal_task_id) OVERRIDE;
+ const FilePathList& files, void* context) OVERRIDE;
private:
DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.viewFiles");
@@ -183,7 +183,7 @@ class ViewFilesFunction
// Select multiple files. Closes the dialog window.
class SelectFilesFunction
- : public FileDialogFunction {
+ : public FileBrowserFunction {
public:
SelectFilesFunction();
@@ -193,9 +193,9 @@ class SelectFilesFunction
// AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE;
- // FileDialogFunction overrides.
+ // FileBrowserFunction overrides.
virtual void GetLocalPathsResponseOnUIThread(
- const FilePathList& files, const std::string& internal_task_id) OVERRIDE;
+ const FilePathList& files, void* context) OVERRIDE;
private:
DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.selectFiles");
@@ -203,7 +203,7 @@ class SelectFilesFunction
// Cancel file selection Dialog. Closes the dialog window.
class CancelFileDialogFunction
- : public FileDialogFunction {
+ : public FileBrowserFunction {
public:
CancelFileDialogFunction() {}
@@ -217,19 +217,60 @@ class CancelFileDialogFunction
DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.cancelDialog");
};
-// Unmounts selected device. Expects volume's device path as an argument.
-class UnmountVolumeFunction
+// Mount a device or a file.
+class AddMountFunction
+ : public FileBrowserFunction {
+ public:
+ AddMountFunction();
+
+ protected:
+ virtual ~AddMountFunction();
+
+ virtual bool RunImpl() OVERRIDE;
+
+ // FileBrowserFunction overrides.
+ virtual void GetLocalPathsResponseOnUIThread(
+ const FilePathList& files, void* context) OVERRIDE;
+
+ private:
+ struct MountParamaters {
+ MountParamaters(const std::string& type,
+ const chromeos::MountPathOptions& options)
+ : mount_type(type), mount_options(options) {}
+ std::string mount_type;
+ chromeos::MountPathOptions mount_options;
+ };
+
+ DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.addMount");
+};
+
+// Unmounts selected device. Expects mount point path as an argument.
+class RemoveMountFunction
: public SyncExtensionFunction {
- public:
- UnmountVolumeFunction();
+ public:
+ RemoveMountFunction();
+
+ protected:
+ virtual ~RemoveMountFunction();
+
+ virtual bool RunImpl() OVERRIDE;
+
+ private:
+ DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.removeMount");
+};
+
+class GetMountPointsFunction
+ : public AsyncExtensionFunction {
+ public:
+ GetMountPointsFunction();
protected:
- virtual ~UnmountVolumeFunction();
+ virtual ~GetMountPointsFunction();
virtual bool RunImpl() OVERRIDE;
private:
- DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.unmountVolume");
+ DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.getMountPoints");
};
// Retrieves devices meta-data. Expects volume's device path as an argument.
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index e3ce123..640492f 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -347,7 +347,9 @@ void FactoryRegistry::ResetFunctions() {
RegisterFunction<RemoveFileWatchBrowserFunction>();
RegisterFunction<SelectFileFunction>();
RegisterFunction<SelectFilesFunction>();
- RegisterFunction<UnmountVolumeFunction>();
+ RegisterFunction<AddMountFunction>();
+ RegisterFunction<RemoveMountFunction>();
+ RegisterFunction<GetMountPointsFunction>();
RegisterFunction<ViewFilesFunction>();
// Mediaplayer
diff --git a/chrome/browser/extensions/file_manager_util.cc b/chrome/browser/extensions/file_manager_util.cc
index fb19e6c..76b5c43 100644
--- a/chrome/browser/extensions/file_manager_util.cc
+++ b/chrome/browser/extensions/file_manager_util.cc
@@ -27,6 +27,7 @@
// This is the "well known" url for the file manager extension from
// browser/resources/file_manager. In the future we may provide a way to swap
// out this file manager for an aftermarket part, but not yet.
+const char kFileBrowserExtensionUrl[] = FILEBROWSER_URL("");
const char kBaseFileBrowserUrl[] = FILEBROWSER_URL("main.html");
const char kMediaPlayerUrl[] = FILEBROWSER_URL("mediaplayer.html");
const char kMediaPlayerPlaylistUrl[] = FILEBROWSER_URL("playlist.html");
@@ -67,6 +68,11 @@ bool IsSupportedAVExtension(const char* ext) {
}
// static
+GURL FileManagerUtil::GetFileBrowserExtensionUrl() {
+ return GURL(kFileBrowserExtensionUrl);
+}
+
+// static
GURL FileManagerUtil::GetFileBrowserUrl() {
return GURL(kBaseFileBrowserUrl);
}
@@ -85,6 +91,21 @@ GURL FileManagerUtil::GetMediaPlayerPlaylistUrl() {
bool FileManagerUtil::ConvertFileToFileSystemUrl(
Profile* profile, const FilePath& full_file_path, const GURL& origin_url,
GURL* url) {
+ FilePath virtual_path;
+ if (!ConvertFileToRelativeFileSystemPath(profile, full_file_path,
+ &virtual_path)) {
+ return false;
+ }
+
+ GURL base_url = fileapi::GetFileSystemRootURI(origin_url,
+ fileapi::kFileSystemTypeExternal);
+ *url = GURL(base_url.spec() + virtual_path.value());
+ return true;
+}
+
+// static
+bool FileManagerUtil::ConvertFileToRelativeFileSystemPath(
+ Profile* profile, const FilePath& full_file_path, FilePath* virtual_path) {
fileapi::FileSystemPathManager* path_manager =
profile->GetFileSystemContext()->path_manager();
fileapi::ExternalFileSystemMountPointProvider* provider =
@@ -93,13 +114,9 @@ bool FileManagerUtil::ConvertFileToFileSystemUrl(
return false;
// Find if this file path is managed by the external provider.
- FilePath virtual_path;
- if (!provider->GetVirtualPath(full_file_path, &virtual_path))
+ if (!provider->GetVirtualPath(full_file_path, virtual_path))
return false;
- GURL base_url = fileapi::GetFileSystemRootURI(origin_url,
- fileapi::kFileSystemTypeExternal);
- *url = GURL(base_url.spec() + virtual_path.value());
return true;
}
diff --git a/chrome/browser/extensions/file_manager_util.h b/chrome/browser/extensions/file_manager_util.h
index 205b893..877eba8 100644
--- a/chrome/browser/extensions/file_manager_util.h
+++ b/chrome/browser/extensions/file_manager_util.h
@@ -16,6 +16,7 @@ class Profile;
class FileManagerUtil {
public:
// Gets base file browser url.
+ static GURL GetFileBrowserExtensionUrl();
static GURL GetFileBrowserUrl();
static GURL GetMediaPlayerUrl();
static GURL GetMediaPlayerPlaylistUrl();
@@ -24,6 +25,13 @@ class FileManagerUtil {
// if |full_file_path| is not managed by the external filesystem provider.
static bool ConvertFileToFileSystemUrl(Profile* profile,
const FilePath& full_file_path, const GURL& origin_url, GURL* url);
+
+ // Converts |full_file_path| into |relative_path| within the external provider
+ // in File API. Returns false if |full_file_path| is not managed by the
+ // external filesystem provider.
+ static bool ConvertFileToRelativeFileSystemPath(Profile* profile,
+ const FilePath& full_file_path, FilePath* relative_path);
+
// Gets base file browser url for.
static GURL GetFileBrowserUrlWithParams(
SelectFileDialog::Type type,
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 63e7bd5..4603d6b 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -515,9 +515,24 @@ void ProfileImpl::RegisterComponentExtensions() {
IDR_BOOKMARKS_MANIFEST));
#if defined(FILE_MANAGER_EXTENSION)
+#ifndef NDEBUG
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kFileManagerExtensionPath)) {
+ FilePath filemgr_extension_path =
+ command_line->GetSwitchValuePath(switches::kFileManagerExtensionPath);
+ component_extensions.push_back(std::make_pair(
+ filemgr_extension_path.value(),
+ IDR_FILEMANAGER_MANIFEST));
+ } else {
component_extensions.push_back(std::make_pair(
FILE_PATH_LITERAL("file_manager"),
IDR_FILEMANAGER_MANIFEST));
+ }
+#else
+ component_extensions.push_back(std::make_pair(
+ FILE_PATH_LITERAL("file_manager"),
+ IDR_FILEMANAGER_MANIFEST));
+#endif
#endif
#if defined(TOUCH_UI)
@@ -532,7 +547,6 @@ void ProfileImpl::RegisterComponentExtensions() {
IDR_MOBILE_MANIFEST));
#ifndef NDEBUG
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kAuthExtensionPath)) {
FilePath auth_extension_path =
command_line->GetSwitchValuePath(switches::kAuthExtensionPath);
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index bdff237..54bd3c8 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -38,6 +38,8 @@
<include name="IDR_FILE_MANAGER_PREVIEW_ICON" file="file_manager/images/icon_preview_16x16.png" type="BINDATA" />
<include name="IDR_FILE_MANAGER_MEDIA_PLAY_ICON" file="file_manager/images/icon_play_16x16.png" type="BINDATA" />
<include name="IDR_FILE_MANAGER_MEDIA_ENQUEUE_ICON" file="file_manager/images/icon_add_to_queue_16x16.png" type="BINDATA" />
+ <include name="IDR_FILE_MANAGER_ARCHIVE_MOUNT_ICON" file="file_manager/images/icon_mount_archive_16x16.png" type="BINDATA" />
+ <include name="IDR_FILE_MANAGER_ARCHIVE_UNMOUNT_ICON" file="file_manager/images/icon_unmount_archive_16x16.png" type="BINDATA" />
<include name="IDR_FILE_MANAGER_IMG_FILETYPE_AUDIO" file="file_manager/images/filetype_audio.png" type="BINDATA" />
<include name="IDR_FILE_MANAGER_IMG_FILETYPE_DOC" file="file_manager/images/filetype_doc.png" type="BINDATA" />
diff --git a/chrome/browser/resources/file_manager/images/icon_mount_archive_16x16.png b/chrome/browser/resources/file_manager/images/icon_mount_archive_16x16.png
new file mode 100644
index 0000000..c47e27f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/icon_mount_archive_16x16.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon_unmount_archive_16x16.png b/chrome/browser/resources/file_manager/images/icon_unmount_archive_16x16.png
new file mode 100644
index 0000000..51eddc5
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/icon_unmount_archive_16x16.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 42814da..c079ffe 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -105,6 +105,18 @@ function FileManager(dialogDom, rootEntries, params) {
this.addEventListener('selection-summarized',
this.onSelectionSummarized_.bind(this));
+ // The list of archives requested to mount. We will show contents once
+ // archive is mounted, but only for mounts from within this filebrowser tab.
+ this.mountRequests_ = [];
+ chrome.fileBrowserPrivate.onMountCompleted.addListener(
+ this.onMountCompleted_.bind(this));
+
+ var self = this;
+ // The list of active mount points to distinct them from other directories.
+ chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) {
+ self.mountPoints_ = mountPoints;
+ });
+
chrome.fileBrowserHandler.onExecute.addListener(
this.onFileTaskExecute_.bind(this));
@@ -144,10 +156,16 @@ FileManager.prototype = {
const RIGHT_TRIANGLE = '\u25b8';
/**
- * The DirectoryEntry.fullPath value of the directory containing external
- * storage volumes.
+ * The DirectoryEntry.fullPath value of the directory containing externally
+ * mounted removable storage volumes.
*/
- const MEDIA_DIRECTORY = '/media';
+ const REMOVABLE_DIRECTORY = 'removable';
+
+ /**
+ * The DirectoryEntry.fullPath value of the directory containing externally
+ * mounted archive file volumes.
+ */
+ const ARCHIVE_DIRECTORY = 'archive';
/**
* Mnemonics for the second parameter of the changeDirectory method.
@@ -640,8 +658,10 @@ FileManager.prototype = {
!this.renameInput_.currentEntry &&
// Not in root directory.
this.currentDirEntry_.fullPath != '/' &&
- // Not in media directory.
- this.currentDirEntry_.fullPath != MEDIA_DIRECTORY &&
+ // Not in media/archive directory.
+ this.currentDirEntry_.fullPath != ARCHIVE_DIRECTORY &&
+ // Not in media/removable directory.
+ this.currentDirEntry_.fullPath != REMOVABLE_DIRECTORY &&
// Only one file selected.
this.selection.totalCount == 1);
};
@@ -657,8 +677,10 @@ FileManager.prototype = {
!this.renameInput_.currentEntry &&
// Not in root directory.
this.currentDirEntry_.fullPath != '/' &&
- // Not in media directory.
- this.currentDirEntry_.fullPath != MEDIA_DIRECTORY);
+ // Not in media/removable directory.
+ this.currentDirEntry_.fullPath != REMOVABLE_DIRECTORY &&
+ // Not in media/archive directory.
+ this.currentDirEntry_.fullPath != ARCHIVE_DIRECTORY);
};
FileManager.prototype.setListType = function(type) {
@@ -1078,8 +1100,11 @@ FileManager.prototype = {
if (path == 'Downloads')
return str('DOWNLOADS_DIRECTORY_LABEL');
- if (path == 'media')
- return str('MEDIA_DIRECTORY_LABEL');
+ if (path == 'archive')
+ return str('ARCHIVE_DIRECTORY_LABEL');
+
+ if (path == 'removable')
+ return str('REMOVABLE_DIRECTORY_LABEL');
return path || str('ROOT_DIRECTORY_LABEL');
};
@@ -1144,8 +1169,8 @@ FileManager.prototype = {
var self = this;
cacheEntryDate(entry, function(entry) {
- if (self.currentDirEntry_.fullPath == MEDIA_DIRECTORY &&
- entry.cachedMtime_.getTime() == 0) {
+ if (self.currentDirEntry_.fullPath == ARCHIVE_DIRECTORY ||
+ self.currentDirEntry_.fullPath == REMOVABLE_DIRECTORY) {
// Mount points for FAT volumes have this time associated with them.
// We'd rather display nothing than this bogus date.
div.textContent = '---';
@@ -1248,8 +1273,12 @@ FileManager.prototype = {
};
if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) {
- chrome.fileBrowserPrivate.getFileTasks(selection.urls,
- this.onTasksFound_.bind(this));
+ // Since unmount task cannot be defined in terms of file patterns,
+ // we manually include it here, if all selected items are mount points.
+ chrome.fileBrowserPrivate.getFileTasks(
+ selection.urls,
+ this.onTasksFound_.bind(this,
+ this.shouldShowUnmount_(selection.urls)));
}
cacheNextFile();
@@ -1302,7 +1331,20 @@ FileManager.prototype = {
this[methodName].apply(this, data.arguments);
};
- FileManager.prototype.onTasksFound_ = function(tasksList) {
+ /**
+ * Callback called when tasks for selected files are determined.
+ * @param {boolean} unmount Whether unmount task should be included.
+ * @param {Array.<Task>} tasksList The tasks list.
+ */
+ FileManager.prototype.onTasksFound_ = function(unmount, tasksList) {
+ if (unmount) {
+ tasksList.push({
+ taskId: this.getExtensionId_() + '|unmount-archive',
+ iconUrl: '',
+ title: ''
+ });
+ }
+
this.taskButtons_.innerHTML = '';
for (var i = 0; i < tasksList.length; i++) {
var task = tasksList[i];
@@ -1329,6 +1371,14 @@ FileManager.prototype = {
task.iconUrl =
chrome.extension.getURL('images/icon_add_to_queue_16x16.png');
task.title = str('ENQUEUE');
+ } else if (task_parts[1] == 'mount-archive') {
+ task.iconUrl =
+ chrome.extension.getURL('images/icon_mount_archive_16x16.png');
+ task.title = str('MOUNT_ARCHIVE');
+ } else if (task_parts[1] == 'unmount-archive') {
+ task.iconUrl =
+ chrome.extension.getURL('images/icon_unmount_archive_16x16.png');
+ task.title = str('UNMOUNT_ARCHIVE');
}
}
@@ -1356,6 +1406,41 @@ FileManager.prototype = {
this.selection.urls);
};
+ /**
+ * Event handler called when some volume was mounted or unmouted.
+ */
+ FileManager.prototype.onMountCompleted_ = function(event) {
+ var self = this;
+ chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) {
+ self.mountPoints_ = mountPoints;
+ if (event.eventType == 'mount') {
+ for (var index = 0; index < self.mountRequests_.length; ++index) {
+ if (self.mountRequests_[index] == event.sourceUrl) {
+ self.mountRequests_.splice(index, 1);
+ if (event.status == 'success') {
+ self.changeDirectory(event.mountPath);
+ } else {
+ // Report mount error.
+ if (event.mountType == 'file') {
+ var fileName = event.sourceUrl.substr(
+ event.sourceUrl.lastIndexOf('/') + 1);
+ window.alert(strf('ARCHIVE_MOUNT_FAILED', fileName,
+ event.status));
+ }
+ }
+ return;
+ }
+ }
+ }
+ // TODO(dgozman): rescan directory, only if it contains mounted points,
+ // when mounts location will be decided.
+ this.rescanDirectory_();
+ });
+ };
+
+ /**
+ * Event handler called when some internal task should be executed.
+ */
FileManager.prototype.onFileTaskExecute_ = function(id, details) {
var urls = details.entries.map(function(entry) {
return entry.toURL();
@@ -1372,7 +1457,31 @@ FileManager.prototype = {
this.imageEditor_.getBuffer().load(urls[0]);
} else if (id == 'play' || id == 'enqueue') {
chrome.fileBrowserPrivate.viewFiles(urls, id);
+ } else if (id == 'mount-archive') {
+ for (var index = 0; index < urls.length; ++index) {
+ this.mountRequests_.push(urls[index]);
+ chrome.fileBrowserPrivate.addMount(urls[index], 'file', {});
+ }
+ } else if (id == 'unmount-archive') {
+ for (var index = 0; index < urls.length; ++index) {
+ chrome.fileBrowserPrivate.removeMount(urls[index]);
+ }
+ }
+ };
+
+ /**
+ * Determines whether unmount task should present for selected files.
+ */
+ FileManager.prototype.shouldShowUnmount_ = function(urls) {
+ for (var index = 0; index < urls.length; ++index) {
+ // Each url should be a mount point.
+ var path = urls[index];
+ if (!this.mountPoints_.hasOwnProperty(path) ||
+ this.mountPoints_[path].type != 'file') {
+ return false;
+ }
}
+ return true;
};
FileManager.prototype.onImageEditorSave = function(canvas) {
@@ -1836,7 +1945,8 @@ FileManager.prototype = {
this.selection.fileCount >= 1);
} else if (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) {
if (this.currentDirEntry_.fullPath == '/' ||
- this.currentDirEntry_.fullPath == MEDIA_DIRECTORY) {
+ this.currentDirEntry_.fullPath == ARCHIVE_DIRECTORY ||
+ this.currentDirEntry_.fullPath == REMOVABLE_DIRECTORY) {
// Nothing can be saved in to the root or media/ directories.
selectable = false;
} else {
@@ -1894,7 +2004,8 @@ FileManager.prototype = {
// New folder should never be enabled in the root or media/ directories.
this.newFolderButton_.disabled =
(this.currentDirEntry_.fullPath == '/' ||
- this.currentDirEntry_.fullPath == MEDIA_DIRECTORY);
+ this.currentDirEntry_.fullPath == ARCHIVE_DIRECTORY ||
+ this.currentDirEntry_.fullPath == REMOVABLE_DIRECTORY);
this.document_.title = this.currentDirEntry_.fullPath;
diff --git a/chrome/browser/resources/file_manager/js/main.js b/chrome/browser/resources/file_manager/js/main.js
index 7181285..1a278c9 100644
--- a/chrome/browser/resources/file_manager/js/main.js
+++ b/chrome/browser/resources/file_manager/js/main.js
@@ -15,7 +15,7 @@ var fileManager;
function init() {
var params;
- var rootPaths = ['Downloads', 'media'];
+ var rootPaths = ['Downloads', 'removable', 'archive'];
if (document.location.search) {
var json = decodeURIComponent(document.location.search.substr(1));
diff --git a/chrome/browser/resources/file_manager/js/mock_chrome.js b/chrome/browser/resources/file_manager/js/mock_chrome.js
index 82bc0c8..ded229c 100644
--- a/chrome/browser/resources/file_manager/js/mock_chrome.js
+++ b/chrome/browser/resources/file_manager/js/mock_chrome.js
@@ -58,6 +58,9 @@ chrome.fileBrowserPrivate = {
addListener: function(cb) { this.callbacks.push(cb) }
},
+ /**
+ * Returns common tasks for a given list of files.
+ */
getFileTasks: function(urlList, callback) {
if (urlList.length == 0)
return callback([]);
@@ -76,6 +79,11 @@ chrome.fileBrowserPrivate = {
regexp: /\.(jpe?g|png|cr2?|tiff)$/i,
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAOCAYAAAAmL5yKAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sEEBcOAw9XftIAAADFSURBVCjPrZKxCsIwEIa/FHFwsvYxROjSQXAoqLiIL+xgBtvZ91A6uOnQc2hT0zRqkR4c3P25+/PfJTCwLU6wEpgBWkDXuInDPSwF5r7mJIeNQFTnIiCeONpVdYlLoK9wEUhNg8+B9FDVaZcgCKAovjTXfvPJFwGZtKW60pt8bOGBzfLouemnFY/MAs8wDeEI4NzaybewBu4AysKVgrK0gfe5iB9vjdAUqQ/S1Y/R3IX9Zc1zxc7zxe2/0Iskt7AsG0hhx14W8XV43FgV4gAAAABJRU5ErkJggg==',
},
+ { taskId: 'mount-archive',
+ title: 'Mount',
+ regexp: /\.(zip)$/i,
+ iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAOCAYAAAAmL5yKAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sEEBcOAw9XftIAAADFSURBVCjPrZKxCsIwEIa/FHFwsvYxROjSQXAoqLiIL+xgBtvZ91A6uOnQc2hT0zRqkR4c3P25+/PfJTCwLU6wEpgBWkDXuInDPSwF5r7mJIeNQFTnIiCeONpVdYlLoK9wEUhNg8+B9FDVaZcgCKAovjTXfvPJFwGZtKW60pt8bOGBzfLouemnFY/MAs8wDeEI4NzaybewBu4AysKVgrK0gfe5iB9vjdAUqQ/S1Y/R3IX9Zc1zxc7zxe2/0Iskt7AsG0hhx14W8XV43FgV4gAAAABJRU5ErkJggg==',
+ },
];
// Copy all tasks, then remove the ones that don't match.
@@ -98,8 +106,72 @@ chrome.fileBrowserPrivate = {
callback(candidateTasks);
},
+ /**
+ * Executes a task.
+ */
executeTask: function(taskId, urlList) {
console.log('executing task: ' + taskId + ': ' + urlList.length + ' urls');
+ var parts = taskId.split('|');
+ taskId = parts[parts.length - 1];
+ function createEntry(url) {
+ return {
+ toURL: function() { return url; }
+ };
+ }
+ var details = {entries: urlList.map(createEntry)};
+ var listeners = chrome.fileBrowserHandler.onExecute.listeners_;
+ for (var listener, index = 0; listener = listeners[index]; ++index) {
+ listener(taskId, details);
+ }
+ },
+
+ /**
+ * Event fired on mount and unmount operations.
+ */
+ onDiskChanged: {
+ listeners_: [],
+ addListener: function(listener) {
+ chrome.fileBrowserPrivate.onDiskChanged.listeners_.push(listener);
+ }
+ },
+
+ addMount: function(source, type, options) {
+ var event = {
+ eventType: 'added',
+ volumeInfo: {
+ devicePath: source,
+ type: type,
+ mountPath: '/'
+ }
+ };
+ var listeners = chrome.fileBrowserPrivate.onDiskChanged.listeners_;
+ for (var listener, index = 0; listener = listeners[index]; ++index) {
+ listener(event);
+ }
+ },
+
+ getMountPoints: function() {
+ // This will work in harness.
+ var path = 'filesystem:file:///persistent/media';
+ var result = {};
+ result[path] = {mountPath: path, type: 'file'};
+ return result;
+ },
+
+ removeMount: function(mountPoint) {
+ console.log('unmounted: ' + mountPoint);
+ var event = {
+ eventType: 'removed',
+ volumeInfo: {
+ devicePath: '',
+ type: '',
+ mountPath: mountPoint
+ }
+ };
+ var listeners = chrome.fileBrowserPrivate.onDiskChanged.listeners_;
+ for (var listener, index = 0; listener = listeners[index]; ++index) {
+ listener(event);
+ }
},
/**
@@ -143,6 +215,9 @@ chrome.fileBrowserPrivate = {
VOLUME_LABEL: 'Volume Label',
READ_ONLY: 'Read Only',
+ MOUNT_ARCHIVE: 'Open archive',
+ UNMOUNT_ARCHIVE: 'Close archive',
+
CONFIRM_OVERWRITE_FILE: 'A file named "$1" already exists. Do you want to replace it?',
FILE_ALREADY_EXISTS: 'The file named "$1" already exists. Please choose a different name.',
DIRECTORY_ALREADY_EXISTS: 'The directory named "$1" already exists. Please choose a different name.',
@@ -203,3 +278,12 @@ chrome.test = {
console.log('chrome.test.sendMessage: ' + msg);
}
};
+
+chrome.fileBrowserHandler = {
+ onExecute: {
+ listeners_: [],
+ addListener: function(listener) {
+ chrome.fileBrowserHandler.onExecute.listeners_.push(listener);
+ }
+ }
+};
diff --git a/chrome/browser/resources/file_manager/manifest.json b/chrome/browser/resources/file_manager/manifest.json
index fcb79e5..572c1ee 100644
--- a/chrome/browser/resources/file_manager/manifest.json
+++ b/chrome/browser/resources/file_manager/manifest.json
@@ -85,6 +85,22 @@
"filesystem:*.mp3",
"filesystem:*.m4a"
]
+ },
+ {
+ "id": "mount-archive",
+ "default_title": "__MSG_MOUNT_ARCHIVE__",
+ "default_icon": "images/icon_mount_archive_16x16.png",
+ "file_filters": [
+ "filesystem:*.zip"
+ ]
+ },
+ {
+ "id": "unmount-archive",
+ "default_title": "__MSG_UNMOUNT_ARCHIVE__",
+ "default_icon": "images/icon_unmount_archive_16x16.png",
+ "file_filters": [
+ "filesystem:*.mounted_zip"
+ ]
}
],
"chrome_url_overrides": {
diff --git a/chrome/browser/ui/webui/chromeos/imageburner/webui_handler.h b/chrome/browser/ui/webui/chromeos/imageburner/webui_handler.h
index c75bb2b..dee9f72 100644
--- a/chrome/browser/ui/webui/chromeos/imageburner/webui_handler.h
+++ b/chrome/browser/ui/webui/chromeos/imageburner/webui_handler.h
@@ -95,6 +95,10 @@ class WebUIHandler
virtual void DeviceChanged(chromeos::MountLibraryEventType event,
const std::string& device_path) OVERRIDE {
}
+ virtual void MountCompleted(chromeos::MountLibrary::MountEvent event_type,
+ chromeos::MountError error_code,
+ const chromeos::MountLibrary::MountPointInfo& mount_info) OVERRIDE {
+ }
// chromeos::BurnLibrary::Observer interface.
virtual void BurnProgressUpdated(chromeos::BurnLibrary* object,
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 1011697..6ca4187 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1118,6 +1118,9 @@ const char kOobeSkipPostLogin[] = "oobe-skip-postlogin";
// Enables overriding the path for the default authentication extension.
const char kAuthExtensionPath[] = "auth-ext-path";
+
+// Enables overriding the path off file manager extension.
+const char kFileManagerExtensionPath[] = "filemgr-ext-path";
#endif
#endif
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 3fe3cfd..5b0b95a 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -309,6 +309,7 @@ extern const char kCompressSystemFeedback[];
#ifndef NDEBUG
extern const char kOobeSkipPostLogin[];
extern const char kAuthExtensionPath[];
+extern const char kFileManagerExtensionPath[];
#endif
#endif
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index d341192..c037325 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -5176,6 +5176,27 @@
}
},
{
+ "id": "MountPointInfo",
+ "type": "object",
+ "description": "Mounted point information.",
+ "properties": {
+ "mountPath": {
+ "type": "string",
+ "optional": true,
+ "description": "Disk volume mount point path. The value corresponds to its Entry.fullPath in File API."
+ },
+ "sourceUrl": {
+ "type": "string",
+ "description": "The path to the mounted devicem, url of the mounted archive file or network resource."
+ },
+ "mountType": {
+ "type": "string",
+ "enum": ["device", "file", "network"],
+ "description": "Type of the mount."
+ }
+ }
+ },
+ {
"id": "VolumeMetadata",
"type": "object",
"description": "Mounted disk volume metadata.",
@@ -5248,6 +5269,39 @@
}
},
{
+ "id": "MountCompletedEvent",
+ "type": "object",
+ "description": "Payload data for mount event.",
+ "properties": {
+ "eventType": {
+ "type": "string",
+ "enum": ["mount", "unmount"],
+ "description": "Is the event raised for mounting or unmounting."
+ },
+ "status": {
+ "type": "string",
+ "enum": ["success", "error_unknown", "error_internal",
+ "error_unknown_filesystem", "error_unsuported_filesystem",
+ "error_invalid_archive", "error_libcros_missing"],
+ "description": "Event type that tells listeners if mount was successfull or an error occurred. It also specifies the error."
+ },
+ "sourceUrl": {
+ "type": "string",
+ "description": "Path that has been mounted."
+ },
+ "mountPath": {
+ "type": "string",
+ "optional": true,
+ "description": "Path that sourcePath was mounted to."
+ },
+ "mountType": {
+ "type": "string",
+ "enum": ["device", "file", "network"],
+ "description": "Type of the mount."
+ }
+ }
+ },
+ {
"id": "FileWatchEvent",
"type": "object",
"description": "Payload data for disk mount / unmount event.",
@@ -5481,13 +5535,55 @@
]
},
{
- "name": "unmountVolume",
- "description": "Unmounts specified volume",
+ "name": "addMount",
+ "description": "Mount a resource or a file.",
"parameters": [
{
- "name": "devicePath",
+ "name": "source",
"type": "string",
- "description": "Device path of the volume."
+ "description": "Mount point source. For compressed files it is relative file path within external file system"
+ },
+ {
+ "name": "mountType",
+ "type": "string",
+ "enum": ["device", "file", "network"],
+ "description": "Mount point type. 'file' for compressed files"
+ },
+ {
+ "name": "options",
+ "type": "object",
+ "description": "Name/value pairs for source specific options",
+ "optional": "true"
+ }
+ ]
+ },
+ {
+ "name": "removeMount",
+ "description": "Unmounts a mounted resource.",
+ "parameters": [
+ {
+ "name": "mountPath",
+ "type": "string",
+ "description": "A path of the mount."
+ }
+ ]
+ },
+ {
+ "name": "getMountPoints",
+ "description": "Get the list of mount points.",
+ "parameters": [
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": "false",
+ "parameters": [
+ {
+ "name" : "mountPoints",
+ "type": "array",
+ "items": {"$ref": "MountPointInfo"},
+ "description": "The list of MountPointInfo representing mounted devices."
+ }
+ ]
}
]
}
@@ -5506,6 +5602,18 @@
]
},
{
+ "name": "onMountCompleted",
+ "type": "function",
+ "description": "Fired when mount event is detected.",
+ "parameters": [
+ {
+ "$ref": "MountCompletedEvent",
+ "name": "event",
+ "description": "MountCompleted event information."
+ }
+ ]
+ },
+ {
"name": "onFileChanged",
"type": "function",
"description": "Fired when watched file change event is detected.",
@@ -6385,7 +6493,7 @@
"title": {
"type": "string",
"optional": true,
- "description": "The title of the notification."
+ "description": "The title of the notification."
},
"bodyText": {
"type": "string",
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 741d2fd..98e31cb 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -77,6 +77,8 @@ var chrome = chrome || {};
throw new Error(message);
} else if (!schemas[i].optional) {
+ console.log(chromeHidden.JSON.stringify(args));
+ console.log(chromeHidden.JSON.stringify(schemas));
throw new Error("Parameter " + (i + 1) + " is required.");
}
}
diff --git a/chrome/test/data/extensions/api_test/webstore_private/common.js b/chrome/test/data/extensions/api_test/webstore_private/common.js
index 8972e67..933b032 100644
--- a/chrome/test/data/extensions/api_test/webstore_private/common.js
+++ b/chrome/test/data/extensions/api_test/webstore_private/common.js
@@ -24,6 +24,7 @@ function checkInstalled(callback) {
}
var cachedIcon = null;
+var img = null;
// This returns the base64-encoded content of the extension's image.
function getIconData(callback) {
@@ -34,8 +35,9 @@ function getIconData(callback) {
canvas.style.display = "none";
canvas.width = 128;
canvas.height = 128;
- var img = new Image();
+ img = new Image();
img.onload = function() {
+ console.log('img.onload called');
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var tmp = canvas.toDataURL();