summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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();