summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-13 09:18:29 +0000
committerbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-13 09:18:29 +0000
commit7bc8299dccc300184e850e1a76db110a85234db1 (patch)
tree668a92aea8b994e089644b20c1d7832e935a4c1a /chrome
parent82222efbc0eb7758d69671099971f1b6dd3eb20d (diff)
downloadchromium_src-7bc8299dccc300184e850e1a76db110a85234db1.zip
chromium_src-7bc8299dccc300184e850e1a76db110a85234db1.tar.gz
chromium_src-7bc8299dccc300184e850e1a76db110a85234db1.tar.bz2
Allow platform apps to get writable FileEntry objects from readable ones.
This propts the user to choose a path to save to, using the file entry passed in as a reference of where to save to. BUG=130196 TEST=Manual testing performed Review URL: https://chromiumcodereview.appspot.com/10539101 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141878 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/api/file_system/file_system_api.cc171
-rw-r--r--chrome/browser/extensions/api/file_system/file_system_api.h15
-rw-r--r--chrome/browser/extensions/shell_window_registry.cc13
-rw-r--r--chrome/browser/extensions/shell_window_registry.h7
-rw-r--r--chrome/chrome_renderer.gypi4
-rw-r--r--chrome/common/extensions/api/file_system.idl3
-rw-r--r--chrome/renderer/extensions/extension_dispatcher.cc10
-rw-r--r--chrome/renderer/extensions/file_system_natives.cc (renamed from chrome/renderer/extensions/experimental.app_custom_bindings.cc)4
-rw-r--r--chrome/renderer/extensions/file_system_natives.h (renamed from chrome/renderer/extensions/experimental.app_custom_bindings.h)12
-rw-r--r--chrome/renderer/resources/extensions/experimental.app_custom_bindings.js4
-rw-r--r--chrome/renderer/resources/extensions/file_system_custom_bindings.js42
11 files changed, 246 insertions, 39 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
index 7c3fa9a..bbf689e 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -5,26 +5,42 @@
#include "chrome/browser/extensions/api/file_system/file_system_api.h"
#include "base/file_path.h"
+#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 "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 "content/public/browser/web_contents.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/isolated_context.h"
-namespace extensions {
-
const char kInvalidParameters[] = "Invalid parameters";
const char kSecurityError[] = "Security error";
+const char kInvalidCallingPage[] = "Invalid calling page";
+const char kUserCancelled[] = "User cancelled";
-bool FileSystemGetDisplayPathFunction::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));
+namespace {
+bool GetFilePathOfFileEntry(const std::string& filesystem_name,
+ const std::string& filesystem_path,
+ const content::RenderViewHost* render_view_host,
+ FilePath* file_path,
+ std::string* error) {
std::string filesystem_id;
if (!fileapi::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) {
- error_ = kInvalidParameters;
+ *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;
}
@@ -32,22 +48,30 @@ bool FileSystemGetDisplayPathFunction::RunImpl() {
FilePath relative_path = FilePath::FromUTF8Unsafe(filesystem_path);
FilePath virtual_path = context->CreateVirtualPath(filesystem_id,
relative_path);
- FilePath file_path;
if (!context->CrackIsolatedPath(virtual_path,
&filesystem_id,
NULL,
- &file_path)) {
- error_ = kInvalidParameters;
+ 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 true;
+}
+
+} // namespace
+
+namespace extensions {
+
+bool FileSystemGetDisplayPathFunction::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 file_path;
+ if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path,
+ render_view_host_, &file_path, &error_)) {
return false;
}
@@ -55,4 +79,115 @@ bool FileSystemGetDisplayPathFunction::RunImpl() {
return true;
}
+// Handles showing a dialog to the user to ask for the filename for a file to
+// save.
+class FileSystemGetWritableFileEntryFunction::FilePicker
+ : public SelectFileDialog::Listener {
+ public:
+ FilePicker(FileSystemGetWritableFileEntryFunction* function,
+ content::WebContents* web_contents,
+ const FilePath& suggested_path)
+ : suggested_path_(suggested_path),
+ function_(function) {
+ select_file_dialog_ = SelectFileDialog::Create(this);
+ SelectFileDialog::FileTypeInfo file_type_info;
+ FilePath::StringType extension = suggested_path.Extension();
+ if (!extension.empty()) {
+ extension.erase(extension.begin()); // drop the .
+ file_type_info.extensions.resize(1);
+ file_type_info.extensions[0].push_back(extension);
+ }
+ file_type_info.include_all_files = true;
+ gfx::NativeWindow owning_window = web_contents ?
+ platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL;
+
+ select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE,
+ string16(),
+ suggested_path,
+ &file_type_info, 0, FILE_PATH_LITERAL(""),
+ web_contents, owning_window, NULL);
+ }
+
+ virtual ~FilePicker() {}
+
+ private:
+ // SelectFileDialog::Listener implementation.
+ virtual void FileSelected(const FilePath& path,
+ int index,
+ void* params) OVERRIDE {
+ function_->FileSelected(path);
+ delete this;
+ }
+
+ virtual void FileSelectionCanceled(void* params) OVERRIDE {
+ function_->FileSelectionCanceled();
+ delete this;
+ }
+
+ FilePath suggested_path_;
+
+ // For managing select file dialogs.
+ scoped_refptr<SelectFileDialog> select_file_dialog_;
+ scoped_refptr<FileSystemGetWritableFileEntryFunction> function_;
+
+ DISALLOW_COPY_AND_ASSIGN(FilePicker);
+};
+
+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;
+ }
+
+ ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
+ DCHECK(registry);
+ ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
+ render_view_host());
+ if (!shell_window) {
+ error_ = kInvalidCallingPage;
+ return false;
+ }
+
+ // The file picker will hold a reference to this function instance, preventing
+ // 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);
+ return true;
+}
+
+void FileSystemGetWritableFileEntryFunction::FileSelected(
+ const FilePath& path) {
+ 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();
+ policy->GrantReadWriteFileSystem(renderer_id, filesystem_id);
+
+ DictionaryValue* dict = new DictionaryValue();
+ result_.reset(dict);
+ dict->SetString("fileSystemId", filesystem_id);
+ dict->SetString("baseName", path.BaseName().AsUTF8Unsafe());
+ SendResponse(true);
+}
+
+void FileSystemGetWritableFileEntryFunction::FileSelectionCanceled() {
+ error_ = kUserCancelled;
+ SendResponse(false);
+}
+
} // 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 67a56e6..0757736 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.h
+++ b/chrome/browser/extensions/api/file_system/file_system_api.h
@@ -19,6 +19,21 @@ class FileSystemGetDisplayPathFunction : public SyncExtensionFunction {
virtual bool RunImpl() OVERRIDE;
};
+class FileSystemGetWritableFileEntryFunction : public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION_NAME("fileSystem.getWritableFileEntry");
+
+ protected:
+ virtual ~FileSystemGetWritableFileEntryFunction() {}
+ virtual bool RunImpl() OVERRIDE;
+
+ private:
+ class FilePicker;
+
+ void FileSelected(const FilePath& path);
+ void FileSelectionCanceled();
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_API_H_
diff --git a/chrome/browser/extensions/shell_window_registry.cc b/chrome/browser/extensions/shell_window_registry.cc
index ab91fe8..7934901 100644
--- a/chrome/browser/extensions/shell_window_registry.cc
+++ b/chrome/browser/extensions/shell_window_registry.cc
@@ -6,6 +6,8 @@
#include "chrome/browser/profiles/profile_dependency_manager.h"
#include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/common/extensions/extension.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
ShellWindowRegistry::ShellWindowRegistry() {}
@@ -45,6 +47,17 @@ ShellWindowRegistry::ShellWindowSet ShellWindowRegistry::GetShellWindowsForApp(
return app_windows;
}
+ShellWindow* ShellWindowRegistry::GetShellWindowForRenderViewHost(
+ content::RenderViewHost* render_view_host) const {
+ for (ShellWindowSet::const_iterator i = shell_windows_.begin();
+ i != shell_windows_.end(); ++i) {
+ if ((*i)->web_contents()->GetRenderViewHost() == render_view_host)
+ return *i;
+ }
+
+ return NULL;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Factory boilerplate
diff --git a/chrome/browser/extensions/shell_window_registry.h b/chrome/browser/extensions/shell_window_registry.h
index 52b5e18..9dd7051 100644
--- a/chrome/browser/extensions/shell_window_registry.h
+++ b/chrome/browser/extensions/shell_window_registry.h
@@ -17,6 +17,10 @@
class Profile;
class ShellWindow;
+namespace content {
+class RenderViewHost;
+}
+
// The ShellWindowRegistry tracks the ShellWindows for all platform apps for a
// particular profile.
// This class is planned to evolve into tracking all PlatformApps for a
@@ -57,6 +61,9 @@ class ShellWindowRegistry : public ProfileKeyedService {
ShellWindowSet GetShellWindowsForApp(const std::string app_id) const;
const ShellWindowSet& shell_windows() const { return shell_windows_; }
+ ShellWindow* GetShellWindowForRenderViewHost(
+ content::RenderViewHost* render_view_host) const;
+
private:
class Factory : public ProfileKeyedServiceFactory {
public:
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 9273650..ffd0eec 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -78,8 +78,6 @@
'renderer/extensions/context_menus_custom_bindings.h',
'renderer/extensions/event_bindings.cc',
'renderer/extensions/event_bindings.h',
- 'renderer/extensions/experimental.app_custom_bindings.cc',
- 'renderer/extensions/experimental.app_custom_bindings.h',
'renderer/extensions/experimental.usb_custom_bindings.cc',
'renderer/extensions/experimental.usb_custom_bindings.h',
'renderer/extensions/extension_custom_bindings.cc',
@@ -97,6 +95,8 @@
'renderer/extensions/file_browser_handler_custom_bindings.h',
'renderer/extensions/file_browser_private_custom_bindings.cc',
'renderer/extensions/file_browser_private_custom_bindings.h',
+ 'renderer/extensions/file_system_natives.cc',
+ 'renderer/extensions/file_system_natives.h',
'renderer/extensions/i18n_custom_bindings.cc',
'renderer/extensions/i18n_custom_bindings.h',
'renderer/extensions/media_gallery_custom_bindings.cc',
diff --git a/chrome/common/extensions/api/file_system.idl b/chrome/common/extensions/api/file_system.idl
index a4e6e9d..7881f3d 100644
--- a/chrome/common/extensions/api/file_system.idl
+++ b/chrome/common/extensions/api/file_system.idl
@@ -6,9 +6,12 @@
[nodoc] namespace fileSystem {
callback GetDisplayPathCallback = void (DOMString displayPath);
+ callback FileEntryCallback = void ([instanceOf=fileEntry] object fileEntry);
interface Functions {
static void getDisplayPath([instanceOf=FileEntry] object fileEntry,
GetDisplayPathCallback onSuccess);
+ static void getWritableFileEntry([instanceOf=FileEntry] object fileEntry,
+ FileEntryCallback onSuccess);
};
};
diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc
index 23af146..add0813 100644
--- a/chrome/renderer/extensions/extension_dispatcher.cc
+++ b/chrome/renderer/extensions/extension_dispatcher.cc
@@ -25,7 +25,6 @@
#include "chrome/renderer/extensions/chrome_v8_extension.h"
#include "chrome/renderer/extensions/context_menus_custom_bindings.h"
#include "chrome/renderer/extensions/event_bindings.h"
-#include "chrome/renderer/extensions/experimental.app_custom_bindings.h"
#include "chrome/renderer/extensions/experimental.usb_custom_bindings.h"
#include "chrome/renderer/extensions/extension_custom_bindings.h"
#include "chrome/renderer/extensions/extension_groups.h"
@@ -33,6 +32,7 @@
#include "chrome/renderer/extensions/extension_request_sender.h"
#include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h"
#include "chrome/renderer/extensions/file_browser_private_custom_bindings.h"
+#include "chrome/renderer/extensions/file_system_natives.h"
#include "chrome/renderer/extensions/i18n_custom_bindings.h"
#include "chrome/renderer/extensions/media_gallery_custom_bindings.h"
#include "chrome/renderer/extensions/miscellaneous_bindings.h"
@@ -78,13 +78,13 @@ using extensions::ApiDefinitionsNatives;
using extensions::AppWindowCustomBindings;
using extensions::ContextMenusCustomBindings;
using extensions::Extension;
-using extensions::ExperimentalAppCustomBindings;
using extensions::ExperimentalUsbCustomBindings;
using extensions::ExtensionAPI;
using extensions::ExtensionCustomBindings;
using extensions::Feature;
using extensions::FileBrowserHandlerCustomBindings;
using extensions::FileBrowserPrivateCustomBindings;
+using extensions::FileSystemNatives;
using extensions::I18NCustomBindings;
using extensions::MiscellaneousBindings;
using extensions::MediaGalleryCustomBindings;
@@ -500,6 +500,10 @@ void ExtensionDispatcher::RegisterNativeHandlers(ModuleSystem* module_system,
scoped_ptr<NativeHandler>(
new SetIconNatives(this, request_sender_.get())));
+ // Natives used by multiple APIs.
+ module_system->RegisterNativeHandler("file_system_natives",
+ scoped_ptr<NativeHandler>(new FileSystemNatives()));
+
// Custom bindings.
module_system->RegisterNativeHandler("app",
scoped_ptr<NativeHandler>(new AppBindings(this, context)));
@@ -512,8 +516,6 @@ void ExtensionDispatcher::RegisterNativeHandlers(ModuleSystem* module_system,
new ExtensionCustomBindings(this)));
module_system->RegisterNativeHandler("experimental_mediaGalleries",
scoped_ptr<NativeHandler>(new MediaGalleryCustomBindings()));
- module_system->RegisterNativeHandler("experimental_app",
- scoped_ptr<NativeHandler>(new ExperimentalAppCustomBindings()));
module_system->RegisterNativeHandler("experimental_usb",
scoped_ptr<NativeHandler>(new ExperimentalUsbCustomBindings()));
module_system->RegisterNativeHandler("file_browser_handler",
diff --git a/chrome/renderer/extensions/experimental.app_custom_bindings.cc b/chrome/renderer/extensions/file_system_natives.cc
index 65f7a6d..7ed653f 100644
--- a/chrome/renderer/extensions/experimental.app_custom_bindings.cc
+++ b/chrome/renderer/extensions/file_system_natives.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/renderer/extensions/experimental.app_custom_bindings.h"
+#include "chrome/renderer/extensions/file_system_natives.h"
#include <string>
@@ -48,7 +48,7 @@ static v8::Handle<v8::Value> GetIsolatedFileSystem(
namespace extensions {
-ExperimentalAppCustomBindings::ExperimentalAppCustomBindings()
+FileSystemNatives::FileSystemNatives()
: ChromeV8Extension(NULL) {
RouteStaticFunction("GetIsolatedFileSystem", &GetIsolatedFileSystem);
}
diff --git a/chrome/renderer/extensions/experimental.app_custom_bindings.h b/chrome/renderer/extensions/file_system_natives.h
index aa11c49a..d873f5c 100644
--- a/chrome/renderer/extensions/experimental.app_custom_bindings.h
+++ b/chrome/renderer/extensions/file_system_natives.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_RENDERER_EXTENSIONS_EXPERIMENTAL_APP_CUSTOM_BINDINGS_H_
-#define CHROME_RENDERER_EXTENSIONS_EXPERIMENTAL_APP_CUSTOM_BINDINGS_H_
+#ifndef CHROME_RENDERER_EXTENSIONS_FILE_SYSTEM_NATIVES_H_
+#define CHROME_RENDERER_EXTENSIONS_FILE_SYSTEM_NATIVES_H_
#pragma once
#include "base/compiler_specific.h"
@@ -12,14 +12,14 @@
namespace extensions {
// Custom bindings for the nativeFileSystem API.
-class ExperimentalAppCustomBindings : public ChromeV8Extension {
+class FileSystemNatives : public ChromeV8Extension {
public:
- ExperimentalAppCustomBindings();
+ FileSystemNatives();
private:
- DISALLOW_COPY_AND_ASSIGN(ExperimentalAppCustomBindings);
+ DISALLOW_COPY_AND_ASSIGN(FileSystemNatives);
};
} // namespace extensions
-#endif // CHROME_RENDERER_EXTENSIONS_EXPERIMENTAL_APP_CUSTOM_BINDINGS_H_
+#endif // CHROME_RENDERER_EXTENSIONS_FILE_SYSTEM_NATIVES_H_
diff --git a/chrome/renderer/resources/extensions/experimental.app_custom_bindings.js b/chrome/renderer/resources/extensions/experimental.app_custom_bindings.js
index 8f0cd1c..52284c7 100644
--- a/chrome/renderer/resources/extensions/experimental.app_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/experimental.app_custom_bindings.js
@@ -5,8 +5,8 @@
// Custom bindings for the experimental.app API.
var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();
-var experimentalAppNatives = requireNative('experimental_app');
-var GetIsolatedFileSystem = experimentalAppNatives.GetIsolatedFileSystem;
+var fileSystemHelpers = requireNative('file_system_natives');
+var GetIsolatedFileSystem = fileSystemHelpers.GetIsolatedFileSystem;
chromeHidden.registerCustomHook('experimental.app', function(bindingsAPI) {
chrome.experimental.app.onLaunched.dispatch =
diff --git a/chrome/renderer/resources/extensions/file_system_custom_bindings.js b/chrome/renderer/resources/extensions/file_system_custom_bindings.js
index 0e6da3a..1847279 100644
--- a/chrome/renderer/resources/extensions/file_system_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/file_system_custom_bindings.js
@@ -5,12 +5,44 @@
// Custom bindings for the fileSystem API.
var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();
+var fileSystemNatives = requireNative('file_system_natives');
+var GetIsolatedFileSystem = fileSystemNatives.GetIsolatedFileSystem;
chromeHidden.registerCustomHook('fileSystem', function(bindingsAPI) {
- bindingsAPI.apiFunctions.setUpdateArgumentsPostValidate(
- 'getDisplayPath', function(fileEntry, callback) {
- var fileSystemName = fileEntry.filesystem.name;
- var relativePath = fileEntry.fullPath.slice(1);
- return [fileSystemName, relativePath, callback];
+ var apiFunctions = bindingsAPI.apiFunctions;
+ function bindFileEntryFunction(functionName) {
+ apiFunctions.setUpdateArgumentsPostValidate(
+ functionName, function(fileEntry, callback) {
+ var fileSystemName = fileEntry.filesystem.name;
+ var relativePath = fileEntry.fullPath.slice(1);
+ return [fileSystemName, relativePath, callback];
+ });
+ }
+ ['getDisplayPath', 'getWritableFileEntry'].forEach(bindFileEntryFunction);
+
+ apiFunctions.setCustomCallback('getWritableFileEntry',
+ function(name, request, response) {
+ if (request.callback && response) {
+ var callback = request.callback;
+ request.callback = null;
+
+ var fileSystemId = response.fileSystemId;
+ var baseName = response.baseName;
+ var fs = GetIsolatedFileSystem(fileSystemId);
+
+ try {
+ fs.root.getFile(baseName, {}, function(fileEntry) {
+ callback(fileEntry);
+ }, function(fileError) {
+ chrome.extension.lastError =
+ 'Error getting fileEntry, code: ' + fileError.code;
+ callback();
+ });
+ } catch (e) {
+ chrome.extension.lastError =
+ 'Error in event handler for onLaunched: ' + e.stack;
+ callback();
+ }
+ }
});
});