| Index: chrome/common/extensions/extension.cc
 | 
| ===================================================================
 | 
| --- chrome/common/extensions/extension.cc	(revision 81212)
 | 
| +++ chrome/common/extensions/extension.cc	(working copy)
 | 
| @@ -32,6 +32,7 @@
 | 
|  #include "chrome/common/extensions/extension_resource.h"
 | 
|  #include "chrome/common/extensions/extension_sidebar_defaults.h"
 | 
|  #include "chrome/common/extensions/extension_sidebar_utils.h"
 | 
| +#include "chrome/common/extensions/file_browser_action.h"
 | 
|  #include "chrome/common/extensions/user_script.h"
 | 
|  #include "chrome/common/url_constants.h"
 | 
|  #include "googleurl/src/url_util.h"
 | 
| @@ -210,7 +211,7 @@
 | 
|  const char Extension::kChromeosInfoPrivatePermissions[] = "chromeosInfoPrivate";
 | 
|  const char Extension::kDebuggerPermission[] = "debugger";
 | 
|  const char Extension::kExperimentalPermission[] = "experimental";
 | 
| -const char Extension::kFileSystemPermission[] = "fileSystem";
 | 
| +const char Extension::kFileBrowserHandlerPermission[] = "fileBrowserHandler";
 | 
|  const char Extension::kFileBrowserPrivatePermission[] = "fileBrowserPrivate";
 | 
|  const char Extension::kGeolocationPermission[] = "geolocation";
 | 
|  const char Extension::kHistoryPermission[] = "history";
 | 
| @@ -234,7 +235,7 @@
 | 
|    { kCookiePermission, 0 },
 | 
|    { kDebuggerPermission, IDS_EXTENSION_PROMPT_WARNING_DEBUGGER },
 | 
|    { kExperimentalPermission, 0 },
 | 
| -  { kFileSystemPermission, 0 },
 | 
| +  { kFileBrowserHandlerPermission, 0 },
 | 
|    { kFileBrowserPrivatePermission, 0 },
 | 
|    { kGeolocationPermission, IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION },
 | 
|    { kIdlePermission, 0 },
 | 
| @@ -879,6 +880,91 @@
 | 
|    return result.release();
 | 
|  }
 | 
|  
 | 
| +Extension::FileBrowserActionList* Extension::LoadFileBrowserActions(
 | 
| +    const ListValue* extension_actions, std::string* error) {
 | 
| +  scoped_ptr<FileBrowserActionList> result(
 | 
| +      new FileBrowserActionList());
 | 
| +  for (ListValue::const_iterator iter = extension_actions->begin();
 | 
| +       iter != extension_actions->end();
 | 
| +       ++iter) {
 | 
| +    if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) {
 | 
| +      *error = errors::kInvalidFileBrowserAction;
 | 
| +      return false;
 | 
| +    }
 | 
| +    scoped_ptr<FileBrowserAction> action(
 | 
| +        LoadFileBrowserAction(
 | 
| +            reinterpret_cast<DictionaryValue*>(*iter), error));
 | 
| +    if (!action.get())
 | 
| +      return NULL;  // Failed to parse file browser action definition.
 | 
| +    result->push_back(linked_ptr<FileBrowserAction>(action.release()));
 | 
| +  }
 | 
| +  return result.release();
 | 
| +}
 | 
| +
 | 
| +FileBrowserAction* Extension::LoadFileBrowserAction(
 | 
| +    const DictionaryValue* file_browser_action, std::string* error) {
 | 
| +  scoped_ptr<FileBrowserAction> result(
 | 
| +      new FileBrowserAction());
 | 
| +  result->set_extension_id(id());
 | 
| +
 | 
| +  std::string id;
 | 
| +  // Read the file action |id| (mandatory).
 | 
| +  if (!file_browser_action->HasKey(keys::kPageActionId) ||
 | 
| +      !file_browser_action->GetString(keys::kPageActionId, &id)) {
 | 
| +    *error = errors::kInvalidPageActionId;
 | 
| +    return NULL;
 | 
| +  }
 | 
| +  result->set_id(id);
 | 
| +
 | 
| +  // Read the page action title from |default_title| (mandatory).
 | 
| +  std::string title;
 | 
| +  if (!file_browser_action->HasKey(keys::kPageActionDefaultTitle) ||
 | 
| +      !file_browser_action->GetString(keys::kPageActionDefaultTitle, &title)) {
 | 
| +    *error = errors::kInvalidPageActionDefaultTitle;
 | 
| +    return NULL;
 | 
| +  }
 | 
| +  result->set_title(title);
 | 
| +
 | 
| +  // Initialize file filters (mandatory).
 | 
| +  ListValue* list_value = NULL;
 | 
| +  if (!file_browser_action->HasKey(keys::kFileFilters) ||
 | 
| +      !file_browser_action->GetList(keys::kFileFilters, &list_value) ||
 | 
| +      list_value->empty()) {
 | 
| +    *error = errors::kInvalidFileFiltersList;
 | 
| +    return false;
 | 
| +  }
 | 
| +  for (size_t i = 0; i < list_value->GetSize(); ++i) {
 | 
| +    std::string filter;
 | 
| +    if (!list_value->GetString(i, &filter)) {
 | 
| +      *error = ExtensionErrorUtils::FormatErrorMessage(
 | 
| +          errors::kInvalidFileFilterValue, base::IntToString(i));
 | 
| +      return false;
 | 
| +    }
 | 
| +    URLPattern pattern(URLPattern::SCHEME_FILESYSTEM);
 | 
| +    if (URLPattern::PARSE_SUCCESS != pattern.Parse(filter,
 | 
| +                                                   URLPattern::PARSE_STRICT)) {
 | 
| +      *error = ExtensionErrorUtils::FormatErrorMessage(
 | 
| +          errors::kInvalidURLPatternError, filter);
 | 
| +      return false;
 | 
| +    }
 | 
| +    result->AddPattern(pattern);
 | 
| +  }
 | 
| +
 | 
| +  std::string default_icon;
 | 
| +  // Read the file browser action |default_icon| (optional).
 | 
| +  if (file_browser_action->HasKey(keys::kPageActionDefaultIcon)) {
 | 
| +    if (!file_browser_action->GetString(
 | 
| +            keys::kPageActionDefaultIcon,&default_icon) ||
 | 
| +        default_icon.empty()) {
 | 
| +      *error = errors::kInvalidPageActionIconPath;
 | 
| +      return NULL;
 | 
| +    }
 | 
| +    result->set_icon_path(default_icon);
 | 
| +  }
 | 
| +
 | 
| +  return result.release();
 | 
| +}
 | 
| +
 | 
|  ExtensionSidebarDefaults* Extension::LoadExtensionSidebarDefaults(
 | 
|      const DictionaryValue* extension_sidebar, std::string* error) {
 | 
|    scoped_ptr<ExtensionSidebarDefaults> result(new ExtensionSidebarDefaults());
 | 
| @@ -1910,6 +1996,21 @@
 | 
|        return false;  // Failed to parse browser action definition.
 | 
|    }
 | 
|  
 | 
| +  // Initialize file browser actions (optional).
 | 
| +  if (source.HasKey(keys::kFileBrowserActions)) {
 | 
| +    ListValue* file_browser_actions_value = NULL;
 | 
| +    if (!source.GetList(keys::kFileBrowserActions,
 | 
| +                              &file_browser_actions_value)) {
 | 
| +      *error = errors::kInvalidFileBrowserAction;
 | 
| +      return false;
 | 
| +    }
 | 
| +
 | 
| +    file_browser_actions_.reset(
 | 
| +        LoadFileBrowserActions(file_browser_actions_value, error));
 | 
| +    if (!file_browser_actions_.get())
 | 
| +      return false;  // Failed to parse file browser actions definition.
 | 
| +  }
 | 
| +
 | 
|    // Load App settings.
 | 
|    if (!LoadIsApp(manifest_value_.get(), error) ||
 | 
|        !LoadExtent(manifest_value_.get(), keys::kWebURLs,
 | 
| @@ -1976,7 +2077,12 @@
 | 
|        // Only COMPONENT extensions can use private APIs.
 | 
|        // TODO(asargent) - We want a more general purpose mechanism for this,
 | 
|        // and better error messages. (http://crbug.com/54013)
 | 
| -      if (!IsComponentOnlyPermission(permission_str)) {
 | 
| +      if (!IsComponentOnlyPermission(permission_str)
 | 
| +#ifndef NDEBUG
 | 
| +           && !CommandLine::ForCurrentProcess()->HasSwitch(
 | 
| +                 switches::kExposePrivateExtensionApi)
 | 
| +#endif
 | 
| +          ) {
 | 
|          continue;
 | 
|        }
 | 
|  
 | 
| @@ -2573,7 +2679,12 @@
 | 
|  }
 | 
|  
 | 
|  bool Extension::CanExecuteScriptEverywhere() const {
 | 
| -  if (location() == Extension::COMPONENT)
 | 
| +  if (location() == Extension::COMPONENT
 | 
| +#ifndef NDEBUG
 | 
| +      || CommandLine::ForCurrentProcess()->HasSwitch(
 | 
| +          switches::kExposePrivateExtensionApi)
 | 
| +#endif
 | 
| +      )
 | 
|      return true;
 | 
|  
 | 
|    ScriptingWhitelist* whitelist =
 | 
| 
 |