diff options
author | benwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-28 21:23:57 +0000 |
---|---|---|
committer | benwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-28 21:23:57 +0000 |
commit | 67037167af9c70a339e8d78ba2ee3287646bf6c0 (patch) | |
tree | 211f2319f814bee90d15344d1c1b831409d8afd9 | |
parent | 0ee7d40cebf50b94bf9212289784861f76c121e2 (diff) | |
download | chromium_src-67037167af9c70a339e8d78ba2ee3287646bf6c0.zip chromium_src-67037167af9c70a339e8d78ba2ee3287646bf6c0.tar.gz chromium_src-67037167af9c70a339e8d78ba2ee3287646bf6c0.tar.bz2 |
Add fileSystemWrite permission for platform apps.
If an app has this permission, file entries it gets from the fileSystem
API are automatically writable. Others (e.g. from drop events) can be
converted via chrome.getWritableFileEntry.
If the app does not have the permission, it cannot get writable file entries
in any way.
BUG=134067
TEST=Automated tests added
Review URL: https://chromiumcodereview.appspot.com/10666045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144799 0039d316-1c4b-4281-b951-d872f2087c98
63 files changed, 1070 insertions, 262 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 9f159bb..0be26f8 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -4383,6 +4383,9 @@ Update checks have repeatedly failed for the extension "<ph name="EXTENSION_NAME <message name="IDS_EXTENSION_PROMPT_WARNING_DOWNLOADS" desc="Permission string for access to downloads."> Download files </message> + <message name="IDS_EXTENSION_PROMPT_WARNING_FILE_SYSTEM_WRITE" desc="Permission string for write access to the file system."> + Write to files that you have opened in the application + </message> <!-- Extension/App error messages --> <message name="IDS_EXTENSION_CANT_GET_ABSOLUTE_PATH" desc="Warning displayed in pack dialog when the absolute path to the extension directory can not be found."> diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc index d70eea3..dc0742a 100644 --- a/chrome/browser/extensions/api/file_system/file_system_api.cc +++ b/chrome/browser/extensions/api/file_system/file_system_api.cc @@ -10,8 +10,8 @@ #include "chrome/browser/extensions/shell_window_registry.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/ui/extensions/shell_window.h" -#include "chrome/browser/ui/select_file_dialog.h" #include "chrome/common/extensions/api/file_system.h" +#include "chrome/common/extensions/permissions/api_permission.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" @@ -24,7 +24,12 @@ const char kSecurityError[] = "Security error"; const char kInvalidCallingPage[] = "Invalid calling page"; const char kUserCancelled[] = "User cancelled"; const char kWritableFileError[] = "Invalid file for writing"; +const char kRequiresFileSystemWriteError[] = + "Operation requires fileSystemWrite permission"; +const char kUnknownChooseFileType[] = "Unknown type"; +const char kOpenFileOption[] = "openFile"; +const char kOpenWritableFileOption[] ="openWritableFile"; const char kSaveFileOption[] = "saveFile"; namespace file_system = extensions::api::file_system; @@ -98,24 +103,107 @@ bool FileSystemGetDisplayPathFunction::RunImpl() { FilePath file_path; if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path, - render_view_host_, &file_path, &error_)) { + render_view_host_, &file_path, &error_)) return false; - } result_.reset(base::Value::CreateStringValue(file_path.value())); return true; } +bool FileSystemEntryFunction::HasFileSystemWritePermission() { + const extensions::Extension* extension = GetExtension(); + if (!extension) + return false; + + return extension->HasAPIPermission(APIPermission::kFileSystemWrite); +} + +void FileSystemEntryFunction::CheckWritableFile(const FilePath& path) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + if (DoCheckWritableFile(path)) { + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&FileSystemEntryFunction::RegisterFileSystemAndSendResponse, + this, path, WRITABLE)); + return; + } + + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this)); +} + +void FileSystemEntryFunction::RegisterFileSystemAndSendResponse( + const FilePath& path, EntryType entry_type) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + std::set<FilePath> filesets; + filesets.insert(path); + + fileapi::IsolatedContext* isolated_context = + fileapi::IsolatedContext::GetInstance(); + DCHECK(isolated_context); + std::string filesystem_id = isolated_context->RegisterIsolatedFileSystem( + filesets); + + content::ChildProcessSecurityPolicy* policy = + content::ChildProcessSecurityPolicy::GetInstance(); + int renderer_id = render_view_host_->GetProcess()->GetID(); + if (entry_type == WRITABLE) + policy->GrantReadWriteFileSystem(renderer_id, filesystem_id); + else + policy->GrantReadFileSystem(renderer_id, filesystem_id); + + // We only need file level access for reading FileEntries. Saving FileEntries + // just needs the file system to have read/write access, which is granted + // above if required. + if (!policy->CanReadFile(renderer_id, path)) + policy->GrantReadFile(renderer_id, path); + + DictionaryValue* dict = new DictionaryValue(); + result_.reset(dict); + dict->SetString("fileSystemId", filesystem_id); + dict->SetString("baseName", path.BaseName().AsUTF8Unsafe()); + SendResponse(true); +} + +void FileSystemEntryFunction::HandleWritableFileError() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + error_ = kWritableFileError; + SendResponse(false); +} + +bool FileSystemGetWritableFileEntryFunction::RunImpl() { + std::string filesystem_name; + std::string filesystem_path; + EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); + EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); + + if (!HasFileSystemWritePermission()) { + error_ = kRequiresFileSystemWriteError; + return false; + } + + FilePath path; + if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path, + render_view_host_, &path, &error_)) + return false; + + content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, + base::Bind(&FileSystemGetWritableFileEntryFunction::CheckWritableFile, + this, path)); + return true; +} + // Handles showing a dialog to the user to ask for the filename for a file to // save or open. -class FileSystemPickerFunction::FilePicker : public SelectFileDialog::Listener { +class FileSystemChooseFileFunction::FilePicker + : public SelectFileDialog::Listener { public: - FilePicker(FileSystemPickerFunction* function, + FilePicker(FileSystemChooseFileFunction* function, content::WebContents* web_contents, const FilePath& suggested_path, - bool for_save) + SelectFileDialog::Type picker_type, + EntryType entry_type) : suggested_path_(suggested_path), - for_save_(for_save), + entry_type_(entry_type), function_(function) { select_file_dialog_ = SelectFileDialog::Create(this); SelectFileDialog::FileTypeInfo file_type_info; @@ -132,21 +220,21 @@ class FileSystemPickerFunction::FilePicker : public SelectFileDialog::Listener { if (g_skip_picker_for_test) { if (g_path_to_be_picked_for_test) { content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&FileSystemPickerFunction::FilePicker::FileSelected, + base::Bind( + &FileSystemChooseFileFunction::FilePicker::FileSelected, base::Unretained(this), *g_path_to_be_picked_for_test, 1, static_cast<void*>(NULL))); } else { content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind( - &FileSystemPickerFunction::FilePicker::FileSelectionCanceled, + &FileSystemChooseFileFunction::FilePicker:: + FileSelectionCanceled, base::Unretained(this), static_cast<void*>(NULL))); } return; } - select_file_dialog_->SelectFile(for_save ? - SelectFileDialog::SELECT_SAVEAS_FILE : - SelectFileDialog::SELECT_OPEN_FILE, + select_file_dialog_->SelectFile(picker_type, string16(), suggested_path, &file_type_info, 0, FILE_PATH_LITERAL(""), @@ -160,7 +248,7 @@ class FileSystemPickerFunction::FilePicker : public SelectFileDialog::Listener { virtual void FileSelected(const FilePath& path, int index, void* params) OVERRIDE { - function_->FileSelected(path, for_save_); + function_->FileSelected(path, entry_type_); delete this; } @@ -171,19 +259,18 @@ class FileSystemPickerFunction::FilePicker : public SelectFileDialog::Listener { FilePath suggested_path_; - // for_save_ is false when using the picker to open a file, and true - // when saving. It affects the style of the dialog and also what happens - // after a file is selected by the user. - bool for_save_; + EntryType entry_type_; scoped_refptr<SelectFileDialog> select_file_dialog_; - scoped_refptr<FileSystemPickerFunction> function_; + scoped_refptr<FileSystemChooseFileFunction> function_; DISALLOW_COPY_AND_ASSIGN(FilePicker); }; -bool FileSystemPickerFunction::ShowPicker(const FilePath& suggested_path, - bool for_save) { +bool FileSystemChooseFileFunction::ShowPicker( + const FilePath& suggested_path, + SelectFileDialog::Type picker_type, + EntryType entry_type) { ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile()); DCHECK(registry); ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost( @@ -197,124 +284,72 @@ bool FileSystemPickerFunction::ShowPicker(const FilePath& suggested_path, // its destruction (and subsequent sending of the function response) until the // user has selected a file or cancelled the picker. At that point, the picker // will delete itself, which will also free the function instance. - new FilePicker(this, shell_window->web_contents(), suggested_path, for_save); + new FilePicker(this, shell_window->web_contents(), suggested_path, + picker_type, entry_type); return true; } // static -void FileSystemPickerFunction::SkipPickerAndAlwaysSelectPathForTest( +void FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( FilePath* path) { g_skip_picker_for_test = true; g_path_to_be_picked_for_test = path; } // static -void FileSystemPickerFunction::SkipPickerAndAlwaysCancelForTest() { +void FileSystemChooseFileFunction::SkipPickerAndAlwaysCancelForTest() { g_skip_picker_for_test = true; g_path_to_be_picked_for_test = NULL; } // static -void FileSystemPickerFunction::StopSkippingPickerForTest() { +void FileSystemChooseFileFunction::StopSkippingPickerForTest() { g_skip_picker_for_test = false; } -void FileSystemPickerFunction::FileSelected(const FilePath& path, - bool for_save) { - if (for_save) { +void FileSystemChooseFileFunction::FileSelected(const FilePath& path, + EntryType entry_type) { + if (entry_type == WRITABLE) { content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, - base::Bind(&FileSystemPickerFunction::CheckWritableFile, this, path)); + base::Bind(&FileSystemChooseFileFunction::CheckWritableFile, + this, path)); return; } // Don't need to check the file, it's for reading. - RegisterFileSystemAndSendResponse(path, false); + RegisterFileSystemAndSendResponse(path, READ_ONLY); } -void FileSystemPickerFunction::FileSelectionCanceled() { +void FileSystemChooseFileFunction::FileSelectionCanceled() { error_ = kUserCancelled; SendResponse(false); } -void FileSystemPickerFunction::CheckWritableFile(const FilePath& path) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); - if (DoCheckWritableFile(path)) { - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&FileSystemPickerFunction::RegisterFileSystemAndSendResponse, - this, path, true)); - return; - } - - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&FileSystemPickerFunction::HandleWritableFileError, this)); -} - -void FileSystemPickerFunction::RegisterFileSystemAndSendResponse( - const FilePath& path, bool for_save) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - std::set<FilePath> filesets; - filesets.insert(path); - - fileapi::IsolatedContext* isolated_context = - fileapi::IsolatedContext::GetInstance(); - DCHECK(isolated_context); - std::string filesystem_id = isolated_context->RegisterIsolatedFileSystem( - filesets); - - content::ChildProcessSecurityPolicy* policy = - content::ChildProcessSecurityPolicy::GetInstance(); - int renderer_id = render_view_host_->GetProcess()->GetID(); - if (for_save) - policy->GrantReadWriteFileSystem(renderer_id, filesystem_id); - else - policy->GrantReadFileSystem(renderer_id, filesystem_id); - - // We only need file level access for reading FileEntries. Saving FileEntries - // just needs the file system to have read/write access, which is granted - // above if required. - if (!policy->CanReadFile(renderer_id, path)) - policy->GrantReadFile(renderer_id, path); - - DictionaryValue* dict = new DictionaryValue(); - result_.reset(dict); - dict->SetString("fileSystemId", filesystem_id); - dict->SetString("baseName", path.BaseName().AsUTF8Unsafe()); - SendResponse(true); -} - -void FileSystemPickerFunction::HandleWritableFileError() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - error_ = kWritableFileError; - SendResponse(false); -} - -bool FileSystemGetWritableFileEntryFunction::RunImpl() { - std::string filesystem_name; - std::string filesystem_path; - EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); - EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); - - FilePath suggested_path; - if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path, - render_view_host_, &suggested_path, &error_)) { - return false; - } - - return ShowPicker(suggested_path, true); -} - bool FileSystemChooseFileFunction::RunImpl() { scoped_ptr<ChooseFile::Params> params(ChooseFile::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - bool for_save = false; + EntryType entry_type = READ_ONLY; + SelectFileDialog::Type picker_type = SelectFileDialog::SELECT_OPEN_FILE; file_system::ChooseFileOptions* options = params->options.get(); - if (options) { - if (options->type.get() && *options->type == kSaveFileOption) - for_save = true; + if (options && options->type.get()) { + if (*options->type == kOpenWritableFileOption) { + entry_type = WRITABLE; + } else if (*options->type == kSaveFileOption) { + entry_type = WRITABLE; + picker_type = SelectFileDialog::SELECT_SAVEAS_FILE; + } else if (*options->type != kOpenFileOption) { + error_ = kUnknownChooseFileType; + return false; + } + } + + if (entry_type == WRITABLE && !HasFileSystemWritePermission()) { + error_ = kRequiresFileSystemWriteError; + return false; } - return ShowPicker(FilePath(), for_save); + return ShowPicker(FilePath(), picker_type, entry_type); } } // 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 index 7cc24db7..ec3293d 100644 --- a/chrome/browser/extensions/api/file_system/file_system_api.h +++ b/chrome/browser/extensions/api/file_system/file_system_api.h @@ -7,6 +7,7 @@ #pragma once #include "chrome/browser/extensions/extension_function.h" +#include "chrome/browser/ui/select_file_dialog.h" namespace extensions { @@ -19,39 +20,33 @@ class FileSystemGetDisplayPathFunction : public SyncExtensionFunction { virtual bool RunImpl() OVERRIDE; }; -class FileSystemPickerFunction : public AsyncExtensionFunction { - public: - // Allow picker UI to be skipped in testing. - static void SkipPickerAndAlwaysSelectPathForTest(FilePath* path); - static void SkipPickerAndAlwaysCancelForTest(); - static void StopSkippingPickerForTest(); - +class FileSystemEntryFunction : public AsyncExtensionFunction { protected: - class FilePicker; + enum EntryType { + READ_ONLY, + WRITABLE + }; - virtual ~FileSystemPickerFunction() {} - bool ShowPicker(const FilePath& suggested_path, bool for_save); + virtual ~FileSystemEntryFunction() {} - private: - // FileSelected and FileSelectionCanceled are called by the file picker. - void FileSelected(const FilePath& path, bool for_save); - void FileSelectionCanceled(); + bool HasFileSystemWritePermission(); - // called on the FILE thread. This is only called when a file is being chosen - // to save. The function will ensure the file exists, creating it if + // Called on the FILE thread. This is called when a writable file entry is + // being returned. The function will ensure the file exists, creating it if // necessary, and also check that the file is not a link. void CheckWritableFile(const FilePath& path); // This will finish the choose file process. This is either called directly // from FileSelected, or from CreateFileIfNecessary. It is called on the UI // thread. - void RegisterFileSystemAndSendResponse(const FilePath& path, bool for_save); + void RegisterFileSystemAndSendResponse(const FilePath& path, + EntryType entry_type); // called on the UI thread if there is a problem checking a writable file. void HandleWritableFileError(); }; -class FileSystemGetWritableFileEntryFunction : public FileSystemPickerFunction { +class FileSystemGetWritableFileEntryFunction : public FileSystemEntryFunction { public: DECLARE_EXTENSION_FUNCTION_NAME("fileSystem.getWritableFileEntry"); @@ -60,13 +55,28 @@ class FileSystemGetWritableFileEntryFunction : public FileSystemPickerFunction { virtual bool RunImpl() OVERRIDE; }; -class FileSystemChooseFileFunction : public FileSystemPickerFunction { +class FileSystemChooseFileFunction : public FileSystemEntryFunction { public: + // Allow picker UI to be skipped in testing. + static void SkipPickerAndAlwaysSelectPathForTest(FilePath* path); + static void SkipPickerAndAlwaysCancelForTest(); + static void StopSkippingPickerForTest(); + DECLARE_EXTENSION_FUNCTION_NAME("fileSystem.chooseFile"); protected: + class FilePicker; + virtual ~FileSystemChooseFileFunction() {} virtual bool RunImpl() OVERRIDE; + bool ShowPicker(const FilePath& suggested_path, + SelectFileDialog::Type picker_type, + EntryType entry_type); + + private: + // FileSelected and FileSelectionCanceled are called by the file picker. + void FileSelected(const FilePath& path, EntryType entry_type); + void FileSelectionCanceled(); }; } // namespace extensions diff --git a/chrome/browser/extensions/api/file_system/file_system_apitest.cc b/chrome/browser/extensions/api/file_system/file_system_apitest.cc index 68cf254..5142d99 100644 --- a/chrome/browser/extensions/api/file_system/file_system_apitest.cc +++ b/chrome/browser/extensions/api/file_system/file_system_apitest.cc @@ -6,41 +6,98 @@ #include "chrome/browser/extensions/api/file_system/file_system_api.h" #include "chrome/browser/extensions/platform_app_browsertest_util.h" +using extensions::FileSystemChooseFileFunction; + class FileSystemApiTest : public PlatformAppBrowserTest { public: virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { PlatformAppBrowserTest::SetUpCommandLine(command_line); - test_file_folder_ = test_data_dir_.AppendASCII("api_test") + test_root_folder_ = test_data_dir_.AppendASCII("api_test") .AppendASCII("file_system"); } virtual void TearDown() OVERRIDE { - extensions::FileSystemPickerFunction::StopSkippingPickerForTest(); + FileSystemChooseFileFunction::StopSkippingPickerForTest(); PlatformAppBrowserTest::TearDown(); }; protected: - FilePath test_file_folder_; + FilePath TempFilePath(const std::string& destination_name, bool copy_gold) { + if (!temp_dir_.CreateUniqueTempDir()) { + ADD_FAILURE() << "CreateUniqueTempDir failed"; + return FilePath(); + } + FilePath destination = temp_dir_.path().AppendASCII(destination_name); + if (copy_gold) { + FilePath source = test_root_folder_.AppendASCII("gold.txt"); + EXPECT_TRUE(file_util::CopyFile(source, destination)); + } + return destination; + } + + FilePath test_root_folder_; + ScopedTempDir temp_dir_; }; IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiGetDisplayPath) { - FilePath test_file = test_file_folder_.AppendASCII("open_existing.txt"); - extensions::FileSystemPickerFunction::SkipPickerAndAlwaysSelectPathForTest( + FilePath test_file = test_root_folder_.AppendASCII("gold.txt"); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( &test_file); ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/get_display_path")) << message_; } IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiOpenExistingFileTest) { - FilePath test_file = test_file_folder_.AppendASCII("open_existing.txt"); - extensions::FileSystemPickerFunction::SkipPickerAndAlwaysSelectPathForTest( + FilePath test_file = TempFilePath("open_existing.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( &test_file); ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/open_existing")) << message_; } +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, + FileSystemApiInvalidChooseFileTypeTest) { + FilePath test_file = TempFilePath("open_existing.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest( + "api_test/file_system/invalid_choose_file_type")) << message_; +} + +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, + FileSystemApiOpenExistingFileWithWriteTest) { + FilePath test_file = TempFilePath("open_existing.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest( + "api_test/file_system/open_existing_with_write")) << message_; +} + +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, + FileSystemApiOpenWritableExistingFileTest) { + FilePath test_file = TempFilePath("open_existing.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest( + "api_test/file_system/open_writable_existing")) << message_; +} + +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, + FileSystemApiOpenWritableExistingFileWithWriteTest) { + FilePath test_file = TempFilePath("open_existing.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest( + "api_test/file_system/open_writable_existing_with_write")) << message_; +} + IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiOpenCancelTest) { - extensions::FileSystemPickerFunction::SkipPickerAndAlwaysCancelForTest(); + FileSystemChooseFileFunction::SkipPickerAndAlwaysCancelForTest(); ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/open_cancel")) << message_; } @@ -51,28 +108,45 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiOpenBackgroundTest) { } IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiSaveNewFileTest) { - FilePath test_file = test_file_folder_.AppendASCII("save_new.txt"); - // Make sure test file path does not exist. - ASSERT_TRUE(file_util::Delete(test_file, false)); - extensions::FileSystemPickerFunction::SkipPickerAndAlwaysSelectPathForTest( + FilePath test_file = TempFilePath("save_new.txt", false); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( &test_file); ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_new")) << message_; } IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiSaveExistingFileTest) { - FilePath test_file = test_file_folder_.AppendASCII("save_existing.txt"); - // Replace test save file to make sure it's pristine. - ASSERT_TRUE(file_util::CopyFile( - test_file_folder_.AppendASCII("open_existing.txt"), test_file)); - extensions::FileSystemPickerFunction::SkipPickerAndAlwaysSelectPathForTest( + FilePath test_file = TempFilePath("save_existing.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( &test_file); ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_existing")) << message_; } +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, + FileSystemApiSaveNewFileWithWriteTest) { + FilePath test_file = TempFilePath("save_new.txt", false); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_new_with_write")) + << message_; +} + +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, + FileSystemApiSaveExistingFileWithWriteTest) { + FilePath test_file = TempFilePath("save_existing.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest( + "api_test/file_system/save_existing_with_write")) << message_; +} + IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiSaveCancelTest) { - extensions::FileSystemPickerFunction::SkipPickerAndAlwaysCancelForTest(); + FileSystemChooseFileFunction::SkipPickerAndAlwaysCancelForTest(); ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_cancel")) << message_; } @@ -81,3 +155,23 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiSaveBackgroundTest) { ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_background")) << message_; } + +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiGetWritableTest) { + FilePath test_file = TempFilePath("writable.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest( + "api_test/file_system/get_writable_file_entry")) << message_; +} + +IN_PROC_BROWSER_TEST_F(FileSystemApiTest, + FileSystemApiGetWritableWithWriteTest) { + FilePath test_file = TempFilePath("writable.txt", true); + ASSERT_FALSE(test_file.empty()); + FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( + &test_file); + ASSERT_TRUE(RunPlatformAppTest( + "api_test/file_system/get_writable_file_entry_with_write")) << message_; +} + diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index 569c608..8888066 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json @@ -124,6 +124,10 @@ "channel": "dev", "extension_types": ["platform_app"] }, + "fileSystemWrite": { + "channel": "dev", + "extension_types": ["platform_app"] + }, "geolocation": { "channel": "stable", "extension_types": [ diff --git a/chrome/common/extensions/api/file_system.idl b/chrome/common/extensions/api/file_system.idl index 0de28ff..b92df0e 100644 --- a/chrome/common/extensions/api/file_system.idl +++ b/chrome/common/extensions/api/file_system.idl @@ -6,7 +6,12 @@ namespace fileSystem { dictionary ChooseFileOptions { - // type can be 'openFile' or 'saveFile'. Default is 'openFile'. + // Valid types are 'openFile', 'openWritableFile' or 'saveFile'. Both + // 'openFile' and 'openWritableFile' will prompt the user to open an + // existing file, with 'openFile' returning a read-only FileEntry on + // success. 'saveFile' will prompt the user to choose an existing file or + // a new file, and will return a writable FileEntry. The default is + // 'openFile'. DOMString? type; }; callback GetDisplayPathCallback = void (DOMString displayPath); diff --git a/chrome/common/extensions/docs/apps/fileSystem.html b/chrome/common/extensions/docs/apps/fileSystem.html index 0d87fec..2511fe5 100644 --- a/chrome/common/extensions/docs/apps/fileSystem.html +++ b/chrome/common/extensions/docs/apps/fileSystem.html @@ -578,7 +578,7 @@ </div> </em> </dt> - <dd>type can be 'openFile' or 'saveFile'. Default is 'openFile'.</dd> + <dd>Valid types are 'openFile', 'openWritableFile' or 'saveFile'. Both 'openFile' and 'openWritableFile' will prompt the user to open an existing file, with 'openFile' returning a read-only FileEntry on success. 'saveFile' will prompt the user to choose an existing file or a new file, and will return a writable FileEntry. The default is 'openFile'.</dd> <!-- OBJECT PROPERTIES --> <!-- OBJECT METHODS --> <!-- OBJECT EVENT FIELDS --> diff --git a/chrome/common/extensions/docs/extensions/fileSystem.html b/chrome/common/extensions/docs/extensions/fileSystem.html index 1d90817..b771f24 100644 --- a/chrome/common/extensions/docs/extensions/fileSystem.html +++ b/chrome/common/extensions/docs/extensions/fileSystem.html @@ -725,7 +725,7 @@ </div> </em> </dt> - <dd>type can be 'openFile' or 'saveFile'. Default is 'openFile'.</dd> + <dd>Valid types are 'openFile', 'openWritableFile' or 'saveFile'. Both 'openFile' and 'openWritableFile' will prompt the user to open an existing file, with 'openFile' returning a read-only FileEntry on success. 'saveFile' will prompt the user to choose an existing file or a new file, and will return a writable FileEntry. The default is 'openFile'.</dd> <!-- OBJECT PROPERTIES --> <!-- OBJECT METHODS --> <!-- OBJECT EVENT FIELDS --> diff --git a/chrome/common/extensions/permissions/api_permission.cc b/chrome/common/extensions/permissions/api_permission.cc index a102a4c..753b356 100644 --- a/chrome/common/extensions/permissions/api_permission.cc +++ b/chrome/common/extensions/permissions/api_permission.cc @@ -86,7 +86,6 @@ void APIPermission::RegisterAllPermissions( { kContextMenus, "contextMenus" }, { kCookie, "cookies" }, { kFileBrowserHandler, "fileBrowserHandler", kFlagCannotBeOptional }, - { kFileSystem, "fileSystem" }, { kHistory, "history", kFlagNone, IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY, PermissionMessage::kBrowsingHistory }, @@ -162,6 +161,10 @@ void APIPermission::RegisterAllPermissions( { kVideoCapture, "videoCapture", kFlagNone, IDS_EXTENSION_PROMPT_WARNING_VIDEO_CAPTURE, PermissionMessage::kVideoCapture }, + { kFileSystem, "fileSystem" }, + { kFileSystemWrite, "fileSystemWrite", kFlagNone, + IDS_EXTENSION_PROMPT_WARNING_FILE_SYSTEM_WRITE, + PermissionMessage::kFileSystemWrite }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(PermissionsToRegister); ++i) { diff --git a/chrome/common/extensions/permissions/api_permission.h b/chrome/common/extensions/permissions/api_permission.h index b5d9f63..917833a 100644 --- a/chrome/common/extensions/permissions/api_permission.h +++ b/chrome/common/extensions/permissions/api_permission.h @@ -50,6 +50,7 @@ class APIPermission { kFileBrowserHandlerInternal, kFileBrowserPrivate, kFileSystem, + kFileSystemWrite, kGeolocation, kHistory, kIdle, diff --git a/chrome/common/extensions/permissions/permission_message.h b/chrome/common/extensions/permissions/permission_message.h index e8710af..3ab22da 100644 --- a/chrome/common/extensions/permissions/permission_message.h +++ b/chrome/common/extensions/permissions/permission_message.h @@ -47,6 +47,7 @@ class PermissionMessage { kAudioCapture, kVideoCapture, kDownloads, + kFileSystemWrite, kEnumBoundary }; diff --git a/chrome/test/data/extensions/api_test/file_system/get_display_path/manifest.json b/chrome/test/data/extensions/api_test/file_system/get_display_path/manifest.json index c5120a5..62c24ef 100644 --- a/chrome/test/data/extensions/api_test/file_system/get_display_path/manifest.json +++ b/chrome/test/data/extensions/api_test/file_system/get_display_path/manifest.json @@ -10,7 +10,6 @@ }, "permissions": [ "experimental", - "appWindow", "fileSystem" ] } diff --git a/chrome/test/data/extensions/api_test/file_system/get_display_path/test.js b/chrome/test/data/extensions/api_test/file_system/get_display_path/test.js index 0836e7a..292ed7e 100644 --- a/chrome/test/data/extensions/api_test/file_system/get_display_path/test.js +++ b/chrome/test/data/extensions/api_test/file_system/get_display_path/test.js @@ -5,12 +5,12 @@ chrome.test.runTests([ function getDisplayPath() { chrome.fileSystem.chooseFile(chrome.test.callbackPass(function(entry) { - chrome.test.assertEq('open_existing.txt', entry.name); + chrome.test.assertEq('gold.txt', entry.name); // Test that we can get the display path of the file. chrome.fileSystem.getDisplayPath(entry, chrome.test.callbackPass( function(path) { chrome.test.assertTrue(path.indexOf("file_system") >= 0); - chrome.test.assertTrue(path.indexOf("open_existing.txt") >= 0); + chrome.test.assertTrue(path.indexOf("gold.txt") >= 0); })); })); } diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/background.js b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/manifest.json b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/manifest.json new file mode 100644 index 0000000..be55801 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/manifest.json @@ -0,0 +1,15 @@ +{ + "name": "chrome.fileSystem get writable file entry", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.getWritableFileEntry", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/test.html b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/test.html new file mode 100644 index 0000000..8d7d1db --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/test.html @@ -0,0 +1,3 @@ +<html> +<script src="test.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/test.js b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/test.js new file mode 100644 index 0000000..35f270c --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry/test.js @@ -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. + +chrome.test.runTests([ + function getWritableEntry() { + chrome.fileSystem.chooseFile(chrome.test.callbackPass(function(entry) { + chrome.test.assertEq('writable.txt', entry.name); + // Test that we can get the display path of the file. + chrome.fileSystem.getWritableFileEntry(entry, chrome.test.callbackFail( + 'Operation requires fileSystemWrite permission', function() {})); + })); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/background.js b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/manifest.json b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/manifest.json new file mode 100644 index 0000000..ff1bbdf --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "chrome.fileSystem get writable file entry with write.", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.getWritableFileEntry.", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem", + "fileSystemWrite" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test.html b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test.html new file mode 100644 index 0000000..d68c654 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test.html @@ -0,0 +1,4 @@ +<html> +<script src="test.js"></script> +<script src="test_util.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test.js b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test.js new file mode 100644 index 0000000..a99e602 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test.js @@ -0,0 +1,16 @@ +// 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. + +chrome.test.runTests([ + function getWritableEntry() { + chrome.fileSystem.chooseFile(chrome.test.callbackPass(function(entry) { + chrome.test.assertEq('writable.txt', entry.name); + // Test that we can get the display path of the file. + chrome.fileSystem.getWritableFileEntry(entry, chrome.test.callbackPass( + function(writable) { + checkEntry(writable, 'writable.txt', false, true); + })); + })); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test_util.js b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test_util.js new file mode 100644 index 0000000..479ef7f --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/get_writable_file_entry_with_write/test_util.js @@ -0,0 +1,62 @@ +// 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. + +// This is a duplicate of the file test_util in +// chrome/test/data/extensions/api_test/file_system + +function checkEntry(entry, expectedName, isNew, shouldBeWritable) { + chrome.test.assertEq(expectedName, entry.name); + // Test that the file can be read. + entry.file(chrome.test.callback(function(file) { + var reader = new FileReader(); + reader.onloadend = chrome.test.callbackPass(function(e) { + if (isNew) + chrome.test.assertEq(reader.result, ""); + else + chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); + // Test that we can write to the file, or not, depending on + // |shouldBeWritable|. + entry.createWriter(function(fileWriter) { + fileWriter.onwriteend = chrome.test.callback(function(e) { + if (fileWriter.error) { + if (shouldBeWritable) { + chrome.test.fail("Error writing to file: " + + fileWriter.error.toString()); + } else { + chrome.test.succeed(); + } + } else { + if (shouldBeWritable) { + // Get a new entry and check the data got to disk. + chrome.fileSystem.chooseFile(chrome.test.callbackPass( + function(readEntry) { + readEntry.file(chrome.test.callback(function(readFile) { + var readReader = new FileReader(); + readReader.onloadend = function(e) { + chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), + 0); + chrome.test.succeed(); + }; + readReader.onerror = function(e) { + chrome.test.fail("Failed to read file after write."); + }; + readReader.readAsText(readFile); + })); + })); + } else { + chrome.test.fail( + "'Could write to file that should not be writable."); + } + } + }); + var blob = new Blob(["HoHoHo!"], {type: "text/plain"}); + fileWriter.write(blob); + }); + }); + reader.onerror = chrome.test.callback(function(e) { + chrome.test.fail("Error reading file contents."); + }); + reader.readAsText(file); + })); +} diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing.txt b/chrome/test/data/extensions/api_test/file_system/gold.txt index c6604a6..c6604a6 100644 --- a/chrome/test/data/extensions/api_test/file_system/open_existing.txt +++ b/chrome/test/data/extensions/api_test/file_system/gold.txt diff --git a/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/background.js b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/manifest.json b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/manifest.json new file mode 100644 index 0000000..69ca1d7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/manifest.json @@ -0,0 +1,15 @@ +{ + "name": "chrome.fileSystem invalid choose file.", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.chooseFile invalid type.", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/test.html b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/test.html new file mode 100644 index 0000000..8d7d1db --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/test.html @@ -0,0 +1,3 @@ +<html> +<script src="test.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/test.js b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/test.js new file mode 100644 index 0000000..ce57977 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/invalid_choose_file_type/test.js @@ -0,0 +1,10 @@ +// 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. + +chrome.test.runTests([ + function saveFile() { + chrome.fileSystem.chooseFile({type: 'invalid'}, chrome.test.callbackFail( + 'Unknown type', function() {})); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/open_cancel/manifest.json b/chrome/test/data/extensions/api_test/file_system/open_cancel/manifest.json index 9fb1f3c..928391c 100644 --- a/chrome/test/data/extensions/api_test/file_system/open_cancel/manifest.json +++ b/chrome/test/data/extensions/api_test/file_system/open_cancel/manifest.json @@ -10,7 +10,6 @@ }, "permissions": [ "experimental", - "appWindow", "fileSystem" ] } diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing/manifest.json b/chrome/test/data/extensions/api_test/file_system/open_existing/manifest.json index 92c3201..ec39a44 100644 --- a/chrome/test/data/extensions/api_test/file_system/open_existing/manifest.json +++ b/chrome/test/data/extensions/api_test/file_system/open_existing/manifest.json @@ -10,7 +10,6 @@ }, "permissions": [ "experimental", - "appWindow", "fileSystem" ] } diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing/test.html b/chrome/test/data/extensions/api_test/file_system/open_existing/test.html index 8d7d1db..d68c654 100644 --- a/chrome/test/data/extensions/api_test/file_system/open_existing/test.html +++ b/chrome/test/data/extensions/api_test/file_system/open_existing/test.html @@ -1,3 +1,4 @@ <html> <script src="test.js"></script> +<script src="test_util.js"></script> </html> diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing/test.js b/chrome/test/data/extensions/api_test/file_system/open_existing/test.js index 0cb41e9..f126826 100644 --- a/chrome/test/data/extensions/api_test/file_system/open_existing/test.js +++ b/chrome/test/data/extensions/api_test/file_system/open_existing/test.js @@ -5,29 +5,7 @@ chrome.test.runTests([ function openFile() { chrome.fileSystem.chooseFile(chrome.test.callbackPass(function(entry) { - chrome.test.assertEq('open_existing.txt', entry.name); - // Test that the file can be read. - entry.file(chrome.test.callback(function(file) { - var reader = new FileReader(); - reader.onloadend = chrome.test.callback(function(e) { - chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); - // Test that we cannot write to the file. - entry.createWriter(chrome.test.callback(function(fileWriter) { - fileWriter.onwriteend = chrome.test.callback(function(e) { - if (fileWriter.error) - chrome.test.succeed(); - else - chrome.test.fail("No error while writing without write access"); - }); - var blob = new Blob(['HoHoHo!'], {type: 'text/plain'}); - fileWriter.write(blob); - })); - }); - reader.onerror = chrome.test.callback(function(e) { - chrome.test.fail("Error reading file contents."); - }); - reader.readAsText(file); - })); + checkEntry(entry, 'open_existing.txt', false, false); })); } ]); diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing/test_util.js b/chrome/test/data/extensions/api_test/file_system/open_existing/test_util.js new file mode 100644 index 0000000..479ef7f --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_existing/test_util.js @@ -0,0 +1,62 @@ +// 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. + +// This is a duplicate of the file test_util in +// chrome/test/data/extensions/api_test/file_system + +function checkEntry(entry, expectedName, isNew, shouldBeWritable) { + chrome.test.assertEq(expectedName, entry.name); + // Test that the file can be read. + entry.file(chrome.test.callback(function(file) { + var reader = new FileReader(); + reader.onloadend = chrome.test.callbackPass(function(e) { + if (isNew) + chrome.test.assertEq(reader.result, ""); + else + chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); + // Test that we can write to the file, or not, depending on + // |shouldBeWritable|. + entry.createWriter(function(fileWriter) { + fileWriter.onwriteend = chrome.test.callback(function(e) { + if (fileWriter.error) { + if (shouldBeWritable) { + chrome.test.fail("Error writing to file: " + + fileWriter.error.toString()); + } else { + chrome.test.succeed(); + } + } else { + if (shouldBeWritable) { + // Get a new entry and check the data got to disk. + chrome.fileSystem.chooseFile(chrome.test.callbackPass( + function(readEntry) { + readEntry.file(chrome.test.callback(function(readFile) { + var readReader = new FileReader(); + readReader.onloadend = function(e) { + chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), + 0); + chrome.test.succeed(); + }; + readReader.onerror = function(e) { + chrome.test.fail("Failed to read file after write."); + }; + readReader.readAsText(readFile); + })); + })); + } else { + chrome.test.fail( + "'Could write to file that should not be writable."); + } + } + }); + var blob = new Blob(["HoHoHo!"], {type: "text/plain"}); + fileWriter.write(blob); + }); + }); + reader.onerror = chrome.test.callback(function(e) { + chrome.test.fail("Error reading file contents."); + }); + reader.readAsText(file); + })); +} diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/background.js b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/manifest.json b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/manifest.json new file mode 100644 index 0000000..c0104c9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "chrome.fileSystem open existing file with write", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.chooseFile opening existing file.", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem", + "fileSystemWrite" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test.html b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test.html new file mode 100644 index 0000000..d68c654 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test.html @@ -0,0 +1,4 @@ +<html> +<script src="test.js"></script> +<script src="test_util.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test.js b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test.js new file mode 100644 index 0000000..f126826 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test.js @@ -0,0 +1,11 @@ +// 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. + +chrome.test.runTests([ + function openFile() { + chrome.fileSystem.chooseFile(chrome.test.callbackPass(function(entry) { + checkEntry(entry, 'open_existing.txt', false, false); + })); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test_util.js b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test_util.js new file mode 100644 index 0000000..479ef7f --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_existing_with_write/test_util.js @@ -0,0 +1,62 @@ +// 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. + +// This is a duplicate of the file test_util in +// chrome/test/data/extensions/api_test/file_system + +function checkEntry(entry, expectedName, isNew, shouldBeWritable) { + chrome.test.assertEq(expectedName, entry.name); + // Test that the file can be read. + entry.file(chrome.test.callback(function(file) { + var reader = new FileReader(); + reader.onloadend = chrome.test.callbackPass(function(e) { + if (isNew) + chrome.test.assertEq(reader.result, ""); + else + chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); + // Test that we can write to the file, or not, depending on + // |shouldBeWritable|. + entry.createWriter(function(fileWriter) { + fileWriter.onwriteend = chrome.test.callback(function(e) { + if (fileWriter.error) { + if (shouldBeWritable) { + chrome.test.fail("Error writing to file: " + + fileWriter.error.toString()); + } else { + chrome.test.succeed(); + } + } else { + if (shouldBeWritable) { + // Get a new entry and check the data got to disk. + chrome.fileSystem.chooseFile(chrome.test.callbackPass( + function(readEntry) { + readEntry.file(chrome.test.callback(function(readFile) { + var readReader = new FileReader(); + readReader.onloadend = function(e) { + chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), + 0); + chrome.test.succeed(); + }; + readReader.onerror = function(e) { + chrome.test.fail("Failed to read file after write."); + }; + readReader.readAsText(readFile); + })); + })); + } else { + chrome.test.fail( + "'Could write to file that should not be writable."); + } + } + }); + var blob = new Blob(["HoHoHo!"], {type: "text/plain"}); + fileWriter.write(blob); + }); + }); + reader.onerror = chrome.test.callback(function(e) { + chrome.test.fail("Error reading file contents."); + }); + reader.readAsText(file); + })); +} diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing/background.js b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing/manifest.json b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/manifest.json new file mode 100644 index 0000000..d1480dd --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/manifest.json @@ -0,0 +1,15 @@ +{ + "name": "chrome.fileSystem open writable file", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.chooseFile opening writable file.", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing/test.html b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/test.html new file mode 100644 index 0000000..8d7d1db --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/test.html @@ -0,0 +1,3 @@ +<html> +<script src="test.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing/test.js b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/test.js new file mode 100644 index 0000000..1c9778d --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing/test.js @@ -0,0 +1,12 @@ +// 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. + +chrome.test.runTests([ + function openFile() { + chrome.fileSystem.chooseFile({type: 'openWritableFile'}, + chrome.test.callbackFail( + 'Operation requires fileSystemWrite permission', + function(entry) {})); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/background.js b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/manifest.json b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/manifest.json new file mode 100644 index 0000000..4eeb7e9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "chrome.fileSystem open writable file with write", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.chooseFile opening writable file.", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem", + "fileSystemWrite" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test.html b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test.html new file mode 100644 index 0000000..d68c654 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test.html @@ -0,0 +1,4 @@ +<html> +<script src="test.js"></script> +<script src="test_util.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test.js b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test.js new file mode 100644 index 0000000..1428764 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test.js @@ -0,0 +1,12 @@ +// 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. + +chrome.test.runTests([ + function openFile() { + chrome.fileSystem.chooseFile({type: 'openWritableFile'}, + chrome.test.callbackPass(function(entry) { + checkEntry(entry, 'open_existing.txt', false, true); + })); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test_util.js b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test_util.js new file mode 100644 index 0000000..479ef7f --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/open_writable_existing_with_write/test_util.js @@ -0,0 +1,62 @@ +// 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. + +// This is a duplicate of the file test_util in +// chrome/test/data/extensions/api_test/file_system + +function checkEntry(entry, expectedName, isNew, shouldBeWritable) { + chrome.test.assertEq(expectedName, entry.name); + // Test that the file can be read. + entry.file(chrome.test.callback(function(file) { + var reader = new FileReader(); + reader.onloadend = chrome.test.callbackPass(function(e) { + if (isNew) + chrome.test.assertEq(reader.result, ""); + else + chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); + // Test that we can write to the file, or not, depending on + // |shouldBeWritable|. + entry.createWriter(function(fileWriter) { + fileWriter.onwriteend = chrome.test.callback(function(e) { + if (fileWriter.error) { + if (shouldBeWritable) { + chrome.test.fail("Error writing to file: " + + fileWriter.error.toString()); + } else { + chrome.test.succeed(); + } + } else { + if (shouldBeWritable) { + // Get a new entry and check the data got to disk. + chrome.fileSystem.chooseFile(chrome.test.callbackPass( + function(readEntry) { + readEntry.file(chrome.test.callback(function(readFile) { + var readReader = new FileReader(); + readReader.onloadend = function(e) { + chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), + 0); + chrome.test.succeed(); + }; + readReader.onerror = function(e) { + chrome.test.fail("Failed to read file after write."); + }; + readReader.readAsText(readFile); + })); + })); + } else { + chrome.test.fail( + "'Could write to file that should not be writable."); + } + } + }); + var blob = new Blob(["HoHoHo!"], {type: "text/plain"}); + fileWriter.write(blob); + }); + }); + reader.onerror = chrome.test.callback(function(e) { + chrome.test.fail("Error reading file contents."); + }); + reader.readAsText(file); + })); +} diff --git a/chrome/test/data/extensions/api_test/file_system/save_background/manifest.json b/chrome/test/data/extensions/api_test/file_system/save_background/manifest.json index 6bde914..b490763 100644 --- a/chrome/test/data/extensions/api_test/file_system/save_background/manifest.json +++ b/chrome/test/data/extensions/api_test/file_system/save_background/manifest.json @@ -10,6 +10,7 @@ }, "permissions": [ "experimental", - "fileSystem" + "fileSystem", + "fileSystemWrite" ] } diff --git a/chrome/test/data/extensions/api_test/file_system/save_cancel/manifest.json b/chrome/test/data/extensions/api_test/file_system/save_cancel/manifest.json index 577d390..d7a394c 100644 --- a/chrome/test/data/extensions/api_test/file_system/save_cancel/manifest.json +++ b/chrome/test/data/extensions/api_test/file_system/save_cancel/manifest.json @@ -10,7 +10,7 @@ }, "permissions": [ "experimental", - "appWindow", - "fileSystem" + "fileSystem", + "fileSystemWrite" ] } diff --git a/chrome/test/data/extensions/api_test/file_system/save_existing/manifest.json b/chrome/test/data/extensions/api_test/file_system/save_existing/manifest.json index 226a071..17de889 100644 --- a/chrome/test/data/extensions/api_test/file_system/save_existing/manifest.json +++ b/chrome/test/data/extensions/api_test/file_system/save_existing/manifest.json @@ -10,7 +10,6 @@ }, "permissions": [ "experimental", - "appWindow", "fileSystem" ] } diff --git a/chrome/test/data/extensions/api_test/file_system/save_existing/test.js b/chrome/test/data/extensions/api_test/file_system/save_existing/test.js index 1691cfd..f9f2b48 100644 --- a/chrome/test/data/extensions/api_test/file_system/save_existing/test.js +++ b/chrome/test/data/extensions/api_test/file_system/save_existing/test.js @@ -4,48 +4,7 @@ chrome.test.runTests([ function saveFile() { - chrome.fileSystem.chooseFile({type: 'saveFile'}, chrome.test.callbackPass( - function(entry) { - chrome.test.assertEq('save_existing.txt', entry.name); - // Test that the file can be readt. - entry.file(chrome.test.callback(function(file) { - var reader = new FileReader(); - reader.onloadend = chrome.test.callbackPass(function(e) { - chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); - // Test that we can write to the file. - entry.createWriter(function(fileWriter) { - fileWriter.onwriteend = chrome.test.callback(function(e) { - if (fileWriter.error) { - chrome.test.fail("Error writing to file: " + - fileWriter.error.toString()); - } else { - // Get a new entry and check the data got to disk. - chrome.fileSystem.chooseFile(chrome.test.callbackPass( - function(readEntry) { - readEntry.file(chrome.test.callback(function(readFile) { - var readReader = new FileReader(); - readReader.onloadend = function(e) { - chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), - 0); - chrome.test.succeed(); - }; - readReader.onerror = function(e) { - chrome.test.fail('Failed to read file after write.'); - }; - readReader.readAsText(readFile); - })); - })); - } - }); - var blob = new Blob(['HoHoHo!'], {type: 'text/plain'}); - fileWriter.write(blob); - }); - }); - reader.onerror = chrome.test.callback(function(e) { - chrome.test.fail("Error reading file contents."); - }); - reader.readAsText(file); - })); - })); + chrome.fileSystem.chooseFile({type: 'saveFile'}, chrome.test.callbackFail( + 'Operation requires fileSystemWrite permission', function() {})); } ]); diff --git a/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/background.js b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/manifest.json b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/manifest.json new file mode 100644 index 0000000..3d483cd --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "chrome.fileSystem save existing file with write", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.chooseFile saving existing file.", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem", + "fileSystemWrite" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test.html b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test.html new file mode 100644 index 0000000..d68c654 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test.html @@ -0,0 +1,4 @@ +<html> +<script src="test.js"></script> +<script src="test_util.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test.js b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test.js new file mode 100644 index 0000000..64f3b33 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test.js @@ -0,0 +1,12 @@ +// 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. + +chrome.test.runTests([ + function saveFile() { + chrome.fileSystem.chooseFile({type: 'saveFile'}, + chrome.test.callbackPass(function(entry) { + checkEntry(entry, 'save_existing.txt', false, true); + })); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test_util.js b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test_util.js new file mode 100644 index 0000000..479ef7f --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_existing_with_write/test_util.js @@ -0,0 +1,62 @@ +// 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. + +// This is a duplicate of the file test_util in +// chrome/test/data/extensions/api_test/file_system + +function checkEntry(entry, expectedName, isNew, shouldBeWritable) { + chrome.test.assertEq(expectedName, entry.name); + // Test that the file can be read. + entry.file(chrome.test.callback(function(file) { + var reader = new FileReader(); + reader.onloadend = chrome.test.callbackPass(function(e) { + if (isNew) + chrome.test.assertEq(reader.result, ""); + else + chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); + // Test that we can write to the file, or not, depending on + // |shouldBeWritable|. + entry.createWriter(function(fileWriter) { + fileWriter.onwriteend = chrome.test.callback(function(e) { + if (fileWriter.error) { + if (shouldBeWritable) { + chrome.test.fail("Error writing to file: " + + fileWriter.error.toString()); + } else { + chrome.test.succeed(); + } + } else { + if (shouldBeWritable) { + // Get a new entry and check the data got to disk. + chrome.fileSystem.chooseFile(chrome.test.callbackPass( + function(readEntry) { + readEntry.file(chrome.test.callback(function(readFile) { + var readReader = new FileReader(); + readReader.onloadend = function(e) { + chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), + 0); + chrome.test.succeed(); + }; + readReader.onerror = function(e) { + chrome.test.fail("Failed to read file after write."); + }; + readReader.readAsText(readFile); + })); + })); + } else { + chrome.test.fail( + "'Could write to file that should not be writable."); + } + } + }); + var blob = new Blob(["HoHoHo!"], {type: "text/plain"}); + fileWriter.write(blob); + }); + }); + reader.onerror = chrome.test.callback(function(e) { + chrome.test.fail("Error reading file contents."); + }); + reader.readAsText(file); + })); +} diff --git a/chrome/test/data/extensions/api_test/file_system/save_new/manifest.json b/chrome/test/data/extensions/api_test/file_system/save_new/manifest.json index 0ba2bcf..6e059ea7 100644 --- a/chrome/test/data/extensions/api_test/file_system/save_new/manifest.json +++ b/chrome/test/data/extensions/api_test/file_system/save_new/manifest.json @@ -10,7 +10,6 @@ }, "permissions": [ "experimental", - "appWindow", "fileSystem" ] } diff --git a/chrome/test/data/extensions/api_test/file_system/save_new/test.js b/chrome/test/data/extensions/api_test/file_system/save_new/test.js index 6e4d22a..f9f2b48 100644 --- a/chrome/test/data/extensions/api_test/file_system/save_new/test.js +++ b/chrome/test/data/extensions/api_test/file_system/save_new/test.js @@ -4,48 +4,7 @@ chrome.test.runTests([ function saveFile() { - chrome.fileSystem.chooseFile({type: 'saveFile'}, chrome.test.callbackPass( - function(entry) { - chrome.test.assertEq('save_new.txt', entry.name); - // Test that the file can be read but has nothing in it. - entry.file(chrome.test.callback(function(file) { - var reader = new FileReader(); - reader.onloadend = chrome.test.callbackPass(function(e) { - chrome.test.assertEq(reader.result, ""); - // Test that we can write to the file. - entry.createWriter(function(fileWriter) { - fileWriter.onwriteend = chrome.test.callback(function(e) { - if (fileWriter.error) { - chrome.test.fail("Error writing to file: " + - fileWriter.error.toString()); - } else { - // Get a new entry and check the data got to disk. - chrome.fileSystem.chooseFile(chrome.test.callbackPass( - function(readEntry) { - readEntry.file(chrome.test.callback(function(readFile) { - var readReader = new FileReader(); - readReader.onloadend = function(e) { - chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), - 0); - chrome.test.succeed(); - }; - readReader.onerror = function(e) { - chrome.test.fail('Failed to read file after write.'); - }; - readReader.readAsText(readFile); - })); - })); - } - }); - var blob = new Blob(['HoHoHo!'], {type: 'text/plain'}); - fileWriter.write(blob); - }); - }); - reader.onerror = chrome.test.callback(function(e) { - chrome.test.fail("Error reading file contents."); - }); - reader.readAsText(file); - })); - })); + chrome.fileSystem.chooseFile({type: 'saveFile'}, chrome.test.callbackFail( + 'Operation requires fileSystemWrite permission', function() {})); } ]); diff --git a/chrome/test/data/extensions/api_test/file_system/save_new_with_write/background.js b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/background.js new file mode 100644 index 0000000..40ec2b7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/background.js @@ -0,0 +1,9 @@ +// 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. + +function onLaunched() { + chrome.appWindow.create('test.html'); +} + +chrome.experimental.app.onLaunched.addListener(onLaunched); diff --git a/chrome/test/data/extensions/api_test/file_system/save_new_with_write/manifest.json b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/manifest.json new file mode 100644 index 0000000..3f6b092 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "chrome.fileSystem save new file with write", + "version": "0.1", + "manifest_version": 2, + "description": "Test for chrome.fileSystem.chooseFile saving new file.", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "experimental", + "fileSystem", + "fileSystemWrite" + ] +} diff --git a/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test.html b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test.html new file mode 100644 index 0000000..d68c654 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test.html @@ -0,0 +1,4 @@ +<html> +<script src="test.js"></script> +<script src="test_util.js"></script> +</html> diff --git a/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test.js b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test.js new file mode 100644 index 0000000..b20ebc0 --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test.js @@ -0,0 +1,12 @@ +// 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. + +chrome.test.runTests([ + function saveFile() { + chrome.fileSystem.chooseFile({type: 'saveFile'}, + chrome.test.callbackPass(function(entry) { + checkEntry(entry, 'save_new.txt', true, true); + })); + } +]); diff --git a/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test_util.js b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test_util.js new file mode 100644 index 0000000..479ef7f --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/save_new_with_write/test_util.js @@ -0,0 +1,62 @@ +// 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. + +// This is a duplicate of the file test_util in +// chrome/test/data/extensions/api_test/file_system + +function checkEntry(entry, expectedName, isNew, shouldBeWritable) { + chrome.test.assertEq(expectedName, entry.name); + // Test that the file can be read. + entry.file(chrome.test.callback(function(file) { + var reader = new FileReader(); + reader.onloadend = chrome.test.callbackPass(function(e) { + if (isNew) + chrome.test.assertEq(reader.result, ""); + else + chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); + // Test that we can write to the file, or not, depending on + // |shouldBeWritable|. + entry.createWriter(function(fileWriter) { + fileWriter.onwriteend = chrome.test.callback(function(e) { + if (fileWriter.error) { + if (shouldBeWritable) { + chrome.test.fail("Error writing to file: " + + fileWriter.error.toString()); + } else { + chrome.test.succeed(); + } + } else { + if (shouldBeWritable) { + // Get a new entry and check the data got to disk. + chrome.fileSystem.chooseFile(chrome.test.callbackPass( + function(readEntry) { + readEntry.file(chrome.test.callback(function(readFile) { + var readReader = new FileReader(); + readReader.onloadend = function(e) { + chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), + 0); + chrome.test.succeed(); + }; + readReader.onerror = function(e) { + chrome.test.fail("Failed to read file after write."); + }; + readReader.readAsText(readFile); + })); + })); + } else { + chrome.test.fail( + "'Could write to file that should not be writable."); + } + } + }); + var blob = new Blob(["HoHoHo!"], {type: "text/plain"}); + fileWriter.write(blob); + }); + }); + reader.onerror = chrome.test.callback(function(e) { + chrome.test.fail("Error reading file contents."); + }); + reader.readAsText(file); + })); +} diff --git a/chrome/test/data/extensions/api_test/file_system/test_util.js b/chrome/test/data/extensions/api_test/file_system/test_util.js new file mode 100644 index 0000000..479ef7f --- /dev/null +++ b/chrome/test/data/extensions/api_test/file_system/test_util.js @@ -0,0 +1,62 @@ +// 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. + +// This is a duplicate of the file test_util in +// chrome/test/data/extensions/api_test/file_system + +function checkEntry(entry, expectedName, isNew, shouldBeWritable) { + chrome.test.assertEq(expectedName, entry.name); + // Test that the file can be read. + entry.file(chrome.test.callback(function(file) { + var reader = new FileReader(); + reader.onloadend = chrome.test.callbackPass(function(e) { + if (isNew) + chrome.test.assertEq(reader.result, ""); + else + chrome.test.assertEq(reader.result.indexOf("Can you see me?"), 0); + // Test that we can write to the file, or not, depending on + // |shouldBeWritable|. + entry.createWriter(function(fileWriter) { + fileWriter.onwriteend = chrome.test.callback(function(e) { + if (fileWriter.error) { + if (shouldBeWritable) { + chrome.test.fail("Error writing to file: " + + fileWriter.error.toString()); + } else { + chrome.test.succeed(); + } + } else { + if (shouldBeWritable) { + // Get a new entry and check the data got to disk. + chrome.fileSystem.chooseFile(chrome.test.callbackPass( + function(readEntry) { + readEntry.file(chrome.test.callback(function(readFile) { + var readReader = new FileReader(); + readReader.onloadend = function(e) { + chrome.test.assertEq(readReader.result.indexOf("HoHoHo!"), + 0); + chrome.test.succeed(); + }; + readReader.onerror = function(e) { + chrome.test.fail("Failed to read file after write."); + }; + readReader.readAsText(readFile); + })); + })); + } else { + chrome.test.fail( + "'Could write to file that should not be writable."); + } + } + }); + var blob = new Blob(["HoHoHo!"], {type: "text/plain"}); + fileWriter.write(blob); + }); + }); + reader.onerror = chrome.test.callback(function(e) { + chrome.test.fail("Error reading file contents."); + }); + reader.readAsText(file); + })); +} |