diff options
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(); |