summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-25 20:37:59 +0000
committerzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-25 20:37:59 +0000
commit55d9bed8de248d583bd5770a42c8520e1225162b (patch)
tree6be27d9ee263e9a475385120a933bcb29fe75a74
parente69b903ec57dc0f511598b03d4aae148a56e33bc (diff)
downloadchromium_src-55d9bed8de248d583bd5770a42c8520e1225162b.zip
chromium_src-55d9bed8de248d583bd5770a42c8520e1225162b.tar.gz
chromium_src-55d9bed8de248d583bd5770a42c8520e1225162b.tar.bz2
Wired local file system support for File API. The local file system provider currently exists for ChromeOS builds only.
This CL exposes new extension permission 'fileSystem' that controls access to individual local file system elements from 3rd party extensions. Another new permission 'fileBrowserPrivate' controls access to following API call that retrieves root DOMFileSystem instance for locally exposed folders:  chrome.fileBrowserPrivate.requestLocalFileSystem(callback) BUG=chromium-os:11983 TEST=ExtensionApiTest.LocalFileSystem Review URL: http://codereview.chromium.org/6519040 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79451 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_file_browser_private_api.cc98
-rw-r--r--chrome/browser/extensions/extension_file_browser_private_api.h36
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc4
-rw-r--r--chrome/browser/extensions/extension_local_filesystem_apitest.cc13
-rw-r--r--chrome/browser/extensions/extension_special_storage_policy.cc17
-rw-r--r--chrome/browser/extensions/extension_special_storage_policy.h2
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/extensions/api/extension_api.json24
-rw-r--r--chrome/common/extensions/extension.cc12
-rw-r--r--chrome/common/extensions/extension.h2
-rw-r--r--chrome/common/extensions/extension_unittest.cc5
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc17
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js12
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js2
-rw-r--r--chrome/test/data/extensions/api_test/local_filesystem/background.html63
-rw-r--r--chrome/test/data/extensions/api_test/local_filesystem/manifest.json14
-rw-r--r--chrome/test/data/extensions/api_test/local_filesystem/tab.html80
-rw-r--r--webkit/chromeos/fileapi/cros_mount_point_provider.cc124
-rw-r--r--webkit/chromeos/fileapi/cros_mount_point_provider.h59
-rw-r--r--webkit/database/database_tracker_unittest.cc4
-rw-r--r--webkit/fileapi/file_system_context.cc3
-rw-r--r--webkit/fileapi/file_system_context.h4
-rw-r--r--webkit/fileapi/file_system_context_unittest.cc5
-rw-r--r--webkit/fileapi/file_system_dir_url_request_job_unittest.cc3
-rw-r--r--webkit/fileapi/file_system_mount_point_provider.h1
-rw-r--r--webkit/fileapi/file_system_operation.cc5
-rw-r--r--webkit/fileapi/file_system_path_manager.cc49
-rw-r--r--webkit/fileapi/file_system_path_manager.h21
-rw-r--r--webkit/fileapi/file_system_path_manager_unittest.cc24
-rw-r--r--webkit/fileapi/file_system_types.h1
-rw-r--r--webkit/fileapi/file_system_url_request_job_unittest.cc2
-rw-r--r--webkit/fileapi/file_system_util.cc7
-rw-r--r--webkit/fileapi/local_file_system_file_util.cc2
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.cc3
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.h1
-rw-r--r--webkit/fileapi/webkit_fileapi.gypi5
-rw-r--r--webkit/quota/special_storage_policy.h3
38 files changed, 704 insertions, 26 deletions
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.cc b/chrome/browser/extensions/extension_file_browser_private_api.cc
new file mode 100644
index 0000000..6acfde6
--- /dev/null
+++ b/chrome/browser/extensions/extension_file_browser_private_api.cc
@@ -0,0 +1,98 @@
+// Copyright (c) 2011 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/extensions/extension_file_browser_private_api.h"
+
+#include "base/json/json_writer.h"
+#include "base/task.h"
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/extension.h"
+#include "content/browser/browser_thread.h"
+#include "webkit/fileapi/file_system_operation.h"
+#include "webkit/fileapi/file_system_types.h"
+
+class LocalFileSystemCallbackDispatcher
+ : public fileapi::FileSystemCallbackDispatcher {
+ public:
+ explicit LocalFileSystemCallbackDispatcher(
+ RequestLocalFileSystemFunction* function) : function_(function) {
+ DCHECK(function_);
+ }
+ // fileapi::FileSystemCallbackDispatcher overrides.
+ virtual void DidSucceed() OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void DidReadMetadata(const base::PlatformFileInfo& info) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void DidReadDirectory(
+ const std::vector<base::FileUtilProxy::Entry>& entries,
+ bool has_more) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void DidWrite(int64 bytes, bool complete) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void DidOpenFileSystem(const std::string& name,
+ const FilePath& path) OVERRIDE {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(function_,
+ &RequestLocalFileSystemFunction::RespondSuccessOnUIThread,
+ name,
+ path));
+ }
+ virtual void DidFail(base::PlatformFileError error_code) OVERRIDE {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(function_,
+ &RequestLocalFileSystemFunction::RespondFailedOnUIThread,
+ error_code));
+ }
+ private:
+ RequestLocalFileSystemFunction* function_;
+ DISALLOW_COPY_AND_ASSIGN(LocalFileSystemCallbackDispatcher);
+};
+
+RequestLocalFileSystemFunction::RequestLocalFileSystemFunction() {
+}
+
+RequestLocalFileSystemFunction::~RequestLocalFileSystemFunction() {
+}
+
+bool RequestLocalFileSystemFunction::RunImpl() {
+ fileapi::FileSystemOperation* operation =
+ new fileapi::FileSystemOperation(
+ new LocalFileSystemCallbackDispatcher(this),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
+ profile()->GetFileSystemContext(),
+ NULL);
+ GURL origin_url = source_url().GetOrigin();
+ operation->OpenFileSystem(origin_url, fileapi::kFileSystemTypeLocal,
+ false); // create
+ // Will finish asynchronously.
+ return true;
+}
+
+void RequestLocalFileSystemFunction::RespondSuccessOnUIThread(
+ const std::string& name, const FilePath& path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ result_.reset(new DictionaryValue());
+ DictionaryValue* dict = reinterpret_cast<DictionaryValue*>(result_.get());
+ dict->SetString("name", name);
+ dict->SetString("path", path.value());
+ dict->SetInteger("error", base::PLATFORM_FILE_OK);
+ SendResponse(true);
+}
+
+void RequestLocalFileSystemFunction::RespondFailedOnUIThread(
+ base::PlatformFileError error_code) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ result_.reset(new DictionaryValue());
+ DictionaryValue* dict = reinterpret_cast<DictionaryValue*>(result_.get());
+ dict->SetInteger("error", static_cast<int>(error_code));
+ SendResponse(true);
+}
+
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.h b/chrome/browser/extensions/extension_file_browser_private_api.h
new file mode 100644
index 0000000..aadcb3c
--- /dev/null
+++ b/chrome/browser/extensions/extension_file_browser_private_api.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FILE_BROWSER_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FILE_BROWSER_PRIVATE_API_H_
+#pragma once
+
+#include <string>
+
+#include "base/file_path.h"
+#include "chrome/browser/extensions/extension_function.h"
+#include "webkit/fileapi/file_system_callback_dispatcher.h"
+
+// Implements the Chrome Extension local File API.
+class RequestLocalFileSystemFunction
+ : public AsyncExtensionFunction {
+ public:
+ RequestLocalFileSystemFunction();
+
+ protected:
+ virtual ~RequestLocalFileSystemFunction();
+
+ // AsyncExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ private:
+ friend class LocalFileSystemCallbackDispatcher;
+ void RespondSuccessOnUIThread(const std::string& name,
+ const FilePath& path);
+ void RespondFailedOnUIThread(base::PlatformFileError error_code);
+
+ DECLARE_EXTENSION_FUNCTION_NAME("fileBrowserPrivate.requestLocalFileSystem");
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_FILE_BROWSER_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index b295d69..38f57c6 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -22,6 +22,7 @@
#include "chrome/browser/extensions/extension_context_menu_api.h"
#include "chrome/browser/extensions/extension_cookies_api.h"
#include "chrome/browser/extensions/extension_debugger_api.h"
+#include "chrome/browser/extensions/extension_file_browser_private_api.h"
#include "chrome/browser/extensions/extension_function.h"
#include "chrome/browser/extensions/extension_history_api.h"
#include "chrome/browser/extensions/extension_i18n_api.h"
@@ -201,6 +202,9 @@ void FactoryRegistry::ResetFunctions() {
// Processes.
RegisterFunction<GetProcessIdForTabFunction>();
+ // Local filesystem.
+ RegisterFunction<RequestLocalFileSystemFunction>();
+
// Metrics.
RegisterFunction<MetricsGetEnabledFunction>();
RegisterFunction<MetricsSetEnabledFunction>();
diff --git a/chrome/browser/extensions/extension_local_filesystem_apitest.cc b/chrome/browser/extensions/extension_local_filesystem_apitest.cc
new file mode 100644
index 0000000..003e56a
--- /dev/null
+++ b/chrome/browser/extensions/extension_local_filesystem_apitest.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2010 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/extensions/extension_apitest.h"
+
+#if defined(OS_CHROMEOS)
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, LocalFileSystem) {
+ ASSERT_TRUE(RunComponentExtensionTest("local_filesystem")) << message_;
+}
+
+#endif
diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc
index a67617d..b1a9825 100644
--- a/chrome/browser/extensions/extension_special_storage_policy.cc
+++ b/chrome/browser/extensions/extension_special_storage_policy.cc
@@ -24,11 +24,18 @@ bool ExtensionSpecialStoragePolicy::IsStorageUnlimited(const GURL& origin) {
return unlimited_extensions_.Contains(origin);
}
+bool ExtensionSpecialStoragePolicy::IsLocalFileSystemAccessAllowed(
+ const GURL& origin) {
+ base::AutoLock locker(lock_);
+ return local_filesystem_extensions_.Contains(origin);
+}
+
void ExtensionSpecialStoragePolicy::GrantRightsForExtension(
const Extension* extension) {
DCHECK(extension);
if (!extension->is_hosted_app() &&
- !extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) {
+ !extension->HasApiPermission(Extension::kUnlimitedStoragePermission) &&
+ !extension->HasApiPermission(Extension::kFileSystemPermission)) {
return;
}
base::AutoLock locker(lock_);
@@ -36,13 +43,16 @@ void ExtensionSpecialStoragePolicy::GrantRightsForExtension(
protected_apps_.Add(extension);
if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission))
unlimited_extensions_.Add(extension);
+ if (extension->HasApiPermission(Extension::kFileSystemPermission))
+ local_filesystem_extensions_.Add(extension);
}
void ExtensionSpecialStoragePolicy::RevokeRightsForExtension(
const Extension* extension) {
DCHECK(extension);
if (!extension->is_hosted_app() &&
- !extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) {
+ !extension->HasApiPermission(Extension::kUnlimitedStoragePermission) &&
+ !extension->HasApiPermission(Extension::kFileSystemPermission)) {
return;
}
base::AutoLock locker(lock_);
@@ -50,12 +60,15 @@ void ExtensionSpecialStoragePolicy::RevokeRightsForExtension(
protected_apps_.Remove(extension);
if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission))
unlimited_extensions_.Remove(extension);
+ if (extension->HasApiPermission(Extension::kFileSystemPermission))
+ local_filesystem_extensions_.Remove(extension);
}
void ExtensionSpecialStoragePolicy::RevokeRightsForAllExtensions() {
base::AutoLock locker(lock_);
protected_apps_.Clear();
unlimited_extensions_.Clear();
+ local_filesystem_extensions_.Clear();
}
//-----------------------------------------------------------------------------
diff --git a/chrome/browser/extensions/extension_special_storage_policy.h b/chrome/browser/extensions/extension_special_storage_policy.h
index ead9b60..88697ee 100644
--- a/chrome/browser/extensions/extension_special_storage_policy.h
+++ b/chrome/browser/extensions/extension_special_storage_policy.h
@@ -26,6 +26,7 @@ class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy {
// data remover. These methods are safe to call on any thread.
virtual bool IsStorageProtected(const GURL& origin);
virtual bool IsStorageUnlimited(const GURL& origin);
+ virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin);
// Methods used by the ExtensionService to populate this class.
void GrantRightsForExtension(const Extension* extension);
@@ -55,6 +56,7 @@ class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy {
base::Lock lock_; // Synchronize all access to the collections.
SpecialCollection protected_apps_;
SpecialCollection unlimited_extensions_;
+ SpecialCollection local_filesystem_extensions_;
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SPECIAL_STORAGE_POLICY_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 8c36136..f4e1fd2a 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -906,6 +906,8 @@
'browser/extensions/extension_event_router.h',
'browser/extensions/extension_event_router_forwarder.cc',
'browser/extensions/extension_event_router_forwarder.h',
+ 'browser/extensions/extension_file_browser_private_api.cc',
+ 'browser/extensions/extension_file_browser_private_api.h',
'browser/extensions/extension_function.cc',
'browser/extensions/extension_function.h',
'browser/extensions/extension_function_dispatcher.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 141d36b..a8ca9d1 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2231,6 +2231,7 @@
'browser/extensions/extension_input_apitest.cc',
'browser/extensions/extension_install_ui_browsertest.cc',
'browser/extensions/extension_javascript_url_apitest.cc',
+ 'browser/extensions/extension_local_filesystem_apitest.cc',
'browser/extensions/extension_management_api_browsertest.cc',
'browser/extensions/extension_management_apitest.cc',
'browser/extensions/extension_management_browsertest.cc',
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 028a76ec..64520fa 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -4480,6 +4480,30 @@
},
{
+ "namespace":"fileBrowserPrivate",
+ "nodoc": "true",
+ "functions": [
+ {
+ "name": "requestLocalFileSystem",
+ "description": "Requests access to local file system",
+ "parameters": [
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": "false",
+ "parameters": [
+ {
+ "type": "object",
+ "isInstanceOf": "DOMFileSystem"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+
+ {
"namespace":"webstorePrivate",
"nodoc": "true",
"functions": [
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 62c5d2f..e9c808d 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -208,6 +208,8 @@ const char Extension::kCookiePermission[] = "cookies";
const char Extension::kChromeosInfoPrivatePermissions[] = "chromeosInfoPrivate";
const char Extension::kDebuggerPermission[] = "debugger";
const char Extension::kExperimentalPermission[] = "experimental";
+const char Extension::kFileSystemPermission[] = "fileSystem";
+const char Extension::kFileBrowserPrivatePermission[] = "fileBrowserPrivate";
const char Extension::kGeolocationPermission[] = "geolocation";
const char Extension::kHistoryPermission[] = "history";
const char Extension::kIdlePermission[] = "idle";
@@ -224,11 +226,14 @@ const char Extension::kWebstorePrivatePermission[] = "webstorePrivate";
const Extension::Permission Extension::kPermissions[] = {
{ kBackgroundPermission, 0 },
{ kBookmarkPermission, IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS },
+ { kChromeosInfoPrivatePermissions, 0},
{ kContentSettingsPermission, 0 },
{ kContextMenusPermission, 0 },
{ kCookiePermission, 0 },
{ kDebuggerPermission, IDS_EXTENSION_PROMPT_WARNING_DEBUGGER },
{ kExperimentalPermission, 0 },
+ { kFileSystemPermission, 0 },
+ { kFileBrowserPrivatePermission, 0 },
{ kGeolocationPermission, IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION },
{ kIdlePermission, 0 },
{ kHistoryPermission, IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY },
@@ -238,7 +243,6 @@ const Extension::Permission Extension::kPermissions[] = {
{ kTabPermission, IDS_EXTENSION_PROMPT_WARNING_TABS },
{ kUnlimitedStoragePermission, 0 },
{ kWebstorePrivatePermission, 0 },
- { kChromeosInfoPrivatePermissions, 0}
};
const size_t Extension::kNumPermissions =
arraysize(Extension::kPermissions);
@@ -1900,10 +1904,12 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
- // Only COMPONENT extensions can use the webstorePrivate APIs.
+ // Only COMPONENT extensions can use the webstorePrivate and
+ // fileBrowserPrivate APIs.
// TODO(asargent) - We want a more general purpose mechanism for this,
// and better error messages. (http://crbug.com/54013)
- if (permission_str == kWebstorePrivatePermission &&
+ if ((permission_str == kWebstorePrivatePermission ||
+ permission_str == kFileBrowserPrivatePermission) &&
location_ != Extension::COMPONENT) {
continue;
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index b03ea18..0b65d56 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -179,6 +179,8 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
static const char kChromeosInfoPrivatePermissions[];
static const char kDebuggerPermission[];
static const char kExperimentalPermission[];
+ static const char kFileSystemPermission[];
+ static const char kFileBrowserPrivatePermission[];
static const char kGeolocationPermission[];
static const char kHistoryPermission[];
static const char kIdlePermission[];
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index cb2266d..f1dc9ed 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -933,12 +933,17 @@ TEST(ExtensionTest, PermissionMessages) {
// The proxy permission is warned as part of host permission checks.
skip.insert(Extension::kProxyPermission);
+ // This permission requires explicit user action (context menu handler)
+ // so we won't prompt for it for now.
+ skip.insert(Extension::kFileSystemPermission);
+
// If you've turned on the experimental command-line flag, we don't need
// to warn you further.
skip.insert(Extension::kExperimentalPermission);
// These are only usable by component extensions.
skip.insert(Extension::kWebstorePrivatePermission);
+ skip.insert(Extension::kFileBrowserPrivatePermission);
skip.insert(Extension::kChromeosInfoPrivatePermissions);
for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index 1a1d7e5..bca44b1 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -234,6 +234,8 @@ class ExtensionImpl : public ExtensionBase {
return v8::FunctionTemplate::New(IsIncognitoProcess);
} else if (name->Equals(v8::String::New("GetUniqueSubEventName"))) {
return v8::FunctionTemplate::New(GetUniqueSubEventName);
+ } else if (name->Equals(v8::String::New("GetLocalFileSystem"))) {
+ return v8::FunctionTemplate::New(GetLocalFileSystem);
}
return ExtensionBase::GetNativeFunction(name);
@@ -301,6 +303,21 @@ class ExtensionImpl : public ExtensionBase {
return v8::String::New(unique_event_name.c_str());
}
+ // Attach an event name to an object.
+ static v8::Handle<v8::Value> GetLocalFileSystem(
+ const v8::Arguments& args) {
+ DCHECK(args.Length() == 2);
+ DCHECK(args[0]->IsString());
+ DCHECK(args[1]->IsString());
+ std::string name(*v8::String::Utf8Value(args[0]));
+ std::string path(*v8::String::Utf8Value(args[1]));
+
+ WebFrame* webframe = WebFrame::frameForCurrentContext();
+ return webframe->createFileSystem(fileapi::kFileSystemTypeLocal,
+ WebKit::WebString::fromUTF8(name.c_str()),
+ WebKit::WebString::fromUTF8(path.c_str()));
+ }
+
// Creates a new messaging channel to the tab with the given ID.
static v8::Handle<v8::Value> OpenChannelToTab(const v8::Arguments& args) {
// Get the current RenderView so that we can send a routed IPC message from
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 6565f6f..d8c2648 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -19,6 +19,7 @@ var chrome = chrome || {};
native function IsExtensionProcess();
native function IsIncognitoProcess();
native function GetUniqueSubEventName(eventName);
+ native function GetLocalFileSystem(name, path);
var chromeHidden = GetChromeHidden();
@@ -658,6 +659,17 @@ var chrome = chrome || {};
});
};
+ apiFunctions["fileBrowserPrivate.requestLocalFileSystem"].customCallback =
+ function(name, request, response) {
+ var resp = response ? [chromeHidden.JSON.parse(response)] : [];
+ var fs = null;
+ if (!resp[0].error)
+ fs = GetLocalFileSystem(resp[0].name, resp[0].path);
+ if (request.callback)
+ request.callback(fs);
+ request.callback = null;
+ };
+
apiFunctions["extension.getViews"].handleRequest = function(properties) {
var windowId = -1;
var type = "ALL";
diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js
index afcd00d..aac3db9 100644
--- a/chrome/renderer/resources/renderer_extension_bindings.js
+++ b/chrome/renderer/resources/renderer_extension_bindings.js
@@ -318,6 +318,8 @@ var chrome = chrome || {};
"experimental.webRequest",
"history",
"idle",
+ "fileBrowserPrivate",
+ "fileSystem",
"management",
"omnibox",
"pageAction",
diff --git a/chrome/test/data/extensions/api_test/local_filesystem/background.html b/chrome/test/data/extensions/api_test/local_filesystem/background.html
new file mode 100644
index 0000000..68d0dec
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/local_filesystem/background.html
@@ -0,0 +1,63 @@
+<script>
+ var fileSystem = null;
+ var testDirName = "tmp/test_dir_" + Math.floor(Math.random()*10000);
+ var testFileName = "test_file_" + Math.floor(Math.random()*10000);
+
+ // Get local FS, create dir with a file in it.
+ console.log("Requesting local file system...");
+ chrome.fileBrowserPrivate.requestLocalFileSystem(getFileSystem);
+
+ function getFileSystem(fs, error) {
+ if (!fs) {
+ errorCallback(error);
+ return;
+ }
+ fileSystem = fs;
+ console.log("DONE requesting local filesystem: " + fileSystem.name);
+ console.log("Creating directory : " + testDirName);
+ fileSystem.root.getDirectory(testDirName, {create:true},
+ directoryCallback, errorCallback);
+ }
+
+ function directoryCallback(directory) {
+ console.log("DONE creating directory: " + directory.fullPath);
+ directory.getFile(testFileName, {create:true}, fileCallback, errorCallback);
+ }
+
+ function fileCallback(file) {
+ console.log("DONE creating file: " + file.fullPath);
+
+ // See if we can access this filesystem and its elements in the tab.
+ console.log("Opening tab...");
+ chrome.tabs.create({
+ url: "tab.html#" + escape(testDirName + "/" + testFileName)
+ });
+ }
+
+function errorCallback(e) {
+ var msg = '';
+ switch (e.code) {
+ case FileError.QUOTA_EXCEEDED_ERR:
+ msg = 'QUOTA_EXCEEDED_ERR';
+ break;
+ case FileError.NOT_FOUND_ERR:
+ msg = 'NOT_FOUND_ERR';
+ break;
+ case FileError.SECURITY_ERR:
+ msg = 'SECURITY_ERR';
+ break;
+ case FileError.INVALID_MODIFICATION_ERR:
+ msg = 'INVALID_MODIFICATION_ERR';
+ break;
+ case FileError.INVALID_STATE_ERR:
+ msg = 'INVALID_STATE_ERR';
+ break;
+ default:
+ msg = 'Unknown Error';
+ break;
+ };
+ chrome.test.fail("Got unexpected error: " + msg);
+ console.log('Error: ' + msg);
+ alert('Error: ' + msg);
+}
+</script>
diff --git a/chrome/test/data/extensions/api_test/local_filesystem/manifest.json b/chrome/test/data/extensions/api_test/local_filesystem/manifest.json
new file mode 100644
index 0000000..367a97a
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/local_filesystem/manifest.json
@@ -0,0 +1,14 @@
+{
+ "key": "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDJ5+2VmV02HP3jkMhxbp2yuyzf4K4JsffgCf8zsPljLVV2A+JXGj0TbvzvDP3RDCKC5qPMprQkoYlKVW2b6H0kQ8dNmZsjxMqEz/ZDx4Z6/VvbMaz8pP+dENs5Io5XlG5Op2nsJF+y+LqbX6qbff9D/s4fTWyqKillpJN+48qs0wIBIw==",
+ "name": "chromeos.local filesystem",
+ "version": "0.1",
+ "description": "Local filesystem access sanity test",
+ "background_page": "background.html",
+ "permissions": [
+ "tabs",
+ "unlimitedStorage",
+ "fileSystem",
+ "fileBrowserPrivate"
+ ]
+}
+
diff --git a/chrome/test/data/extensions/api_test/local_filesystem/tab.html b/chrome/test/data/extensions/api_test/local_filesystem/tab.html
new file mode 100644
index 0000000..0caad48
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/local_filesystem/tab.html
@@ -0,0 +1,80 @@
+<script>
+var fileSystem = null;
+var testDirName = null;
+var testFileName = null;
+
+function errorCallback(e) {
+ var msg = '';
+ switch (e.code) {
+ case FileError.QUOTA_EXCEEDED_ERR:
+ msg = 'QUOTA_EXCEEDED_ERR';
+ break;
+ case FileError.NOT_FOUND_ERR:
+ msg = 'NOT_FOUND_ERR';
+ break;
+ case FileError.SECURITY_ERR:
+ msg = 'SECURITY_ERR';
+ break;
+ case FileError.INVALID_MODIFICATION_ERR:
+ msg = 'INVALID_MODIFICATION_ERR';
+ break;
+ case FileError.INVALID_STATE_ERR:
+ msg = 'INVALID_STATE_ERR';
+ break;
+ default:
+ msg = 'Unknown Error';
+ break;
+ };
+ chrome.test.fail("Got unexpected error: " + msg);
+ console.log('Error: ' + msg);
+ alert('Error: ' + msg);
+}
+
+function successCallback(entry) {
+ chrome.test.succeed();
+}
+
+function successEntryCallback(entry) {
+ console.log("Deleting dir : " + testDirName);
+ fileSystem.root.getDirectory(testDirName, {create:false},
+ function(directory) {
+ // Do clean-up. (Assume the tab won't be reloaded in testing.)
+ directory.removeRecursively(successCallback, errorCallback);
+ }, errorCallback);
+}
+
+chrome.test.runTests([function tab() {
+ // Get dir, file name.
+ var loc = window.location.href;
+ console.log("Opening tab " + loc);
+ if (loc.indexOf("#") == -1 ) {
+ chrome.test.fail("Missing params");
+ return;
+ }
+ loc = unescape(loc.substr(loc.indexOf("#") + 1));
+ if (loc.lastIndexOf("/") == -1 ) {
+ chrome.test.fail("Bad params");
+ return;
+ }
+ testDirName = loc.substr(0, loc.lastIndexOf("/"));
+ testFileName = loc.substr(loc.lastIndexOf("/") + 1);
+
+ console.log("Requesting local file system...");
+ chrome.fileBrowserPrivate.requestLocalFileSystem(function(fs, error) {
+ if (!fs) {
+ errorCallback(error);
+ return;
+ }
+ fileSystem = fs;
+ console.log("DONE requesting filesystem: " + fileSystem.name);
+ // Read directory content.
+ console.log("Opening file : " + testDirName+'/'+testFileName);
+ fileSystem.root.getDirectory(testDirName, {create: false},
+ function(dirEntry) {
+ console.log('DONE opening directory: ' + dirEntry.fullPath);
+ fileSystem.root.getFile(testDirName+'/'+testFileName, {create:false},
+ successEntryCallback, errorCallback);
+ }, errorCallback);
+ });
+}]);
+</script>
diff --git a/webkit/chromeos/fileapi/cros_mount_point_provider.cc b/webkit/chromeos/fileapi/cros_mount_point_provider.cc
new file mode 100644
index 0000000..1579c36
--- /dev/null
+++ b/webkit/chromeos/fileapi/cros_mount_point_provider.cc
@@ -0,0 +1,124 @@
+ // Copyright (c) 2011 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 "webkit/chromeos/fileapi/cros_mount_point_provider.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/scoped_callback_factory.h"
+#include "base/scoped_ptr.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/glue/webkit_glue.h"
+
+namespace chromeos {
+
+const char CrosMountPointProvider::kLocalName[] = "Local";
+const char CrosMountPointProvider::kLocalDirName[] = "/local/";
+
+typedef struct {
+ const char* local_root_path;
+ const char* web_root_path;
+} FixedExposedPaths;
+
+// Top level file system elements exposed in FileAPI in ChromeOS:
+FixedExposedPaths fixed_exposed_paths[] = {
+ {"/home/chronos/user/", "Downloads"},
+ {"/", "media"},
+ {"/", "tmp"},
+};
+
+CrosMountPointProvider::CrosMountPointProvider(
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy)
+ : local_dir_name_(kLocalName),
+ special_storage_policy_(special_storage_policy) {
+
+ // TODO(zelidrag): There's got to be a better way to generate UUID.
+ srand(time(NULL));
+ std::string virtual_root;
+ virtual_root.append(base::StringPrintf("%hx%hx-%hx-%hx-%hx-%hx%hx%hx",
+ static_cast<unsigned short>(rand()), static_cast<unsigned short>(rand()),
+ static_cast<unsigned short>(rand()),
+ static_cast<unsigned short>(rand()),
+ static_cast<unsigned short>(rand()),
+ static_cast<unsigned short>(rand()), static_cast<unsigned short>(rand()),
+ static_cast<unsigned short>(rand())));
+
+ // Create virtual root node.
+ virtual_root_path_ = FilePath(virtual_root);
+ base_path_ = virtual_root_path_.Append(local_dir_name_);
+
+ for (size_t i = 0; i < arraysize(fixed_exposed_paths); i++) {
+ mount_point_map_.insert(std::pair<std::string, std::string>(
+ std::string(fixed_exposed_paths[i].web_root_path),
+ std::string(fixed_exposed_paths[i].local_root_path)));
+ }
+}
+
+CrosMountPointProvider::~CrosMountPointProvider() {
+}
+
+// TODO(zelidrag) share with SandboxMountPointProvider impl.
+std::string GetOriginIdentifierFromURL(
+ const GURL& url) {
+ WebKit::WebSecurityOrigin web_security_origin =
+ WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
+ return web_security_origin.databaseIdentifier().utf8();
+}
+
+void CrosMountPointProvider::GetFileSystemRootPath(
+ const GURL& origin_url,
+ fileapi::FileSystemType type,
+ bool create,
+ fileapi::FileSystemPathManager::GetRootPathCallback* callback_ptr) {
+ DCHECK(type == fileapi::kFileSystemTypeLocal);
+
+ std::string name(GetOriginIdentifierFromURL(origin_url));
+ name += ':';
+ name += CrosMountPointProvider::kLocalName;
+
+ FilePath root_path = FilePath(CrosMountPointProvider::kLocalDirName);
+ callback_ptr->Run(!root_path.empty(), root_path, name);
+}
+
+// Like GetFileSystemRootPath, but synchronous, and can be called only while
+// running on the file thread.
+FilePath CrosMountPointProvider::GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url,
+ fileapi::FileSystemType type,
+ const FilePath& virtual_path,
+ bool create) {
+ DCHECK(type == fileapi::kFileSystemTypeLocal);
+
+ std::vector<FilePath::StringType> components;
+ virtual_path.GetComponents(&components);
+ if (components.size() < 1) {
+ return FilePath();
+ }
+
+ // Check if this root directory is exposed by this provider.
+ MountPointMap::iterator iter = mount_point_map_.find(components[0]);
+ if (iter == mount_point_map_.end()) {
+ return FilePath();
+ }
+
+ return FilePath(iter->second);
+}
+
+// TODO(zelidrag): Share this code with SandboxMountPointProvider impl.
+bool CrosMountPointProvider::IsRestrictedFileName(const FilePath& path) const {
+ return false;
+}
+
+bool CrosMountPointProvider::IsAccessAllowed(const GURL& origin_url) {
+ return special_storage_policy_->IsLocalFileSystemAccessAllowed(origin_url);
+}
+
+} // namespace chromeos
+
diff --git a/webkit/chromeos/fileapi/cros_mount_point_provider.h b/webkit/chromeos/fileapi/cros_mount_point_provider.h
new file mode 100644
index 0000000..5ac8f37
--- /dev/null
+++ b/webkit/chromeos/fileapi/cros_mount_point_provider.h
@@ -0,0 +1,59 @@
+ // Copyright (c) 2011 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.
+
+#ifndef WEBKIT_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_
+#define WEBKIT_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "webkit/fileapi/file_system_mount_point_provider.h"
+#include "webkit/quota/special_storage_policy.h"
+
+namespace chromeos {
+
+// An interface to provide local filesystem paths.
+class CrosMountPointProvider
+ : public fileapi::FileSystemMountPointProvider {
+ public:
+ CrosMountPointProvider(
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy);
+ virtual ~CrosMountPointProvider();
+
+ // fileapi::FileSystemMountPointProvider overrides.
+ virtual bool IsAccessAllowed(const GURL& origin_url) OVERRIDE;
+
+ virtual void GetFileSystemRootPath(
+ const GURL& origin_url,
+ fileapi::FileSystemType type,
+ bool create,
+ fileapi::FileSystemPathManager::GetRootPathCallback* callback) OVERRIDE;
+
+ virtual FilePath GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url,
+ fileapi::FileSystemType type,
+ const FilePath& virtual_path,
+ bool create);
+
+ virtual bool IsRestrictedFileName(const FilePath& filename) const OVERRIDE;
+
+ private:
+ class GetFileSystemRootPathTask;
+ typedef std::map<std::string, std::string> MountPointMap;
+
+ static const char kLocalDirName[];
+ static const char kLocalName[];
+ FilePath virtual_root_path_;
+ FilePath base_path_;
+ std::string local_dir_name_;
+ MountPointMap mount_point_map_;
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+
+ DISALLOW_COPY_AND_ASSIGN(CrosMountPointProvider);
+};
+
+} // namespace chromeos
+
+#endif // WEBKIT_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_
diff --git a/webkit/database/database_tracker_unittest.cc b/webkit/database/database_tracker_unittest.cc
index a8d2928..d12524e 100644
--- a/webkit/database/database_tracker_unittest.cc
+++ b/webkit/database/database_tracker_unittest.cc
@@ -29,6 +29,10 @@ class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy {
virtual bool IsStorageUnlimited(const GURL& origin) {
return false;
}
+
+ virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) {
+ return false;
+ }
};
class TestObserver : public webkit_database::DatabaseTracker::Observer {
diff --git a/webkit/fileapi/file_system_context.cc b/webkit/fileapi/file_system_context.cc
index b5c1308..205963a 100644
--- a/webkit/fileapi/file_system_context.cc
+++ b/webkit/fileapi/file_system_context.cc
@@ -27,7 +27,8 @@ FileSystemContext::FileSystemContext(
allow_file_access_from_files_(allow_file_access),
unlimited_quota_(unlimited_quota),
path_manager_(new FileSystemPathManager(
- file_message_loop, profile_path, is_incognito, allow_file_access)),
+ file_message_loop, profile_path, special_storage_policy, is_incognito,
+ allow_file_access)),
usage_tracker_(new FileSystemUsageTracker(
file_message_loop, profile_path, is_incognito)) {
}
diff --git a/webkit/fileapi/file_system_context.h b/webkit/fileapi/file_system_context.h
index 16e3551..dbdb9aa 100644
--- a/webkit/fileapi/file_system_context.h
+++ b/webkit/fileapi/file_system_context.h
@@ -16,10 +16,6 @@ namespace base {
class MessageLoopProxy;
}
-namespace quota {
-class SpecialStoragePolicy;
-}
-
namespace fileapi {
class FileSystemContext;
diff --git a/webkit/fileapi/file_system_context_unittest.cc b/webkit/fileapi/file_system_context_unittest.cc
index 55dfcd9..d3ea661 100644
--- a/webkit/fileapi/file_system_context_unittest.cc
+++ b/webkit/fileapi/file_system_context_unittest.cc
@@ -12,7 +12,6 @@
#include "base/string_number_conversions.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/quota/special_storage_policy.h"
using namespace fileapi;
@@ -34,6 +33,10 @@ class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy {
virtual bool IsStorageUnlimited(const GURL& origin) {
return origin == GURL(kTestOrigins[1]);
}
+
+ virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) {
+ return false;
+ }
};
scoped_refptr<FileSystemContext> NewFileSystemContext(
diff --git a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc
index eff2b3b..49c68b5 100644
--- a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc
+++ b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -48,7 +48,8 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
file_thread_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
path_manager_.reset(new FileSystemPathManager(
- file_thread_proxy_, temp_dir_.path(), false, false));
+ file_thread_proxy_, temp_dir_.path(),
+ NULL, false, false));
path_manager_->GetFileSystemRootPath(
GURL("http://remote/"), kFileSystemTypeTemporary, true, // create
diff --git a/webkit/fileapi/file_system_mount_point_provider.h b/webkit/fileapi/file_system_mount_point_provider.h
index 3136636..3210331 100644
--- a/webkit/fileapi/file_system_mount_point_provider.h
+++ b/webkit/fileapi/file_system_mount_point_provider.h
@@ -35,6 +35,7 @@ class FileSystemMountPointProvider {
virtual FilePath GetFileSystemRootPathOnFileThread(
const GURL& origin_url,
FileSystemType type,
+ const FilePath& virtual_path,
bool create) = 0;
// Checks if a given |name| contains any restricted names/chars in it.
diff --git a/webkit/fileapi/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc
index 5de0c64..1555cd7 100644
--- a/webkit/fileapi/file_system_operation.cc
+++ b/webkit/fileapi/file_system_operation.cc
@@ -405,7 +405,8 @@ void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation_ptr) {
}
void FileSystemOperation::DidGetRootPath(
- bool success, const FilePath& path, const std::string& name) {
+ bool success,
+ const FilePath& path, const std::string& name) {
DCHECK(success || path.empty());
FilePath result;
// We ignore the path, and return a URL instead. The point was just to verify
@@ -492,6 +493,7 @@ void FileSystemOperation::DidGetMetadata(
void FileSystemOperation::DidReadDirectory(
base::PlatformFileError rv,
const std::vector<base::FileUtilProxy::Entry>& entries) {
+
if (rv == base::PLATFORM_FILE_OK)
dispatcher_->DidReadDirectory(entries, false /* has_more */);
else
@@ -550,6 +552,7 @@ bool FileSystemOperation::VerifyFileSystemPathForRead(
dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
return false;
}
+
return true;
}
diff --git a/webkit/fileapi/file_system_path_manager.cc b/webkit/fileapi/file_system_path_manager.cc
index 64f3274..3f4ed9f 100644
--- a/webkit/fileapi/file_system_path_manager.cc
+++ b/webkit/fileapi/file_system_path_manager.cc
@@ -19,6 +19,10 @@
#include "webkit/fileapi/sandbox_mount_point_provider.h"
#include "webkit/glue/webkit_glue.h"
+#if defined(OS_CHROMEOS)
+#include "webkit/chromeos/fileapi/cros_mount_point_provider.h"
+#endif
+
// We use some of WebKit types for conversions between origin identifiers
// and origin URLs.
using WebKit::WebFileSystem;
@@ -32,6 +36,7 @@ namespace fileapi {
FileSystemPathManager::FileSystemPathManager(
scoped_refptr<base::MessageLoopProxy> file_message_loop,
const FilePath& profile_path,
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
bool is_incognito,
bool allow_file_access_from_files)
: is_incognito_(is_incognito),
@@ -41,6 +46,10 @@ FileSystemPathManager::FileSystemPathManager(
ALLOW_THIS_IN_INITIALIZER_LIST(this),
file_message_loop,
profile_path)) {
+#if defined(OS_CHROMEOS)
+ local_provider_.reset(
+ new chromeos::CrosMountPointProvider(special_storage_policy));
+#endif
}
FileSystemPathManager::~FileSystemPathManager() {}
@@ -55,6 +64,14 @@ void FileSystemPathManager::GetFileSystemRootPath(
sandbox_provider_->GetFileSystemRootPath(
origin_url, type, create, callback_ptr);
break;
+ case kFileSystemTypeLocal:
+ if (local_provider_.get()) {
+ local_provider_->GetFileSystemRootPath(
+ origin_url, type, create, callback_ptr);
+ } else {
+ callback_ptr->Run(false, FilePath(), std::string());
+ }
+ break;
case kFileSystemTypeUnknown:
default:
NOTREACHED();
@@ -63,13 +80,19 @@ void FileSystemPathManager::GetFileSystemRootPath(
}
FilePath FileSystemPathManager::GetFileSystemRootPathOnFileThread(
- const GURL& origin_url, FileSystemType type, bool create) {
+ const GURL& origin_url, FileSystemType type, const FilePath& virtual_path,
+ bool create) {
switch (type) {
case kFileSystemTypeTemporary:
case kFileSystemTypePersistent:
return sandbox_provider_->GetFileSystemRootPathOnFileThread(
- origin_url, type, create);
+ origin_url, type, virtual_path, create);
break;
+ case kFileSystemTypeLocal:
+ return local_provider_.get() ?
+ local_provider_->GetFileSystemRootPathOnFileThread(
+ origin_url, type, virtual_path, create) :
+ FilePath();
case kFileSystemTypeUnknown:
default:
NOTREACHED();
@@ -114,6 +137,25 @@ bool FileSystemPathManager::CrackFileSystemPath(
local_path = local_path.NormalizeWindowsPathSeparators();
#endif
+ // Check if file access to this type of file system is allowed
+ // for this origin.
+ switch (local_type) {
+ case kFileSystemTypeTemporary:
+ case kFileSystemTypePersistent:
+ if (!sandbox_provider_->IsAccessAllowed(local_url))
+ return false;
+ break;
+ case kFileSystemTypeLocal:
+ if (!local_provider_.get() ||
+ !local_provider_->IsAccessAllowed(local_url)) {
+ return false;
+ }
+ break;
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED();
+ return false;
+ }
// Any paths that include parent references are considered invalid.
// These should have been taken care of in CrackFileSystemURL.
DCHECK(!local_path.ReferencesParent());
@@ -160,6 +202,9 @@ bool FileSystemPathManager::IsRestrictedFileName(
case kFileSystemTypeTemporary:
case kFileSystemTypePersistent:
return sandbox_provider_->IsRestrictedFileName(filename);
+ case kFileSystemTypeLocal:
+ return local_provider_.get() ?
+ local_provider_->IsRestrictedFileName(filename) : true;
case kFileSystemTypeUnknown:
default:
NOTREACHED();
diff --git a/webkit/fileapi/file_system_path_manager.h b/webkit/fileapi/file_system_path_manager.h
index c1d2df9..5a9613a 100644
--- a/webkit/fileapi/file_system_path_manager.h
+++ b/webkit/fileapi/file_system_path_manager.h
@@ -10,6 +10,7 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "webkit/fileapi/file_system_types.h"
+#include "webkit/quota/special_storage_policy.h"
class GURL;
@@ -19,6 +20,7 @@ class MessageLoopProxy;
namespace fileapi {
+class FileSystemMountPointProvider;
class SandboxMountPointProvider;
// TODO(kinuko): Probably this module must be called FileSystemPathUtil
@@ -32,10 +34,12 @@ class SandboxMountPointProvider;
// <type> is either one of "Temporary" or "Persistent".
class FileSystemPathManager {
public:
- FileSystemPathManager(scoped_refptr<base::MessageLoopProxy> file_message_loop,
- const FilePath& profile_path,
- bool is_incognito,
- bool allow_file_access_from_files);
+ FileSystemPathManager(
+ scoped_refptr<base::MessageLoopProxy> file_message_loop,
+ const FilePath& profile_path,
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
+ bool is_incognito,
+ bool allow_file_access_from_files);
~FileSystemPathManager();
// Callback for GetFileSystemRootPath.
@@ -59,9 +63,11 @@ class FileSystemPathManager {
// Like GetFileSystemRootPath, but synchronous, and can be called only while
// running on the file thread.
- virtual FilePath GetFileSystemRootPathOnFileThread(const GURL& origin_url,
- FileSystemType type,
- bool create);
+ virtual FilePath GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url,
+ FileSystemType type,
+ const FilePath& virtual_path,
+ bool create);
// Cracks the given |path|, retrieves the information embedded in the path
// and populates |origin_url|, |type| and |virtual_path|. The |virtual_path|
// is a sandboxed path in the file system, i.e. the relative path to the
@@ -95,6 +101,7 @@ class FileSystemPathManager {
const bool is_incognito_;
const bool allow_file_access_from_files_;
scoped_ptr<SandboxMountPointProvider> sandbox_provider_;
+ scoped_ptr<FileSystemMountPointProvider> local_provider_;
DISALLOW_COPY_AND_ASSIGN(FileSystemPathManager);
};
diff --git a/webkit/fileapi/file_system_path_manager_unittest.cc b/webkit/fileapi/file_system_path_manager_unittest.cc
index 8f004c2..ca7a74a 100644
--- a/webkit/fileapi/file_system_path_manager_unittest.cc
+++ b/webkit/fileapi/file_system_path_manager_unittest.cc
@@ -19,6 +19,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/sandbox_mount_point_provider.h"
+#include "webkit/quota/special_storage_policy.h"
using namespace fileapi;
@@ -69,6 +70,8 @@ const struct RootPathFileURITest {
"file__0" PS "Temporary" },
{ fileapi::kFileSystemTypePersistent, "file:///",
"file__0" PS "Persistent" },
+ // TODO(zelidrag): Add fileapi::kFileSystemTypeLocal test cases here once
+ // we fix ChromeOS build of this test.
};
const struct CheckValidPathTest {
@@ -160,6 +163,21 @@ const struct IsRestrictedNameTest {
{ FILE_PATH_LITERAL("|ab"), true, },
};
+class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy {
+ public:
+ virtual bool IsStorageProtected(const GURL& origin) {
+ return false;
+ }
+
+ virtual bool IsStorageUnlimited(const GURL& origin) {
+ return true;
+ }
+
+ virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) {
+ return true;
+ }
+};
+
} // namespace
class FileSystemPathManagerTest : public testing::Test {
@@ -181,7 +199,11 @@ class FileSystemPathManagerTest : public testing::Test {
bool allow_file_access) {
return new FileSystemPathManager(
base::MessageLoopProxy::CreateForCurrentThread(),
- data_dir_.path(), incognito, allow_file_access);
+ data_dir_.path(),
+ scoped_refptr<quota::SpecialStoragePolicy>(
+ new TestSpecialStoragePolicy()),
+ incognito,
+ allow_file_access);
}
void OnGetRootPath(bool success,
diff --git a/webkit/fileapi/file_system_types.h b/webkit/fileapi/file_system_types.h
index 043e3a2..8b7fe01 100644
--- a/webkit/fileapi/file_system_types.h
+++ b/webkit/fileapi/file_system_types.h
@@ -10,6 +10,7 @@ namespace fileapi {
enum FileSystemType {
kFileSystemTypeTemporary,
kFileSystemTypePersistent,
+ kFileSystemTypeLocal,
kFileSystemTypeUnknown,
};
diff --git a/webkit/fileapi/file_system_url_request_job_unittest.cc b/webkit/fileapi/file_system_url_request_job_unittest.cc
index 2cdb6d1c..d23923c 100644
--- a/webkit/fileapi/file_system_url_request_job_unittest.cc
+++ b/webkit/fileapi/file_system_url_request_job_unittest.cc
@@ -69,7 +69,7 @@ class FileSystemURLRequestJobTest : public testing::Test {
// TODO(adamk): Run this on the FILE thread we've created as well.
path_manager_.reset(new FileSystemPathManager(
base::MessageLoopProxy::CreateForCurrentThread(),
- temp_dir_.path(), false, false));
+ temp_dir_.path(), NULL, false, false));
path_manager_->GetFileSystemRootPath(
GURL("http://remote/"), kFileSystemTypeTemporary, true, // create
diff --git a/webkit/fileapi/file_system_util.cc b/webkit/fileapi/file_system_util.cc
index ae36fa850..a15c2a8 100644
--- a/webkit/fileapi/file_system_util.cc
+++ b/webkit/fileapi/file_system_util.cc
@@ -17,6 +17,7 @@ namespace fileapi {
static const char kPersistentDir[] = "/persistent/";
static const char kTemporaryDir[] = "/temporary/";
+static const char kLocalDir[] = "/local/";
bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type,
FilePath* file_path) {
@@ -76,6 +77,9 @@ bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type,
} else if (path.compare(0, strlen(kTemporaryDir), kTemporaryDir) == 0) {
file_system_type = kFileSystemTypeTemporary;
path = path.substr(strlen(kTemporaryDir));
+ } else if (path.compare(0, strlen(kLocalDir), kLocalDir) == 0) {
+ file_system_type = kFileSystemTypeLocal;
+ path = path.substr(strlen(kLocalDir));
} else {
return false;
}
@@ -110,6 +114,9 @@ GURL GetFileSystemRootURI(
case kFileSystemTypePersistent:
path += (kPersistentDir + 1); // We don't want the leading slash.
break;
+ case kFileSystemTypeLocal:
+ path += (kLocalDir + 1); // We don't want the leading slash.
+ break;
default:
NOTREACHED();
return GURL();
diff --git a/webkit/fileapi/local_file_system_file_util.cc b/webkit/fileapi/local_file_system_file_util.cc
index a017d57..8def3f6 100644
--- a/webkit/fileapi/local_file_system_file_util.cc
+++ b/webkit/fileapi/local_file_system_file_util.cc
@@ -169,7 +169,7 @@ FilePath LocalFileSystemFileUtil::GetLocalPath(
FileSystemType type,
const FilePath& virtual_path) {
FilePath root = context->file_system_context()->path_manager()->
- GetFileSystemRootPathOnFileThread(origin_url, type, false);
+ GetFileSystemRootPathOnFileThread(origin_url, type, virtual_path, false);
if (root.empty())
return FilePath();
return root.Append(virtual_path);
diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc
index d7f6146..7576055 100644
--- a/webkit/fileapi/sandbox_mount_point_provider.cc
+++ b/webkit/fileapi/sandbox_mount_point_provider.cc
@@ -231,7 +231,8 @@ void SandboxMountPointProvider::GetFileSystemRootPath(
};
FilePath SandboxMountPointProvider::GetFileSystemRootPathOnFileThread(
- const GURL& origin_url, FileSystemType type, bool create) {
+ const GURL& origin_url, FileSystemType type, const FilePath& unused,
+ bool create) {
FilePath origin_base_path;
if (!GetOriginBasePathAndName(origin_url, &origin_base_path, type, NULL)) {
return FilePath();
diff --git a/webkit/fileapi/sandbox_mount_point_provider.h b/webkit/fileapi/sandbox_mount_point_provider.h
index b401435..be85f77 100644
--- a/webkit/fileapi/sandbox_mount_point_provider.h
+++ b/webkit/fileapi/sandbox_mount_point_provider.h
@@ -45,6 +45,7 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider {
virtual FilePath GetFileSystemRootPathOnFileThread(
const GURL& origin_url,
FileSystemType type,
+ const FilePath& unused,
bool create);
// The FileSystem directory name.
diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi
index 1b0e127..acb1b4a 100644
--- a/webkit/fileapi/webkit_fileapi.gypi
+++ b/webkit/fileapi/webkit_fileapi.gypi
@@ -54,6 +54,11 @@
'<(DEPTH)/webkit/support/setup_third_party.gyp:third_party_headers',
],
}],
+ ['chromeos==1', {
+ 'sources': [
+ '../chromeos/fileapi/cros_mount_point_provider.cc',
+ ],
+ }],
],
},
],
diff --git a/webkit/quota/special_storage_policy.h b/webkit/quota/special_storage_policy.h
index 90526f0..99cc643d 100644
--- a/webkit/quota/special_storage_policy.h
+++ b/webkit/quota/special_storage_policy.h
@@ -27,6 +27,9 @@ class SpecialStoragePolicy
// Unlimited storage is not subject to 'quotas'.
virtual bool IsStorageUnlimited(const GURL& origin) = 0;
+ // Local file system access allowed via File API.
+ virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) = 0;
+
protected:
friend class base::RefCountedThreadSafe<SpecialStoragePolicy>;
virtual ~SpecialStoragePolicy();