summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 00:05:32 +0000
committerbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 00:05:32 +0000
commitffc7b4d4d78923095866c6ee60ce7b7daefe89f8 (patch)
tree6fe017ff0b18981c8cf9d2a740b6bc20973a85dc
parentb1c4de4c2e2713ed8431d230d1e638efefaa7693 (diff)
downloadchromium_src-ffc7b4d4d78923095866c6ee60ce7b7daefe89f8.zip
chromium_src-ffc7b4d4d78923095866c6ee60ce7b7daefe89f8.tar.gz
chromium_src-ffc7b4d4d78923095866c6ee60ce7b7daefe89f8.tar.bz2
Implement extension API chrome.fileSystem.getDisplayPath().
This allows platform apps to get the full path of file entries in isolated file systems for display purposes. BUG=130452 TEST=Test added Review URL: https://chromiumcodereview.appspot.com/10477009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141119 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/file_system/file_system_api.cc60
-rw-r--r--chrome/browser/extensions/api/file_system/file_system_api.h24
-rw-r--r--chrome/browser/extensions/platform_app_browsertest.cc9
-rw-r--r--chrome/chrome_browser_extensions.gypi2
-rw-r--r--chrome/common/extensions/api/_permission_features.json4
-rw-r--r--chrome/common/extensions/api/api.gyp1
-rw-r--r--chrome/common/extensions/api/file_system.idl14
-rw-r--r--chrome/common/extensions/extension_permission_set.cc3
-rw-r--r--chrome/common/extensions/extension_permission_set.h1
-rw-r--r--chrome/common/extensions/extension_permission_set_unittest.cc1
-rw-r--r--chrome/renderer/extensions/experimental.app_custom_bindings.cc5
-rw-r--r--chrome/renderer/extensions/media_gallery_custom_bindings.cc5
-rw-r--r--chrome/test/data/extensions/platform_apps/get_display_path/manifest.json18
-rw-r--r--chrome/test/data/extensions/platform_apps/get_display_path/test.js27
-rw-r--r--content/browser/child_process_security_policy_impl.cc9
-rw-r--r--content/browser/child_process_security_policy_impl.h2
-rw-r--r--content/public/browser/child_process_security_policy.h5
-rw-r--r--webkit/fileapi/file_system_util.cc30
-rw-r--r--webkit/fileapi/file_system_util.h14
-rw-r--r--webkit/fileapi/file_system_util_unittest.cc29
20 files changed, 255 insertions, 8 deletions
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc
new file mode 100644
index 0000000..d9a3104
--- /dev/null
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/file_system/file_system_api.h"
+
+#include "base/file_path.h"
+#include "chrome/common/extensions/api/file_system.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/fileapi/isolated_context.h"
+
+namespace GetDisplayPath = extensions::api::file_system::GetDisplayPath;
+
+namespace extensions {
+
+const char kInvalidParameters[] = "Invalid parameters";
+const char kSecurityError[] = "Security error";
+
+bool FileSystemGetDisplayPathFunction::RunImpl() {
+ scoped_ptr<GetDisplayPath::Params> params(GetDisplayPath::Params::Create(
+ *args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ std::string filesystem_id;
+ if (!fileapi::CrackIsolatedFileSystemName(params->fsname, &filesystem_id)) {
+ error_ = kInvalidParameters;
+ return false;
+ }
+
+ fileapi::IsolatedContext* context = fileapi::IsolatedContext::GetInstance();
+ FilePath relative_path = FilePath::FromUTF8Unsafe(params->fspath);
+ FilePath virtual_path = context->CreateVirtualPath(filesystem_id,
+ relative_path);
+ FilePath file_path;
+ if (!context->CrackIsolatedPath(virtual_path,
+ &filesystem_id,
+ NULL,
+ &file_path)) {
+ error_ = kInvalidParameters;
+ return false;
+ }
+
+ // Only return the display path if the process has read access to the
+ // filesystem.
+ content::ChildProcessSecurityPolicy* policy =
+ content::ChildProcessSecurityPolicy::GetInstance();
+ if (!policy->CanReadFileSystem(render_view_host_->GetProcess()->GetID(),
+ filesystem_id)) {
+ error_ = kSecurityError;
+ return false;
+ }
+
+ result_.reset(base::Value::CreateStringValue(file_path.value()));
+ return true;
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.h b/chrome/browser/extensions/api/file_system/file_system_api.h
new file mode 100644
index 0000000..67a56e6
--- /dev/null
+++ b/chrome/browser/extensions/api/file_system/file_system_api.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_API_H_
+#pragma once
+
+#include "chrome/browser/extensions/extension_function.h"
+
+namespace extensions {
+
+class FileSystemGetDisplayPathFunction : public SyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION_NAME("fileSystem.getDisplayPath");
+
+ protected:
+ virtual ~FileSystemGetDisplayPathFunction() {}
+ virtual bool RunImpl() OVERRIDE;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_API_H_
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc
index fbb99a4..bf9df1c 100644
--- a/chrome/browser/extensions/platform_app_browsertest.cc
+++ b/chrome/browser/extensions/platform_app_browsertest.cc
@@ -240,4 +240,13 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNothing) {
ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_nothing"))
<< message_;
}
+
+// Test that platform apps can use the chrome.fileSystem.getDisplayPath
+// function to get the native file system path of a file they are launched with.
+IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, GetDisplayPath) {
+ SetCommandLineArg("platform_apps/launch_files/test.txt");
+ ASSERT_TRUE(RunPlatformAppTest("platform_apps/get_display_path"))
+ << message_;
+}
+
#endif // defined(OS_CHROMEOS)
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index bd41b87..60f0bf6 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -139,6 +139,8 @@
'browser/extensions/api/extension_action/extension_page_actions_api.h',
'browser/extensions/api/extension_action/extension_page_actions_api_constants.cc',
'browser/extensions/api/extension_action/extension_page_actions_api_constants.h',
+ 'browser/extensions/api/file_system/file_system_api.cc',
+ 'browser/extensions/api/file_system/file_system_api.h',
'browser/extensions/api/idltest/idltest_api.cc',
'browser/extensions/api/idltest/idltest_api.h',
'browser/extensions/api/identity/identity_api.cc',
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index ac2d56c..072b810 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -110,6 +110,10 @@
"extension_types": ["extension", "packaged_app", "platform_app"],
"location": "component"
},
+ "fileSystem": {
+ "channel": "dev",
+ "extension_types": ["platform_app"]
+ },
"geolocation": {
"channel": "stable",
"extension_types": [
diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp
index d94c83c..e2bc07b 100644
--- a/chrome/common/extensions/api/api.gyp
+++ b/chrome/common/extensions/api/api.gyp
@@ -37,6 +37,7 @@
'experimental_serial.idl',
'experimental_socket.idl',
'experimental_usb.idl',
+ 'file_system.idl',
],
'cc_dir': 'chrome/common/extensions/api',
'root_namespace': 'extensions::api',
diff --git a/chrome/common/extensions/api/file_system.idl b/chrome/common/extensions/api/file_system.idl
new file mode 100644
index 0000000..502a26c
--- /dev/null
+++ b/chrome/common/extensions/api/file_system.idl
@@ -0,0 +1,14 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// File-level comment to appease parser. Eventually this will not be necessary.
+
+[nodoc] namespace fileSystem {
+ callback GetDisplayPathCallback = void (DOMString displayPath);
+
+ interface Functions {
+ static void getDisplayPath(DOMString fsname, DOMString fspath,
+ GetDisplayPathCallback onSuccess);
+ };
+};
diff --git a/chrome/common/extensions/extension_permission_set.cc b/chrome/common/extensions/extension_permission_set.cc
index fb392dd..52a292b 100644
--- a/chrome/common/extensions/extension_permission_set.cc
+++ b/chrome/common/extensions/extension_permission_set.cc
@@ -241,6 +241,9 @@ void ExtensionAPIPermission::RegisterAllPermissions(
kFileBrowserHandler, "fileBrowserHandler", 0,
ExtensionPermissionMessage::kNone, kFlagCannotBeOptional);
info->RegisterPermission(
+ kFileSystem, "fileSystem", 0,
+ ExtensionPermissionMessage::kNone, kFlagNone);
+ info->RegisterPermission(
kHistory, "history", IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
ExtensionPermissionMessage::kBrowsingHistory,
kFlagNone);
diff --git a/chrome/common/extensions/extension_permission_set.h b/chrome/common/extensions/extension_permission_set.h
index d8be820..83c4f0e 100644
--- a/chrome/common/extensions/extension_permission_set.h
+++ b/chrome/common/extensions/extension_permission_set.h
@@ -119,6 +119,7 @@ class ExtensionAPIPermission {
kExperimental,
kFileBrowserHandler,
kFileBrowserPrivate,
+ kFileSystem,
kGeolocation,
kHistory,
kIdle,
diff --git a/chrome/common/extensions/extension_permission_set_unittest.cc b/chrome/common/extensions/extension_permission_set_unittest.cc
index 6b560ee..b0020b5 100644
--- a/chrome/common/extensions/extension_permission_set_unittest.cc
+++ b/chrome/common/extensions/extension_permission_set_unittest.cc
@@ -622,6 +622,7 @@ TEST(ExtensionPermissionsTest, PermissionMessages) {
// Platform apps. TODO(miket): must we skip?
skip.insert(ExtensionAPIPermission::kSocket);
skip.insert(ExtensionAPIPermission::kUsb);
+ skip.insert(ExtensionAPIPermission::kFileSystem);
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
ExtensionAPIPermissionSet permissions = info->GetAll();
diff --git a/chrome/renderer/extensions/experimental.app_custom_bindings.cc b/chrome/renderer/extensions/experimental.app_custom_bindings.cc
index 683f883..65f7a6d 100644
--- a/chrome/renderer/extensions/experimental.app_custom_bindings.cc
+++ b/chrome/renderer/extensions/experimental.app_custom_bindings.cc
@@ -30,9 +30,8 @@ static v8::Handle<v8::Value> GetIsolatedFileSystem(
GURL context_url = UserScriptSlave::GetDataSourceURLForFrame(webframe);
CHECK(context_url.SchemeIs(chrome::kExtensionScheme));
- std::string name(fileapi::GetFileSystemName(context_url.GetOrigin(),
- fileapi::kFileSystemTypeIsolated));
- name.append(file_system_id);
+ std::string name(fileapi::GetIsolatedFileSystemName(context_url.GetOrigin(),
+ file_system_id));
std::string root(fileapi::GetFileSystemRootURI(context_url.GetOrigin(),
fileapi::kFileSystemTypeIsolated).spec());
diff --git a/chrome/renderer/extensions/media_gallery_custom_bindings.cc b/chrome/renderer/extensions/media_gallery_custom_bindings.cc
index baedab9..2b8a6d3 100644
--- a/chrome/renderer/extensions/media_gallery_custom_bindings.cc
+++ b/chrome/renderer/extensions/media_gallery_custom_bindings.cc
@@ -57,10 +57,7 @@ v8::Handle<v8::Value> MediaGalleryCustomBindings::GetMediaFileSystemObject(
const GURL origin = GURL(webframe->document().securityOrigin().toString());
const GURL root_url =
fileapi::GetFileSystemRootURI(origin, fileapi::kFileSystemTypeIsolated);
- const std::string fsname_prefix =
- fileapi::GetFileSystemName(origin, fileapi::kFileSystemTypeIsolated);
- const std::string fsname =
- base::StringPrintf("%s_%s", fsname_prefix.c_str(), fsid.c_str());
+ const std::string fsname = fileapi::GetIsolatedFileSystemName(origin, fsid);
const std::string url = base::StringPrintf("%s%s/%s/",
root_url.spec().c_str(),
fsid.c_str(),
diff --git a/chrome/test/data/extensions/platform_apps/get_display_path/manifest.json b/chrome/test/data/extensions/platform_apps/get_display_path/manifest.json
new file mode 100644
index 0000000..526abff
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/get_display_path/manifest.json
@@ -0,0 +1,18 @@
+{
+ "name": "Platform App fileSystem.getDisplayPath test",
+ "platform_app": true,
+ "version": "1",
+ "manifest_version": 2,
+ "intents": {
+ "http://webintents.org/view": {
+ "type": [
+ "text/*"
+ ],
+ "title": "Test editor"
+ }
+ },
+ "permissions": ["experimental", "fileSystem"],
+ "background": {
+ "scripts": ["test.js"]
+ }
+}
diff --git a/chrome/test/data/extensions/platform_apps/get_display_path/test.js b/chrome/test/data/extensions/platform_apps/get_display_path/test.js
new file mode 100644
index 0000000..2ab01ea
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/get_display_path/test.js
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test that there is a launchData.intent, it is set up proerly, and that the
+// FileEntry in launchData.intent.data can be read.
+function onLaunched(launchData) {
+ chrome.test.runTests([
+ function testIntent() {
+ chrome.test.assertFalse(!launchData, "No launchData");
+ chrome.test.assertFalse(!launchData.intent, "No launchData.intent");
+ chrome.test.assertEq(launchData.intent.action,
+ "http://webintents.org/view");
+ chrome.test.assertEq(launchData.intent.type,
+ "chrome-extension://fileentry");
+ chrome.test.assertFalse(!launchData.intent.data,
+ "No launchData.intent.data");
+ var entry = launchData.intent.data;
+ chrome.fileSystem.getDisplayPath(entry.filesystem.name,
+ entry.fullPath.slice(1), chrome.test.callbackPass(function(path) {
+ chrome.test.assertFalse(path.indexOf('test.txt') == -1);
+ }));
+ }
+ ]);
+}
+
+chrome.experimental.app.onLaunched.addListener(onLaunched);
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index 5ae03e7..d8d4415 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -465,7 +465,7 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
}
bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
- const FilePath& file) {
+ const FilePath& file) {
return HasPermissionsForFile(child_id, file, kReadFilePermissions);
}
@@ -476,6 +476,13 @@ bool ChildProcessSecurityPolicyImpl::CanReadDirectory(
kEnumerateDirectoryPermissions);
}
+bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
+ int child_id, const std::string& filesystem_id) {
+ return HasPermissionsForFileSystem(child_id,
+ filesystem_id,
+ kReadFilePermissions);
+}
+
bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
int child_id, const FilePath& file, int permissions) {
base::AutoLock lock(lock_);
diff --git a/content/browser/child_process_security_policy_impl.h b/content/browser/child_process_security_policy_impl.h
index d150e3f..330efb3 100644
--- a/content/browser/child_process_security_policy_impl.h
+++ b/content/browser/child_process_security_policy_impl.h
@@ -46,6 +46,8 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
const std::string& filesystem_id) OVERRIDE;
virtual void GrantScheme(int child_id, const std::string& scheme) OVERRIDE;
virtual bool CanReadFile(int child_id, const FilePath& file) OVERRIDE;
+ virtual bool CanReadFileSystem(int child_id,
+ const std::string& filesystem_id) OVERRIDE;
// Pseudo schemes are treated differently than other schemes because they
// cannot be requested like normal URLs. There is no mechanism for revoking
diff --git a/content/public/browser/child_process_security_policy.h b/content/public/browser/child_process_security_policy.h
index aecfdd1..141713b 100644
--- a/content/public/browser/child_process_security_policy.h
+++ b/content/public/browser/child_process_security_policy.h
@@ -96,6 +96,11 @@ class ChildProcessSecurityPolicy {
// Grants the child process the capability to access URLs of the provided
// scheme.
virtual void GrantScheme(int child_id, const std::string& scheme) = 0;
+
+ // Returns true iff read access has been granted to the file system with
+ // |filesystem_id|.
+ virtual bool CanReadFileSystem(int child_id,
+ const std::string& filesystem_id) = 0;
};
}; // namespace content
diff --git a/webkit/fileapi/file_system_util.cc b/webkit/fileapi/file_system_util.cc
index 985c021..285351a 100644
--- a/webkit/fileapi/file_system_util.cc
+++ b/webkit/fileapi/file_system_util.cc
@@ -276,4 +276,34 @@ WebKit::WebFileError PlatformFileErrorToWebFileError(
}
}
+std::string GetIsolatedFileSystemName(const GURL& origin_url,
+ const std::string& filesystem_id) {
+ std::string name(fileapi::GetFileSystemName(origin_url,
+ fileapi::kFileSystemTypeIsolated));
+ name.append("_");
+ name.append(filesystem_id);
+ return name;
+}
+
+bool CrackIsolatedFileSystemName(const std::string& filesystem_name,
+ std::string* filesystem_id) {
+ DCHECK(filesystem_id);
+
+ // |filesystem_name| is of the form {origin}:isolated_{filesystem_id}.
+ std::string start_token(":");
+ start_token = start_token.append(kIsolatedName).append("_");
+ size_t pos = filesystem_name.find(start_token);
+ if (pos == std::string::npos)
+ return false;
+ if (pos == 0)
+ return false;
+
+ *filesystem_id = filesystem_name.substr(pos + start_token.length(),
+ std::string::npos);
+ if (filesystem_id->empty())
+ return false;
+
+ return true;
+}
+
} // namespace fileapi
diff --git a/webkit/fileapi/file_system_util.h b/webkit/fileapi/file_system_util.h
index f23f177..841a30c 100644
--- a/webkit/fileapi/file_system_util.h
+++ b/webkit/fileapi/file_system_util.h
@@ -124,6 +124,20 @@ FILEAPI_EXPORT FilePath StringToFilePath(const std::string& file_path_string);
FILEAPI_EXPORT WebKit::WebFileError PlatformFileErrorToWebFileError(
base::PlatformFileError error_code);
+// Generate a file system name for the given arguments. Should only be used by
+// platform apps.
+FILEAPI_EXPORT std::string GetIsolatedFileSystemName(
+ const GURL& origin_url,
+ const std::string& filesystem_id);
+
+// Find the file system id from |filesystem_name|. Should only be used by
+// platform apps. This function will return false if the file system name is
+// not of the form {origin}:Isolated_{id}, and will also check that there is an
+// origin and id present. It will not check that the origin or id are valid.
+FILEAPI_EXPORT bool CrackIsolatedFileSystemName(
+ const std::string& filesystem_name,
+ std::string* filesystem_id);
+
} // namespace fileapi
#endif // WEBKIT_FILEAPI_FILE_SYSTEM_UTIL_H_
diff --git a/webkit/fileapi/file_system_util_unittest.cc b/webkit/fileapi/file_system_util_unittest.cc
index 7f567c0..6ac85e4 100644
--- a/webkit/fileapi/file_system_util_unittest.cc
+++ b/webkit/fileapi/file_system_util_unittest.cc
@@ -157,5 +157,34 @@ TEST_F(FileSystemUtilTest, VirtualPathGetComponents) {
}
}
+TEST_F(FileSystemUtilTest, GetIsolatedFileSystemName) {
+ GURL origin_url("http://foo");
+ std::string fsname1 = GetIsolatedFileSystemName(origin_url, "bar");
+ EXPECT_EQ("http_foo_0:Isolated_bar", fsname1);
+}
+
+TEST_F(FileSystemUtilTest, CrackIsolatedFileSystemName) {
+ std::string fsid;
+ EXPECT_TRUE(CrackIsolatedFileSystemName("foo:Isolated_bar", &fsid));
+ EXPECT_EQ("bar", fsid);
+ EXPECT_TRUE(CrackIsolatedFileSystemName("foo:Isolated__bar", &fsid));
+ EXPECT_EQ("_bar", fsid);
+ EXPECT_TRUE(CrackIsolatedFileSystemName("foo::Isolated_bar", &fsid));
+ EXPECT_EQ("bar", fsid);
+}
+
+TEST_F(FileSystemUtilTest, RejectBadIsolatedFileSystemName) {
+ std::string fsid;
+ EXPECT_FALSE(CrackIsolatedFileSystemName("foobar", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName("foo:_bar", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Isolatedbar", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName("fooIsolatedbar", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Persistent", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Temporary", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName("foo:External", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName(":Isolated_bar", &fsid));
+ EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Isolated_", &fsid));
+}
+
} // namespace (anonymous)
} // namespace fileapi