1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
28ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Use of this source code is governed by a BSD-style license that can be
38ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// found in the LICENSE file.
48ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
58ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension.h"
68ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
78ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include <algorithm>
88ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
98ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/base64.h"
108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/basictypes.h"
118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/command_line.h"
128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/file_path.h"
138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/file_util.h"
148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/i18n/rtl.h"
158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/logging.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/stl_util-inl.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/string16.h"
198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/string_number_conversions.h"
208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/utf_string_conversions.h"
218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/values.h"
228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/version.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/sha2.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/third_party/nss/blapi.h"
258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/chrome_constants.h"
268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/chrome_switches.h"
278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/chrome_version_info.h"
288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_action.h"
298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_constants.h"
308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_error_utils.h"
318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_l10n_util.h"
328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_resource.h"
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/extensions/extension_sidebar_defaults.h"
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/extensions/extension_sidebar_utils.h"
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/file_browser_handler.h"
368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/user_script.h"
378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/url_constants.h"
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "googleurl/src/url_util.h"
398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "grit/chromium_strings.h"
408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "grit/generated_resources.h"
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/theme_resources.h"
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/registry_controlled_domain.h"
438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "third_party/skia/include/core/SkBitmap.h"
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/resource/resource_bundle.h"
468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "webkit/glue/image_decoder.h"
478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace keys = extension_manifest_keys;
498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace values = extension_manifest_values;
508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace errors = extension_manifest_errors;
518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace {
538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst int kPEMOutputColumns = 65;
558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// KEY MARKERS
578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kKeyBeginHeaderMarker[] = "-----BEGIN";
588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kKeyBeginFooterMarker[] = "-----END";
598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kKeyInfoEndMarker[] = "KEY-----";
608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kPublic[] = "PUBLIC";
618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kPrivate[] = "PRIVATE";
628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst int kRSAKeySize = 1024;
648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Converts a normal hexadecimal string into the alphabet used by extensions.
668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// We use the characters 'a'-'p' instead of '0'-'f' to avoid ever having a
678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// completely numeric host, since some software interprets that as an IP
688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// address.
698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenstatic void ConvertHexadecimalToIDAlphabet(std::string* id) {
708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < id->size(); ++i) {
718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    int val;
72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (base::HexStringToInt(id->begin() + i, id->begin() + i + 1, &val))
738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      (*id)[i] = val + 'a';
748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    else
758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      (*id)[i] = 'a';
768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// These keys are allowed by all crx files (apps, extensions, themes, etc).
808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenstatic const char* kBaseCrxKeys[] = {
818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kCurrentLocale,
828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kDefaultLocale,
838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kDescription,
848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kIcons,
858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kName,
868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kPublicKey,
878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kSignature,
888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kVersion,
898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  keys::kUpdateURL
908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen};
918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool IsBaseCrxKey(const std::string& key) {
938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < arraysize(kBaseCrxKeys); ++i) {
948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (key == kBaseCrxKeys[i])
958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
1008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Constant used to represent an undefined l10n message id.
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kUndefinedMessageId = -1;
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Names of API modules that do not require a permission.
1058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kBrowserActionModuleName[] = "browserAction";
1068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kBrowserActionsModuleName[] = "browserActions";
1078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kDevToolsModuleName[] = "devtools";
1088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kExtensionModuleName[] = "extension";
1098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kI18NModuleName[] = "i18n";
1104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char kOmniboxModuleName[] = "omnibox";
1118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kPageActionModuleName[] = "pageAction";
1128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kPageActionsModuleName[] = "pageActions";
1138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char kTestModuleName[] = "test";
1148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Names of modules that can be used without listing it in the permissions
1168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// section of the manifest.
1178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char* kNonPermissionModuleNames[] = {
1188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kBrowserActionModuleName,
1198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kBrowserActionsModuleName,
1208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kDevToolsModuleName,
1218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kExtensionModuleName,
1228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kI18NModuleName,
1234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  kOmniboxModuleName,
1248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kPageActionModuleName,
1258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kPageActionsModuleName,
1268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  kTestModuleName
1278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen};
1288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst size_t kNumNonPermissionModuleNames =
1298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    arraysize(kNonPermissionModuleNames);
1308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Names of functions (within modules requiring permissions) that can be used
1328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// without asking for the module permission. In other words, functions you can
1338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// use with no permissions specified.
1348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char* kNonPermissionFunctionNames[] = {
1358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  "tabs.create",
1368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  "tabs.update"
1378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen};
1388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst size_t kNumNonPermissionFunctionNames =
1398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    arraysize(kNonPermissionFunctionNames);
1408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// A singleton object containing global data needed by the extension objects.
142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass ExtensionConfig {
1438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen public:
14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  static ExtensionConfig* GetInstance() {
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return Singleton<ExtensionConfig>::get();
1468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
1478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Extension::PermissionMessage::MessageId GetPermissionMessageId(
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const std::string& permission) {
1508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return Extension::kPermissions[permission_map_[permission]].message_id;
1518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
1528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Extension::ScriptingWhitelist* whitelist() { return &scripting_whitelist_; }
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen private:
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  friend struct DefaultSingletonTraits<ExtensionConfig>;
1578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ExtensionConfig() {
1598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t i = 0; i < Extension::kNumPermissions; ++i)
1608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      permission_map_[Extension::kPermissions[i].name] = i;
1618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  };
1628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ~ExtensionConfig() { }
1648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::map<const std::string, size_t> permission_map_;
1668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // A whitelist of extensions that can script anywhere. Do not add to this
168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // list (except in tests) without consulting the Extensions team first.
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Note: Component extensions have this right implicitly and do not need to be
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // added to this list.
171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Extension::ScriptingWhitelist scripting_whitelist_;
172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
1738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Aliased to kTabPermission for purposes of API checks, but not allowed
1758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// in the permissions field of the manifest.
1768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenstatic const char kWindowPermission[] = "windows";
1778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Rank extension locations in a way that allows
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Extension::GetHigherPriorityLocation() to compare locations.
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// An extension installed from two locations will have the location
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// with the higher rank, as returned by this function. The actual
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// integer values may change, and should never be persisted.
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint GetLocationRank(Extension::Location location) {
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const int kInvalidRank = -1;
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int rank = kInvalidRank;  // Will CHECK that rank is not kInvalidRank.
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  switch (location) {
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Component extensions can not be overriden by any other type.
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case Extension::COMPONENT:
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      rank = 6;
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Policy controlled extensions may not be overridden by any type
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // that is not part of chrome.
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case Extension::EXTERNAL_POLICY_DOWNLOAD:
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      rank = 5;
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // A developer-loaded extension should override any installed type
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // that a user can disable.
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case Extension::LOAD:
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      rank = 4;
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // The relative priority of various external sources is not important,
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // but having some order ensures deterministic behavior.
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case Extension::EXTERNAL_REGISTRY:
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      rank = 3;
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case Extension::EXTERNAL_PREF:
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      rank = 2;
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case Extension::EXTERNAL_PREF_DOWNLOAD:
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      rank = 1;
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // User installed extensions are overridden by any external type.
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case Extension::INTERNAL:
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      rank = 0;
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default:
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED() << "Need to add new extension locaton " << location;
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(rank != kInvalidRank);
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return rank;
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}  // namespace
2338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst FilePath::CharType Extension::kManifestFilename[] =
2358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    FILE_PATH_LITERAL("manifest.json");
2368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst FilePath::CharType Extension::kLocaleFolder[] =
2378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    FILE_PATH_LITERAL("_locales");
2388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst FilePath::CharType Extension::kMessagesFilename[] =
2398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    FILE_PATH_LITERAL("messages.json");
2408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#if defined(OS_WIN)
2428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kExtensionRegistryPath[] =
2438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    "Software\\Google\\Chrome\\Extensions";
2448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#endif
2458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// first 16 bytes of SHA256 hashed public key.
2478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst size_t Extension::kIdSize = 16;
2488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kMimeType[] = "application/x-chrome-extension";
2508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst int Extension::kIconSizes[] = {
2528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  EXTENSION_ICON_LARGE,
2538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  EXTENSION_ICON_MEDIUM,
2548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  EXTENSION_ICON_SMALL,
2558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  EXTENSION_ICON_SMALLISH,
2568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  EXTENSION_ICON_BITTY
2578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen};
2588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst int Extension::kPageActionIconMaxSize = 19;
2608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst int Extension::kBrowserActionIconMaxSize = 19;
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst int Extension::kSidebarIconMaxSize = 16;
2628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Explicit permissions -- permission declaration required.
2648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kBackgroundPermission[] = "background";
2658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kBookmarkPermission[] = "bookmarks";
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char Extension::kContextMenusPermission[] = "contextMenus";
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char Extension::kContentSettingsPermission[] = "contentSettings";
2688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kCookiePermission[] = "cookies";
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char Extension::kChromeosInfoPrivatePermissions[] = "chromeosInfoPrivate";
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char Extension::kDebuggerPermission[] = "debugger";
2718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kExperimentalPermission[] = "experimental";
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char Extension::kFileBrowserHandlerPermission[] = "fileBrowserHandler";
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char Extension::kFileBrowserPrivatePermission[] = "fileBrowserPrivate";
2748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kGeolocationPermission[] = "geolocation";
2758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kHistoryPermission[] = "history";
2768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kIdlePermission[] = "idle";
277731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst char Extension::kManagementPermission[] = "management";
2788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kNotificationPermission[] = "notifications";
2798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kProxyPermission[] = "proxy";
2808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kTabPermission[] = "tabs";
2818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kUnlimitedStoragePermission[] = "unlimitedStorage";
2828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kWebstorePrivatePermission[] = "webstorePrivate";
2838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// In general, all permissions should have an install message.
2858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// See ExtensionsTest.PermissionMessages for an explanation of each
2868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// exception.
2878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst Extension::Permission Extension::kPermissions[] = {
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kBackgroundPermission,           PermissionMessage::ID_NONE },
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kBookmarkPermission,             PermissionMessage::ID_BOOKMARKS },
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kChromeosInfoPrivatePermissions, PermissionMessage::ID_NONE },
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kContentSettingsPermission,      PermissionMessage::ID_NONE },
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kContextMenusPermission,         PermissionMessage::ID_NONE },
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kCookiePermission,               PermissionMessage::ID_NONE },
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kDebuggerPermission,             PermissionMessage::ID_DEBUGGER },
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kExperimentalPermission,         PermissionMessage::ID_NONE },
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kFileBrowserHandlerPermission,   PermissionMessage::ID_NONE },
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kFileBrowserPrivatePermission,   PermissionMessage::ID_NONE },
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kGeolocationPermission,          PermissionMessage::ID_GEOLOCATION },
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kIdlePermission,                 PermissionMessage::ID_NONE },
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kHistoryPermission,              PermissionMessage::ID_BROWSING_HISTORY },
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kManagementPermission,           PermissionMessage::ID_MANAGEMENT },
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kNotificationPermission,         PermissionMessage::ID_NONE },
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kProxyPermission,                PermissionMessage::ID_NONE },
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kTabPermission,                  PermissionMessage::ID_TABS },
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kUnlimitedStoragePermission,     PermissionMessage::ID_NONE },
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { kWebstorePrivatePermission,      PermissionMessage::ID_NONE }
3078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen};
3088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst size_t Extension::kNumPermissions =
3098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    arraysize(Extension::kPermissions);
3108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
3118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char* const Extension::kHostedAppPermissionNames[] = {
3128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Extension::kBackgroundPermission,
3138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Extension::kGeolocationPermission,
3148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Extension::kNotificationPermission,
3158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Extension::kUnlimitedStoragePermission,
3168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Extension::kWebstorePrivatePermission,
3178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen};
3188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst size_t Extension::kNumHostedAppPermissions =
3198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    arraysize(Extension::kHostedAppPermissionNames);
3208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char* const Extension::kComponentPrivatePermissionNames[] = {
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Extension::kFileBrowserPrivatePermission,
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Extension::kWebstorePrivatePermission,
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Extension::kChromeosInfoPrivatePermissions,
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst size_t Extension::kNumComponentPrivatePermissions =
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    arraysize(Extension::kComponentPrivatePermissionNames);
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
3298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// We purposefully don't put this into kPermissionNames.
3308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage";
3318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
332201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst int Extension::kValidWebExtentSchemes =
333201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
334201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst int Extension::kValidHostPermissionSchemes =
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UserScript::kValidUserScriptSchemes | URLPattern::SCHEME_CHROMEUI;
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// PermissionMessage
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtension::PermissionMessage Extension::PermissionMessage::CreateFromMessageId(
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Extension::PermissionMessage::MessageId message_id) {
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (message_id <= ID_NONE)
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return PermissionMessage(message_id, string16());
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  string16 message = l10n_util::GetStringUTF16(kMessageIds[message_id]);
350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return PermissionMessage(message_id, message);
351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtension::PermissionMessage Extension::PermissionMessage::CreateFromHostList(
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::vector<std::string> hosts) {
356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(hosts.size() > 0);
357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MessageId message_id;
359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  string16 message;
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  switch (hosts.size()) {
361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case 1:
362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message_id = ID_HOSTS_1;
363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           UTF8ToUTF16(hosts[0]));
365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case 2:
367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message_id = ID_HOSTS_2;
368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           UTF8ToUTF16(hosts[0]),
370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           UTF8ToUTF16(hosts[1]));
371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case 3:
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message_id = ID_HOSTS_3;
374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           UTF8ToUTF16(hosts[0]),
376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           UTF8ToUTF16(hosts[1]),
377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           UTF8ToUTF16(hosts[2]));
378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default:
380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message_id = ID_HOSTS_4_OR_MORE;
381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message = l10n_util::GetStringFUTF16(
382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          kMessageIds[message_id],
383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          UTF8ToUTF16(hosts[0]),
384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          UTF8ToUTF16(hosts[1]),
385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::IntToString16(hosts.size() - 2));
386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return PermissionMessage(message_id, message);
390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtension::PermissionMessage::PermissionMessage(
393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Extension::PermissionMessage::MessageId message_id, string16 message)
394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : message_id_(message_id),
395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      message_(message) {
396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int Extension::PermissionMessage::kMessageIds[] = {
399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  kUndefinedMessageId,  // "unknown"
400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  kUndefinedMessageId,  // "none"
401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS,
402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION,
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_TABS,
405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT,
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_DEBUGGER,
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_1_HOST,
408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS,
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS
413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
414201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick//
416513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Extension
417731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick//
418731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
419513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
420513209b27ff55e2841eac0e4120199c23acce758Ben Murdochscoped_refptr<Extension> Extension::Create(const FilePath& path,
421513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                           Location location,
422513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                           const DictionaryValue& value,
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           int flags,
424513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                           std::string* error) {
425513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<Extension> extension = new Extension(path, location);
426dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension->InitFromValue(value, flags, error))
428513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return NULL;
429513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return extension;
430731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
431731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
432201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochnamespace {
433201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst char* kGalleryUpdateHttpUrl =
434201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://clients2.google.com/service/update2/crx";
435201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst char* kGalleryUpdateHttpsUrl =
436201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "https://clients2.google.com/service/update2/crx";
437201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}  // namespace
438201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
439201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// static
440201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochGURL Extension::GalleryUpdateUrl(bool secure) {
441201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  CommandLine* cmdline = CommandLine::ForCurrentProcess();
442201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cmdline->HasSwitch(switches::kAppsGalleryUpdateURL))
443201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return GURL(cmdline->GetSwitchValueASCII(switches::kAppsGalleryUpdateURL));
444201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  else
445201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return GURL(secure ? kGalleryUpdateHttpsUrl : kGalleryUpdateHttpUrl);
446201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
447201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
4488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtension::Location Extension::GetHigherPriorityLocation(
450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Extension::Location loc1, Extension::Location loc2) {
451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (loc1 == loc2)
452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return loc1;
453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int loc1_rank = GetLocationRank(loc1);
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int loc2_rank = GetLocationRank(loc2);
456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If two different locations have the same rank, then we can not
458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // deterministicly choose a location.
459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(loc1_rank != loc2_rank);
460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Lowest rank has highest priority.
462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return (loc1_rank > loc2_rank ? loc1 : loc2 );
463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtension::PermissionMessage::MessageId Extension::GetPermissionMessageId(
467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& permission) {
46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return ExtensionConfig::GetInstance()->GetPermissionMessageId(permission);
4698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
4708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtension::PermissionMessages Extension::GetPermissionMessages() const {
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PermissionMessages messages;
473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!plugins().empty()) {
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    messages.push_back(PermissionMessage::CreateFromMessageId(
475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        PermissionMessage::ID_FULL_ACCESS));
4768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return messages;
4778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
4788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (HasEffectiveAccessToAllHosts()) {
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    messages.push_back(PermissionMessage::CreateFromMessageId(
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        PermissionMessage::ID_HOSTS_ALL));
482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<std::string> hosts = GetDistinctHostsForDisplay(
484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        GetEffectiveHostPermissions().patterns());
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!hosts.empty())
486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      messages.push_back(PermissionMessage::CreateFromHostList(hosts));
487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
4888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::set<PermissionMessage> simple_msgs = GetSimplePermissionMessages();
4908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end());
4918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
4928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return messages;
4938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
4948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::vector<string16> Extension::GetPermissionMessageStrings() const {
496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<string16> messages;
497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PermissionMessages permissions = GetPermissionMessages();
498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (PermissionMessages::const_iterator i = permissions.begin();
499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       i != permissions.end(); ++i)
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    messages.push_back(i->message());
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return messages;
502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::set<Extension::PermissionMessage>
505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Extension::GetSimplePermissionMessages() const {
506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::set<PermissionMessage> messages;
507731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::set<std::string>::const_iterator i;
508731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (i = api_permissions().begin(); i != api_permissions().end(); ++i) {
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PermissionMessage::MessageId message_id = GetPermissionMessageId(*i);
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (message_id > PermissionMessage::ID_NONE)
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      messages.insert(PermissionMessage::CreateFromMessageId(message_id));
5138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
5148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return messages;
5158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
5168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
517201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// static
518201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::vector<std::string> Extension::GetDistinctHostsForDisplay(
519201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const URLPatternList& list) {
520201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return GetDistinctHosts(list, true);
5218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
5228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
5238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
524201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool Extension::IsElevatedHostList(
525201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const URLPatternList& old_list, const URLPatternList& new_list) {
526201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TODO(jstritar): This is overly conservative with respect to subdomains.
527201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // For example, going from *.google.com to www.google.com will be
528201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // considered an elevation, even though it is not (http://crbug.com/65337).
529201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
530201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::vector<std::string> new_hosts = GetDistinctHosts(new_list, false);
531201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::vector<std::string> old_hosts = GetDistinctHosts(old_list, false);
5328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
533201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end());
534201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end());
535201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::set<std::string> new_hosts_only;
536201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
537201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::set_difference(new_hosts_set.begin(), new_hosts_set.end(),
538201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      old_hosts_set.begin(), old_hosts_set.end(),
539201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      std::inserter(new_hosts_only, new_hosts_only.begin()));
540201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
541dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return !new_hosts_only.empty();
542201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
543201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Helper for GetDistinctHosts(): com > net > org > everything else.
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic bool RcdBetterThan(const std::string& a, const std::string& b) {
546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (a == b)
547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (a == "com")
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (a == "net")
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return b != "com";
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (a == "org")
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return b != "com" && b != "net";
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return false;
555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// static
558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::vector<std::string> Extension::GetDistinctHosts(
559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const URLPatternList& host_patterns, bool include_rcd) {
560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Use a vector to preserve order (also faster than a map on small sets).
561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Each item is a host split into two parts: host without RCDs and
562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // current best RCD.
563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  typedef std::vector<std::pair<std::string, std::string> > HostVector;
564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  HostVector hosts_best_rcd;
5658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < host_patterns.size(); ++i) {
566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string host = host_patterns[i].host();
567201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Add the subdomain wildcard back to the host, if necessary.
569201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (host_patterns[i].match_subdomains())
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      host = "*." + host;
571201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If the host has an RCD, split it off so we can detect duplicates.
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string rcd;
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength(
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        host, false);
576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (reg_len && reg_len != std::string::npos) {
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (include_rcd)  // else leave rcd empty
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        rcd = host.substr(host.size() - reg_len);
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      host = host.substr(0, host.size() - reg_len);
580731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Check if we've already seen this host.
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    HostVector::iterator it = hosts_best_rcd.begin();
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (; it != hosts_best_rcd.end(); ++it) {
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (it->first == host)
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If this host was found, replace the RCD if this one is better.
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (it != hosts_best_rcd.end()) {
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (include_rcd && RcdBetterThan(rcd, it->second))
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        it->second = rcd;
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {  // Previously unseen host, append it.
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      hosts_best_rcd.push_back(std::make_pair(host, rcd));
5948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
5958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
5968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Build up the final vector by concatenating hosts and RCDs.
598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<std::string> distinct_hosts;
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (HostVector::iterator it = hosts_best_rcd.begin();
600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       it != hosts_best_rcd.end(); ++it)
601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    distinct_hosts.push_back(it->first + it->second);
6028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return distinct_hosts;
6038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
6048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
605731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickFilePath Extension::MaybeNormalizePath(const FilePath& path) {
606731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if defined(OS_WIN)
607731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Normalize any drive letter to upper-case. We do this for consistency with
608731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // net_utils::FilePathToFileURL(), which does the same thing, to make string
609731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // comparisons simpler.
610731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::wstring path_str = path.value();
611731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (path_str.size() >= 2 && path_str[0] >= L'a' && path_str[0] <= L'z' &&
612731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      path_str[1] == ':')
613731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    path_str[0] += ('A' - 'a');
614731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
615731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return FilePath(path_str);
616731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#else
617731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return path;
618731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif
619731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
620731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
6218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
6228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::IsHostedAppPermission(const std::string& str) {
6238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < Extension::kNumHostedAppPermissions; ++i) {
6248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (str == Extension::kHostedAppPermissionNames[i]) {
6258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
6268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
6278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
6288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
6298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
6308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst std::string Extension::VersionString() const {
632731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return version()->GetString();
6338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
6348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
6368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::IsExtension(const FilePath& file_name) {
6378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return file_name.MatchesExtension(chrome::kExtensionFileExtension);
6388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
6398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
6418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::IdIsValid(const std::string& id) {
6428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Verify that the id is legal.
6438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (id.size() != (kIdSize * 2))
6448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
6458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // We only support lowercase IDs, because IDs can be used as URL components
6478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // (where GURL will lowercase it).
6488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string temp = StringToLowerASCII(id);
6498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < temp.size(); i++)
6508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (temp[i] < 'a' || temp[i] > 'p')
6518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
6528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
6548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
6558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
657731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string Extension::GenerateIdForPath(const FilePath& path) {
658731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  FilePath new_path = Extension::MaybeNormalizePath(path);
659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string path_bytes =
660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::string(reinterpret_cast<const char*>(new_path.value().data()),
661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                  new_path.value().size() * sizeof(FilePath::CharType));
662731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string id;
663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!GenerateId(path_bytes, &id))
664731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return "";
665731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return id;
666731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
667731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
66821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenExtension::Type Extension::GetType() const {
669731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (is_theme())
670731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return TYPE_THEME;
671731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (converted_from_user_script())
672731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return TYPE_USER_SCRIPT;
673731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (is_hosted_app())
674731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return TYPE_HOSTED_APP;
675731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (is_packaged_app())
676731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return TYPE_PACKAGED_APP;
677731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return TYPE_EXTENSION;
678731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
679731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
680731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
6818ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenGURL Extension::GetResourceURL(const GURL& extension_url,
6828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                               const std::string& relative_path) {
6838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DCHECK(extension_url.SchemeIs(chrome::kExtensionScheme));
6848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DCHECK_EQ("/", extension_url.path());
6858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  GURL ret_val = GURL(extension_url.spec() + relative_path);
6878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DCHECK(StartsWithASCII(ret_val.spec(), extension_url.spec(), false));
6888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return ret_val;
6908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
6918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::GenerateId(const std::string& input, std::string* output) {
6938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  CHECK(output);
6948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  uint8 hash[Extension::kIdSize];
695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::SHA256HashString(input, hash, sizeof(hash));
6968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash)));
6978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  ConvertHexadecimalToIDAlphabet(output);
6988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
6998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
7008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
7018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
7028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Helper method that loads a UserScript object from a dictionary in the
7038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// content_script list of the manifest.
7048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     int definition_index,
706ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     int flags,
707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     std::string* error,
7088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                     UserScript* result) {
709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // When strict error checks are enabled, make URL pattern parsing strict.
710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  URLPattern::ParseOption parse_strictness =
711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (flags & STRICT_ERROR_CHECKS ? URLPattern::PARSE_STRICT
712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   : URLPattern::PARSE_LENIENT);
713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // run_at
7158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (content_script->HasKey(keys::kRunAt)) {
7168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string run_location;
7178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!content_script->GetString(keys::kRunAt, &run_location)) {
7188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidRunAt,
7198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          base::IntToString(definition_index));
7208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
7218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
7228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
7238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (run_location == values::kRunAtDocumentStart) {
7248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      result->set_run_location(UserScript::DOCUMENT_START);
7258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else if (run_location == values::kRunAtDocumentEnd) {
7268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      result->set_run_location(UserScript::DOCUMENT_END);
7278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else if (run_location == values::kRunAtDocumentIdle) {
7288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      result->set_run_location(UserScript::DOCUMENT_IDLE);
7298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else {
7308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidRunAt,
7318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          base::IntToString(definition_index));
7328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
7338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
7348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
7358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
7368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // all frames
7378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (content_script->HasKey(keys::kAllFrames)) {
7388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    bool all_frames = false;
7398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!content_script->GetBoolean(keys::kAllFrames, &all_frames)) {
7408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
7418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            errors::kInvalidAllFrames, base::IntToString(definition_index));
7428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
7438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
7448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    result->set_match_all_frames(all_frames);
7458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
7468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
7478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // matches
7488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  ListValue* matches = NULL;
7498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!content_script->GetList(keys::kMatches, &matches)) {
7508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidMatches,
7518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        base::IntToString(definition_index));
7528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
7538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
7548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
7558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (matches->GetSize() == 0) {
7568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidMatchCount,
7578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        base::IntToString(definition_index));
7588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
7598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
7608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t j = 0; j < matches->GetSize(); ++j) {
7618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string match_str;
7628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!matches->GetString(j, &match_str)) {
763dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
764dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          errors::kInvalidMatch,
765dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::IntToString(definition_index),
766dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::IntToString(j),
767dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          errors::kExpectString);
7688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
7698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
7708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
771513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    URLPattern pattern(UserScript::kValidUserScriptSchemes);
772731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (CanExecuteScriptEverywhere())
773513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      pattern.set_valid_schemes(URLPattern::SCHEME_ALL);
774513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
775dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    URLPattern::ParseResult parse_result = pattern.Parse(match_str,
776dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                         parse_strictness);
777dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (parse_result != URLPattern::PARSE_SUCCESS) {
778dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
779dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          errors::kInvalidMatch,
780dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::IntToString(definition_index),
781dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::IntToString(j),
782dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          URLPattern::GetParseResultString(parse_result));
7838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
7848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
7858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (pattern.MatchesScheme(chrome::kFileScheme) &&
787ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        !CanExecuteScriptEverywhere()) {
788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      wants_file_access_ = true;
789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!(flags & ALLOW_FILE_ACCESS))
790ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        pattern.set_valid_schemes(
791ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
792ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
793ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    result->add_url_pattern(pattern);
7958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
7968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
7978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // include/exclude globs (mostly for Greasemonkey compatibility)
7988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!LoadGlobsHelper(content_script, definition_index, keys::kIncludeGlobs,
7998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                       error, &UserScript::add_glob, result)) {
8008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
8018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!LoadGlobsHelper(content_script, definition_index, keys::kExcludeGlobs,
8048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                       error, &UserScript::add_exclude_glob, result)) {
8058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
8068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // js and css keys
8098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  ListValue* js = NULL;
8108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (content_script->HasKey(keys::kJs) &&
8118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      !content_script->GetList(keys::kJs, &js)) {
8128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidJsList,
8138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        base::IntToString(definition_index));
8148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
8158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  ListValue* css = NULL;
8188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (content_script->HasKey(keys::kCss) &&
8198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      !content_script->GetList(keys::kCss, &css)) {
8208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidCssList,
8218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        base::IntToString(definition_index));
8228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
8238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // The manifest needs to have at least one js or css user script definition.
8268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (((js ? js->GetSize() : 0) + (css ? css->GetSize() : 0)) == 0) {
8278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kMissingFile,
8288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        base::IntToString(definition_index));
8298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
8308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (js) {
8338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t script_index = 0; script_index < js->GetSize();
8348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         ++script_index) {
8358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      Value* value;
8368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string relative;
8378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!js->Get(script_index, &value) || !value->GetAsString(&relative)) {
8388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidJs,
8398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            base::IntToString(definition_index),
8408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            base::IntToString(script_index));
8418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
8428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
8438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      GURL url = GetResourceURL(relative);
8448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      ExtensionResource resource = GetResource(relative);
8458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      result->js_scripts().push_back(UserScript::File(
8468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          resource.extension_root(), resource.relative_path(), url));
8478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
8488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (css) {
8518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t script_index = 0; script_index < css->GetSize();
8528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         ++script_index) {
8538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      Value* value;
8548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string relative;
8558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!css->Get(script_index, &value) || !value->GetAsString(&relative)) {
8568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidCss,
8578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            base::IntToString(definition_index),
8588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            base::IntToString(script_index));
8598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
8608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
8618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      GURL url = GetResourceURL(relative);
8628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      ExtensionResource resource = GetResource(relative);
8638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      result->css_scripts().push_back(UserScript::File(
8648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          resource.extension_root(), resource.relative_path(), url));
8658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
8668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
8698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
8708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::LoadGlobsHelper(
8728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    const DictionaryValue* content_script,
8738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    int content_script_index,
8748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    const char* globs_property_name,
8758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string* error,
8768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    void(UserScript::*add_method)(const std::string& glob),
8778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    UserScript *instance) {
8788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!content_script->HasKey(globs_property_name))
8798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;  // they are optional
8808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  ListValue* list = NULL;
8828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!content_script->GetList(globs_property_name, &list)) {
8838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidGlobList,
8848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        base::IntToString(content_script_index),
8858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        globs_property_name);
8868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
8878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
8888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < list->GetSize(); ++i) {
8908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string glob;
8918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!list->GetString(i, &glob)) {
8928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidGlob,
8938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          base::IntToString(content_script_index),
8948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          globs_property_name,
8958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          base::IntToString(i));
8968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
8978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
8988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
8998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    (instance->*add_method)(glob);
9008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
9018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
9038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
9048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9058ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenExtensionAction* Extension::LoadExtensionActionHelper(
9068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    const DictionaryValue* extension_action, std::string* error) {
9078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  scoped_ptr<ExtensionAction> result(new ExtensionAction());
9088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  result->set_extension_id(id());
9098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Page actions are hidden by default, and browser actions ignore
9118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // visibility.
9128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  result->SetIsVisible(ExtensionAction::kDefaultTabId, false);
9138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // TODO(EXTENSIONS_DEPRECATED): icons list is obsolete.
9158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  ListValue* icons = NULL;
9168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (extension_action->HasKey(keys::kPageActionIcons) &&
9178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      extension_action->GetList(keys::kPageActionIcons, &icons)) {
9188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (ListValue::const_iterator iter = icons->begin();
9198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         iter != icons->end(); ++iter) {
9208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string path;
9218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!(*iter)->GetAsString(&path) || path.empty()) {
9228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = errors::kInvalidPageActionIconPath;
9238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return NULL;
9248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
9258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      result->icon_paths()->push_back(path);
9278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
9288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
9298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // TODO(EXTENSIONS_DEPRECATED): Read the page action |id| (optional).
9318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string id;
9328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (extension_action->HasKey(keys::kPageActionId)) {
9338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!extension_action->GetString(keys::kPageActionId, &id)) {
9348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageActionId;
9358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return NULL;
9368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
9378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    result->set_id(id);
9388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
9398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string default_icon;
9418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Read the page action |default_icon| (optional).
9428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (extension_action->HasKey(keys::kPageActionDefaultIcon)) {
9438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!extension_action->GetString(keys::kPageActionDefaultIcon,
9448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                     &default_icon) ||
9458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        default_icon.empty()) {
9468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageActionIconPath;
9478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return NULL;
9488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
9498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    result->set_default_icon_path(default_icon);
9508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
9518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Read the page action title from |default_title| if present, |name| if not
9538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // (both optional).
9548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string title;
9558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (extension_action->HasKey(keys::kPageActionDefaultTitle)) {
9568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!extension_action->GetString(keys::kPageActionDefaultTitle, &title)) {
9578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageActionDefaultTitle;
9588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return NULL;
9598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
9608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  } else if (extension_action->HasKey(keys::kName)) {
9618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!extension_action->GetString(keys::kName, &title)) {
9628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageActionName;
9638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return NULL;
9648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
9658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
9668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  result->SetTitle(ExtensionAction::kDefaultTabId, title);
9678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Read the action's |popup| (optional).
9698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  const char* popup_key = NULL;
9708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (extension_action->HasKey(keys::kPageActionDefaultPopup))
9718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    popup_key = keys::kPageActionDefaultPopup;
9728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // For backward compatibility, alias old key "popup" to new
9748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // key "default_popup".
9758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (extension_action->HasKey(keys::kPageActionPopup)) {
9768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (popup_key) {
9778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
9788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          errors::kInvalidPageActionOldAndNewKeys,
9798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          keys::kPageActionDefaultPopup,
9808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          keys::kPageActionPopup);
9818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return NULL;
9828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
9838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    popup_key = keys::kPageActionPopup;
9848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
9858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (popup_key) {
9878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    DictionaryValue* popup = NULL;
9888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string url_str;
9898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
9908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (extension_action->GetString(popup_key, &url_str)) {
9918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // On success, |url_str| is set.  Nothing else to do.
9928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else if (extension_action->GetDictionary(popup_key, &popup)) {
9938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // TODO(EXTENSIONS_DEPRECATED): popup is now a string only.
9948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Support the old dictionary format for backward compatibility.
9958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!popup->GetString(keys::kPageActionPopupPath, &url_str)) {
9968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
9978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            errors::kInvalidPageActionPopupPath, "<missing>");
9988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return NULL;
9998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
10008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else {
10018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageActionPopup;
10028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return NULL;
10038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
10048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
10058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!url_str.empty()) {
10068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // An empty string is treated as having no popup.
10078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      GURL url = GetResourceURL(url_str);
10088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!url.is_valid()) {
10098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
10108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            errors::kInvalidPageActionPopupPath, url_str);
10118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return NULL;
10128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
10138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      result->SetPopupUrl(ExtensionAction::kDefaultTabId, url);
10148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else {
10158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      DCHECK(!result->HasPopup(ExtensionAction::kDefaultTabId))
10168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          << "Shouldn't be posible for the popup to be set.";
10178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
10188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
10198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
10208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return result.release();
10218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
10228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1023ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtension::FileBrowserHandlerList* Extension::LoadFileBrowserHandlers(
1024ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ListValue* extension_actions, std::string* error) {
1025ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<FileBrowserHandlerList> result(
1026ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new FileBrowserHandlerList());
1027ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ListValue::const_iterator iter = extension_actions->begin();
1028ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != extension_actions->end();
1029ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ++iter) {
1030ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) {
1031ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = errors::kInvalidFileBrowserHandler;
1032ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return NULL;
1033ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1034ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    scoped_ptr<FileBrowserHandler> action(
1035ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        LoadFileBrowserHandler(
1036ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            reinterpret_cast<DictionaryValue*>(*iter), error));
1037ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!action.get())
1038ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return NULL;  // Failed to parse file browser action definition.
1039ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result->push_back(linked_ptr<FileBrowserHandler>(action.release()));
1040ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1041ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return result.release();
1042ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1043ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1044ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileBrowserHandler* Extension::LoadFileBrowserHandler(
1045ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const DictionaryValue* file_browser_handler, std::string* error) {
1046ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<FileBrowserHandler> result(
1047ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new FileBrowserHandler());
1048ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->set_extension_id(id());
1049ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1050ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string id;
1051ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Read the file action |id| (mandatory).
1052ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!file_browser_handler->HasKey(keys::kPageActionId) ||
1053ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !file_browser_handler->GetString(keys::kPageActionId, &id)) {
1054ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *error = errors::kInvalidPageActionId;
1055ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return NULL;
1056ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1057ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->set_id(id);
1058ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1059ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Read the page action title from |default_title| (mandatory).
1060ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string title;
1061ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!file_browser_handler->HasKey(keys::kPageActionDefaultTitle) ||
1062ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !file_browser_handler->GetString(keys::kPageActionDefaultTitle, &title)) {
1063ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *error = errors::kInvalidPageActionDefaultTitle;
1064ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return NULL;
1065ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1066ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->set_title(title);
1067ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1068ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Initialize file filters (mandatory).
1069ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* list_value = NULL;
1070ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!file_browser_handler->HasKey(keys::kFileFilters) ||
1071ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !file_browser_handler->GetList(keys::kFileFilters, &list_value) ||
1072ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      list_value->empty()) {
1073ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *error = errors::kInvalidFileFiltersList;
1074ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return NULL;
1075ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1076ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < list_value->GetSize(); ++i) {
1077ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string filter;
1078ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!list_value->GetString(i, &filter)) {
1079ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1080ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          errors::kInvalidFileFilterValue, base::IntToString(i));
1081ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return NULL;
1082ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    URLPattern pattern(URLPattern::SCHEME_FILESYSTEM);
1084ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (URLPattern::PARSE_SUCCESS != pattern.Parse(filter,
1085ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                   URLPattern::PARSE_STRICT)) {
1086ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1087ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          errors::kInvalidURLPatternError, filter);
1088ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return NULL;
1089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1090ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result->AddPattern(pattern);
1091ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1092ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1093ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string default_icon;
1094ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Read the file browser action |default_icon| (optional).
1095ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) {
1096ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!file_browser_handler->GetString(
1097ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            keys::kPageActionDefaultIcon,&default_icon) ||
1098ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        default_icon.empty()) {
1099ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = errors::kInvalidPageActionIconPath;
1100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return NULL;
1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result->set_icon_path(default_icon);
1103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return result.release();
1106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
110872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionSidebarDefaults* Extension::LoadExtensionSidebarDefaults(
110972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const DictionaryValue* extension_sidebar, std::string* error) {
111072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<ExtensionSidebarDefaults> result(new ExtensionSidebarDefaults());
111172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
111272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string default_icon;
111372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Read sidebar's |default_icon| (optional).
111472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (extension_sidebar->HasKey(keys::kSidebarDefaultIcon)) {
111572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!extension_sidebar->GetString(keys::kSidebarDefaultIcon,
111672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                      &default_icon) ||
111772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        default_icon.empty()) {
111872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      *error = errors::kInvalidSidebarDefaultIconPath;
111972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return NULL;
112072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
112172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    result->set_default_icon_path(default_icon);
112272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
112372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
112472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Read sidebar's |default_title| (optional).
112572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  string16 default_title;
112672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (extension_sidebar->HasKey(keys::kSidebarDefaultTitle)) {
112772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!extension_sidebar->GetString(keys::kSidebarDefaultTitle,
112872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                      &default_title)) {
112972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      *error = errors::kInvalidSidebarDefaultTitle;
113072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return NULL;
113172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
113272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
113372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  result->set_default_title(default_title);
113472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
113572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Read sidebar's |default_page| (optional).
113672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string default_page;
113772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (extension_sidebar->HasKey(keys::kSidebarDefaultPage)) {
113872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!extension_sidebar->GetString(keys::kSidebarDefaultPage,
113972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                      &default_page) ||
114072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        default_page.empty()) {
114172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      *error = errors::kInvalidSidebarDefaultPage;
114272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return NULL;
114372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
114472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    GURL url = extension_sidebar_utils::ResolveRelativePath(
114572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        default_page, this, error);
114672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!url.is_valid())
114772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return NULL;
114872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    result->set_default_page(url);
114972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
115072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
115172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return result.release();
115272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
115372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1154513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool Extension::ContainsNonThemeKeys(const DictionaryValue& source) const {
11558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (DictionaryValue::key_iterator key = source.begin_keys();
11568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen       key != source.end_keys(); ++key) {
11578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!IsBaseCrxKey(*key) && *key != keys::kTheme)
11588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
11598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
11608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
11618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
11628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
11638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::LoadIsApp(const DictionaryValue* manifest,
11648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                          std::string* error) {
1165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (manifest->HasKey(keys::kApp))
1166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    is_app_ = true;
11678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
11688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
11698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
11708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
11718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::LoadExtent(const DictionaryValue* manifest,
11728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                           const char* key,
11738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                           ExtensionExtent* extent,
11748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                           const char* list_error,
11758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                           const char* value_error,
1176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           URLPattern::ParseOption parse_strictness,
11778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                           std::string* error) {
11788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Value* temp = NULL;
11798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!manifest->Get(key, &temp))
11808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;
11818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
11828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (temp->GetType() != Value::TYPE_LIST) {
11838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = list_error;
11848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
11858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
11868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
11878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  ListValue* pattern_list = static_cast<ListValue*>(temp);
11888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < pattern_list->GetSize(); ++i) {
11898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string pattern_string;
11908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!pattern_list->GetString(i, &pattern_string)) {
11918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(value_error,
1192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                       base::UintToString(i),
1193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                       errors::kExpectString);
11948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
11958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
11968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
11978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    URLPattern pattern(kValidWebExtentSchemes);
1198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    URLPattern::ParseResult parse_result = pattern.Parse(pattern_string,
1199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                         parse_strictness);
1200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (parse_result == URLPattern::PARSE_ERROR_EMPTY_PATH) {
1201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      pattern_string += "/";
1202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      parse_result = pattern.Parse(pattern_string, parse_strictness);
1203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
1204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (parse_result != URLPattern::PARSE_SUCCESS) {
1206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          value_error,
1208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::UintToString(i),
1209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          URLPattern::GetParseResultString(parse_result));
12108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
12118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
12128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Do not allow authors to claim "<all_urls>".
1214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (pattern.match_all_urls()) {
1215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          value_error,
1217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::UintToString(i),
1218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          errors::kCannotClaimAllURLsInExtent);
1219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
1220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
1221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Do not allow authors to claim "*" for host.
1223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (pattern.host().empty()) {
1224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          value_error,
1226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::UintToString(i),
1227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          errors::kCannotClaimAllHostsInExtent);
1228731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return false;
1229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
1230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
12318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // We do not allow authors to put wildcards in their paths. Instead, we
12328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // imply one at the end.
12338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (pattern.path().find('*') != std::string::npos) {
1234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          value_error,
1236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::UintToString(i),
1237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          errors::kNoWildCardsInPaths);
12388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
12398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
1240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    pattern.SetPath(pattern.path() + '*');
12418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
12428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    extent->AddPattern(pattern);
12438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
12448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
12458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
12468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
12478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
12488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::LoadLaunchURL(const DictionaryValue* manifest,
12498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                              std::string* error) {
12508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Value* temp = NULL;
12518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
12528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // launch URL can be either local (to chrome-extension:// root) or an absolute
12538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // web URL.
12548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (manifest->Get(keys::kLaunchLocalPath, &temp)) {
12558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (manifest->Get(keys::kLaunchWebURL, NULL)) {
12568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kLaunchPathAndURLAreExclusive;
12578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
12588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
12598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
12608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string launch_path;
12618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!temp->GetAsString(&launch_path)) {
12628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchLocalPath;
12638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
12648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
12658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
12668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // Ensure the launch path is a valid relative URL.
1267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    GURL resolved = url().Resolve(launch_path);
1268731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (!resolved.is_valid() || resolved.GetOrigin() != url()) {
12698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchLocalPath;
12708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
12718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
12728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    launch_local_path_ = launch_path;
12748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  } else if (manifest->Get(keys::kLaunchWebURL, &temp)) {
12758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string launch_url;
12768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!temp->GetAsString(&launch_url)) {
12778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchWebURL;
12788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
12798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
12808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Ensure the launch URL is a valid absolute URL and web extent scheme.
1282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL url(launch_url);
1283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    URLPattern pattern(kValidWebExtentSchemes);
1284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!url.is_valid() || !pattern.SetScheme(url.scheme())) {
12858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchWebURL;
12868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
12878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
12888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1289513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    launch_web_url_ = launch_url;
1290731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else if (is_app()) {
12918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = errors::kLaunchURLRequired;
12928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
12938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
12948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
12958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // If there is no extent, we default the extent based on the launch URL.
1296731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (web_extent().is_empty() && !launch_web_url().empty()) {
1297731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    GURL launch_url(launch_web_url());
12988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    URLPattern pattern(kValidWebExtentSchemes);
12998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!pattern.SetScheme("*")) {
13008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchWebURL;
13018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
13028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
13038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    pattern.set_host(launch_url.host());
1304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    pattern.SetPath("/*");
1305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    extent_.AddPattern(pattern);
1306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
1307731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1308731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // In order for the --apps-gallery-url switch to work with the gallery
1309731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // process isolation, we must insert any provided value into the component
1310731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // app's launch url and web extent.
1311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (id() == extension_misc::kWebStoreAppId) {
1312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string gallery_url_str = CommandLine::ForCurrentProcess()->
1313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        GetSwitchValueASCII(switches::kAppsGalleryURL);
1314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Empty string means option was not used.
1316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!gallery_url_str.empty()) {
1317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      GURL gallery_url(gallery_url_str);
1318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!gallery_url.is_valid()) {
1319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(WARNING) << "Invalid url given in switch "
1320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                     << switches::kAppsGalleryURL;
1321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else {
1322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (gallery_url.has_port()) {
1323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          LOG(WARNING) << "URLs passed to switch " << switches::kAppsGalleryURL
1324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       << " should not contain a port.  Removing it.";
1325731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          GURL::Replacements remove_port;
1327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          remove_port.ClearPort();
1328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          gallery_url = gallery_url.ReplaceComponents(remove_port);
1329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
1330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        launch_web_url_ = gallery_url.spec();
1332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        URLPattern pattern(kValidWebExtentSchemes);
1334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        pattern.Parse(gallery_url.spec(), URLPattern::PARSE_STRICT);
1335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        pattern.SetPath(pattern.path() + '*');
1336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        extent_.AddPattern(pattern);
1337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
1338731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
13398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
13408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
13418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
13428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
13438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
13448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::LoadLaunchContainer(const DictionaryValue* manifest,
13458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                    std::string* error) {
13468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  Value* temp = NULL;
13478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!manifest->Get(keys::kLaunchContainer, &temp))
13488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;
13498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
13508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string launch_container_string;
13518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!temp->GetAsString(&launch_container_string)) {
13528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = errors::kInvalidLaunchContainer;
13538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
13548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
13558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
13568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (launch_container_string == values::kLaunchContainerPanel) {
1357513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    launch_container_ = extension_misc::LAUNCH_PANEL;
13588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  } else if (launch_container_string == values::kLaunchContainerTab) {
1359513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    launch_container_ = extension_misc::LAUNCH_TAB;
13608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  } else {
13618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = errors::kInvalidLaunchContainer;
13628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
13638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
13648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
13658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Validate the container width if present.
13668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (manifest->Get(keys::kLaunchWidth, &temp)) {
1367731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (launch_container() != extension_misc::LAUNCH_PANEL &&
1368731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        launch_container() != extension_misc::LAUNCH_WINDOW) {
13698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchWidthContainer;
13708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
13718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
1372513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!temp->GetAsInteger(&launch_width_) ||
1373513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        launch_width_ < 0) {
1374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      launch_width_ = 0;
13758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchWidth;
13768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
13778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
13788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
13798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
13808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Validate container height if present.
13818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (manifest->Get(keys::kLaunchHeight, &temp)) {
1382731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (launch_container() != extension_misc::LAUNCH_PANEL &&
1383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        launch_container() != extension_misc::LAUNCH_WINDOW) {
13848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchHeightContainer;
13858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
13868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
1387513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!temp->GetAsInteger(&launch_height_) || launch_height_ < 0) {
1388513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      launch_height_ = 0;
13898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidLaunchHeight;
13908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
13918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
13928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
13938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
13948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
13958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
13968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool Extension::LoadAppIsolation(const DictionaryValue* manifest,
1398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 std::string* error) {
1399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Only parse app isolation features if this switch is present.
1400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!CommandLine::ForCurrentProcess()->HasSwitch(
1401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          switches::kEnableExperimentalAppManifests))
1402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
1403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Value* temp = NULL;
1405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!manifest->Get(keys::kIsolation, &temp))
1406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
1407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (temp->GetType() != Value::TYPE_LIST) {
1409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *error = errors::kInvalidIsolation;
1410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
1411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* isolation_list = static_cast<ListValue*>(temp);
1414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < isolation_list->GetSize(); ++i) {
1415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string isolation_string;
1416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!isolation_list->GetString(i, &isolation_string)) {
1417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          errors::kInvalidIsolationValue,
1419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::UintToString(i));
1420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
1421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Check for isolated storage.
1424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (isolation_string == values::kIsolatedStorage) {
1425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      is_storage_isolated_ = true;
1426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
1427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      LOG(WARNING) << "Did not recognize isolation type: "
1428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                   << isolation_string;
1429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
1432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
14348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::EnsureNotHybridApp(const DictionaryValue* manifest,
14358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                   std::string* error) {
14368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (web_extent().is_empty())
14378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;
14388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
14398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (DictionaryValue::key_iterator key = manifest->begin_keys();
14408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen       key != manifest->end_keys(); ++key) {
14418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!IsBaseCrxKey(*key) &&
14428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *key != keys::kApp &&
14438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *key != keys::kPermissions &&
1444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *key != keys::kOptionsPage &&
1445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *key != keys::kBackground) {
1446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
1447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          errors::kHostedAppsCannotIncludeExtensionFeatures, *key);
14488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
14498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
14508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
14518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
14528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
14538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
14548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1455513209b27ff55e2841eac0e4120199c23acce758Ben MurdochExtension::Extension(const FilePath& path, Location location)
1456513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    : incognito_split_mode_(false),
1457513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      location_(location),
1458513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      converted_from_user_script_(false),
1459513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      is_theme_(false),
1460513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      is_app_(false),
1461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      is_storage_isolated_(false),
1462513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      launch_container_(extension_misc::LAUNCH_TAB),
1463513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      launch_width_(0),
1464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      launch_height_(0),
1465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      wants_file_access_(false) {
1466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(path.empty() || path.IsAbsolute());
1467513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  path_ = MaybeNormalizePath(path);
14688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
1469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1470513209b27ff55e2841eac0e4120199c23acce758Ben MurdochExtension::~Extension() {
1471513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
1472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1473513209b27ff55e2841eac0e4120199c23acce758Ben MurdochExtensionResource Extension::GetResource(
1474513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const std::string& relative_path) const {
14758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#if defined(OS_POSIX)
14768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  FilePath relative_file_path(relative_path);
14778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#elif defined(OS_WIN)
14788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  FilePath relative_file_path(UTF8ToWide(relative_path));
14798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#endif
14808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return ExtensionResource(id(), path(), relative_file_path);
14818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
14828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1483513209b27ff55e2841eac0e4120199c23acce758Ben MurdochExtensionResource Extension::GetResource(
1484513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const FilePath& relative_file_path) const {
14858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return ExtensionResource(id(), path(), relative_file_path);
14868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
14878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
14888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// TODO(rafaelw): Move ParsePEMKeyBytes, ProducePEM & FormatPEMForOutput to a
14898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// util class in base:
14908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// http://code.google.com/p/chromium/issues/detail?id=13572
14918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::ParsePEMKeyBytes(const std::string& input,
14928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                 std::string* output) {
14938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DCHECK(output);
14948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!output)
14958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
14968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (input.length() == 0)
14978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
14988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
14998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string working = input;
15008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (StartsWithASCII(working, kKeyBeginHeaderMarker, true)) {
15018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    working = CollapseWhitespaceASCII(working, true);
15028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    size_t header_pos = working.find(kKeyInfoEndMarker,
15038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      sizeof(kKeyBeginHeaderMarker) - 1);
15048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (header_pos == std::string::npos)
15058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
15068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    size_t start_pos = header_pos + sizeof(kKeyInfoEndMarker) - 1;
15078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    size_t end_pos = working.rfind(kKeyBeginFooterMarker);
15088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (end_pos == std::string::npos)
15098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
15108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (start_pos >= end_pos)
15118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
15128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
15138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    working = working.substr(start_pos, end_pos - start_pos);
15148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (working.length() == 0)
15158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
15168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
15178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
15188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return base::Base64Decode(working, output);
15198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
15208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool Extension::ProducePEM(const std::string& input, std::string* output) {
15228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  CHECK(output);
15238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (input.length() == 0)
15248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
15258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
15268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return base::Base64Encode(input, output);
15278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
15288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool Extension::FormatPEMForFileOutput(const std::string& input,
15308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                       std::string* output,
15318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                       bool is_public) {
15328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  CHECK(output);
15338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (input.length() == 0)
15348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
15358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  *output = "";
15368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(kKeyBeginHeaderMarker);
15378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(" ");
15388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(is_public ? kPublic : kPrivate);
15398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(" ");
15408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(kKeyInfoEndMarker);
15418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append("\n");
15428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < input.length(); ) {
15438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    int slice = std::min<int>(input.length() - i, kPEMOutputColumns);
15448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    output->append(input.substr(i, slice));
15458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    output->append("\n");
15468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    i += slice;
15478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
15488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(kKeyBeginFooterMarker);
15498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(" ");
15508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(is_public ? kPublic : kPrivate);
15518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(" ");
15528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append(kKeyInfoEndMarker);
15538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  output->append("\n");
15548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
15558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
15568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
15578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
15588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
1559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool Extension::IsPrivilegeIncrease(const bool granted_full_access,
1560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    const std::set<std::string>& granted_apis,
1561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    const ExtensionExtent& granted_extent,
1562513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                    const Extension* new_extension) {
1563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // If the extension had native code access, we don't need to go any further.
1564201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Things can't get any worse.
1565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (granted_full_access)
15668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
15678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
15688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Otherwise, if the new extension has a plugin, it's a privilege increase.
1569201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (new_extension->HasFullPermissions())
15708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;
15718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1572201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // If the extension hadn't been granted access to all hosts in the past, then
1573201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // see if the extension requires more host permissions.
1574201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!HasEffectiveAccessToAllHosts(granted_extent, granted_apis)) {
15758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (new_extension->HasEffectiveAccessToAllHosts())
15768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
15778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1578201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const ExtensionExtent new_extent =
1579201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        new_extension->GetEffectiveHostPermissions();
1580201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1581201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (IsElevatedHostList(granted_extent.patterns(), new_extent.patterns()))
15828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
15838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
15848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1585201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::set<std::string> new_apis = new_extension->api_permissions();
1586201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::set<std::string> new_apis_only;
1587201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::set_difference(new_apis.begin(), new_apis.end(),
1588201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      granted_apis.begin(), granted_apis.end(),
1589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      std::inserter(new_apis_only, new_apis_only.begin()));
1590201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1591201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Ignore API permissions that don't require user approval when deciding if
1592201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // an extension has increased its privileges.
1593201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t new_api_count = 0;
1594201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (std::set<std::string>::iterator i = new_apis_only.begin();
1595201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch       i != new_apis_only.end(); ++i) {
1596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
1597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (GetPermissionMessageId(*i) > PermissionMessage::ID_NONE)
1598201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new_api_count++;
1599201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
16008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1601201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (new_api_count)
16028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;
16038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
16058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
16068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
1608513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid Extension::DecodeIcon(const Extension* extension,
16098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                           Icons icon_size,
16108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                           scoped_ptr<SkBitmap>* result) {
16118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  FilePath icon_path = extension->GetIconResource(
16128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      icon_size, ExtensionIconSet::MATCH_EXACTLY).GetFilePath();
16138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DecodeIconFromPath(icon_path, icon_size, result);
16148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
16158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
16178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvoid Extension::DecodeIconFromPath(const FilePath& icon_path,
16188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                   Icons icon_size,
16198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                   scoped_ptr<SkBitmap>* result) {
16208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (icon_path.empty())
16218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return;
16228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string file_contents;
16248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!file_util::ReadFileToString(icon_path, &file_contents)) {
162572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(ERROR) << "Could not read icon file: " << icon_path.LossyDisplayName();
16268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return;
16278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
16288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Decode the image using WebKit's image decoder.
16308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  const unsigned char* data =
16318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    reinterpret_cast<const unsigned char*>(file_contents.data());
16328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  webkit_glue::ImageDecoder decoder;
16338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  scoped_ptr<SkBitmap> decoded(new SkBitmap());
16348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  *decoded = decoder.Decode(data, file_contents.length());
16358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (decoded->empty()) {
16368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    LOG(ERROR) << "Could not decode icon file: "
163772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen               << icon_path.LossyDisplayName();
16388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return;
16398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
16408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (decoded->width() != icon_size || decoded->height() != icon_size) {
16428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    LOG(ERROR) << "Icon file has unexpected size: "
16438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen               << base::IntToString(decoded->width()) << "x"
16448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen               << base::IntToString(decoded->height());
16458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return;
16468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
16478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  result->swap(decoded);
16498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
16508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
1652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst SkBitmap& Extension::GetDefaultIcon(bool is_app) {
1653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (is_app) {
1654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
1655ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        IDR_APP_DEFAULT_ICON);
1656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
1657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
1658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        IDR_EXTENSION_DEFAULT_ICON);
1659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
16628ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenGURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) {
16638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return GURL(std::string(chrome::kExtensionScheme) +
16648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen              chrome::kStandardSchemeSeparator + extension_id + "/");
16658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
16668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool Extension::InitFromValue(const DictionaryValue& source, int flags,
1668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              std::string* error) {
1669dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // When strict error checks are enabled, make URL pattern parsing strict.
1670dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  URLPattern::ParseOption parse_strictness =
1671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (flags & STRICT_ERROR_CHECKS ? URLPattern::PARSE_STRICT
1672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   : URLPattern::PARSE_LENIENT);
1673dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
16748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kPublicKey)) {
16758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string public_key_bytes;
1676731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (!source.GetString(keys::kPublicKey,
1677513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          &public_key_) ||
1678513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        !ParsePEMKeyBytes(public_key_,
1679731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          &public_key_bytes) ||
1680513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        !GenerateId(public_key_bytes, &id_)) {
16818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidKey;
16828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
16838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
1684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (flags & REQUIRE_KEY) {
16858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = errors::kInvalidKey;
16868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
16878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  } else {
16888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // If there is a path, we generate the ID from it. This is useful for
16898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // development mode, because it keeps the ID stable across restarts and
16908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // reloading the extension.
1691513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    id_ = Extension::GenerateIdForPath(path());
1692513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (id_.empty()) {
16938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      NOTREACHED() << "Could not create ID from path.";
16948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
16958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
16968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
16978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
16988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Make a copy of the manifest so we can store it in prefs.
169972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  manifest_value_.reset(source.DeepCopy());
17008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize the URL.
1702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  extension_url_ = Extension::GetBaseURLFromExtensionId(id());
17038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize version.
17058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string version_str;
17068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!source.GetString(keys::kVersion, &version_str)) {
17078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = errors::kInvalidVersion;
17088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
17098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
171021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  version_.reset(Version::GetVersionFromString(version_str));
1711513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!version_.get() ||
1712513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      version_->components().size() > 4) {
17138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = errors::kInvalidVersion;
17148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
17158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
17168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize name.
17188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  string16 localized_name;
17198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (!source.GetString(keys::kName, &localized_name)) {
17208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    *error = errors::kInvalidName;
17218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
17228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
1723201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  base::i18n::AdjustStringForLocaleDirection(&localized_name);
1724513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  name_ = UTF16ToUTF8(localized_name);
17258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize description (if present).
17278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kDescription)) {
1728731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (!source.GetString(keys::kDescription,
1729513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          &description_)) {
17308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidDescription;
17318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
17328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
17338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
17348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1735513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Initialize homepage url (if present).
1736513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (source.HasKey(keys::kHomepageURL)) {
1737513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    std::string tmp;
1738513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!source.GetString(keys::kHomepageURL, &tmp)) {
1739513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      *error = ExtensionErrorUtils::FormatErrorMessage(
1740513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          errors::kInvalidHomepageURL, "");
1741513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return false;
1742513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
1743513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    homepage_url_ = GURL(tmp);
1744513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!homepage_url_.is_valid()) {
1745513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      *error = ExtensionErrorUtils::FormatErrorMessage(
1746513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          errors::kInvalidHomepageURL, tmp);
1747513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return false;
1748513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
1749513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
1750513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
17518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize update url (if present).
17528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kUpdateURL)) {
17538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string tmp;
17548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetString(keys::kUpdateURL, &tmp)) {
17558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
17568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          errors::kInvalidUpdateURL, "");
17578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
17588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
1759513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    update_url_ = GURL(tmp);
1760513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!update_url_.is_valid() ||
1761513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        update_url_.has_ref()) {
17628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
17638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          errors::kInvalidUpdateURL, tmp);
17648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
17658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
17668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
17678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Validate minimum Chrome version (if present). We don't need to store this,
17698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // since the extension is not valid if it is incorrect.
17708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kMinimumChromeVersion)) {
17718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string minimum_version_string;
17728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetString(keys::kMinimumChromeVersion,
17738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                          &minimum_version_string)) {
17748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidMinimumChromeVersion;
17758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
17768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
17778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    scoped_ptr<Version> minimum_version(
17798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        Version::GetVersionFromString(minimum_version_string));
17808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!minimum_version.get()) {
17818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidMinimumChromeVersion;
17828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
17838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
17848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    chrome::VersionInfo current_version_info;
17868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!current_version_info.is_valid()) {
17878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      NOTREACHED();
17888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
17898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
17908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    scoped_ptr<Version> current_version(
17928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        Version::GetVersionFromString(current_version_info.Version()));
17938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!current_version.get()) {
17948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      DCHECK(false);
17958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
17968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
17978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
17988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (current_version->CompareTo(*minimum_version) < 0) {
17998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
18008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          errors::kChromeVersionTooLow,
18018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          l10n_util::GetStringUTF8(IDS_PRODUCT_NAME),
18028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          minimum_version_string);
18038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
18048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
18058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
18068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
18078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize converted_from_user_script (if present)
18088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  source.GetBoolean(keys::kConvertedFromUserScript,
1809513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                    &converted_from_user_script_);
18108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
18118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize icons (if present).
18128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kIcons)) {
18138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    DictionaryValue* icons_value = NULL;
18148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetDictionary(keys::kIcons, &icons_value)) {
18158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidIcons;
18168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
18178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
18188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
18198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t i = 0; i < arraysize(kIconSizes); ++i) {
18208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string key = base::IntToString(kIconSizes[i]);
18218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (icons_value->HasKey(key)) {
18228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        std::string icon_path;
18238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (!icons_value->GetString(key, &icon_path)) {
18248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          *error = ExtensionErrorUtils::FormatErrorMessage(
18258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen              errors::kInvalidIconPath, key);
18268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          return false;
18278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
18288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1829dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (!icon_path.empty() && icon_path[0] == '/')
18308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          icon_path = icon_path.substr(1);
18318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
18328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (icon_path.empty()) {
18338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          *error = ExtensionErrorUtils::FormatErrorMessage(
18348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen              errors::kInvalidIconPath, key);
18358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          return false;
18368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
18378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1838513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        icons_.Add(kIconSizes[i], icon_path);
18398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
18408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
18418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
18428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
18438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize themes (if present).
1844513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  is_theme_ = false;
18458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kTheme)) {
18468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // Themes cannot contain extension keys.
18478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (ContainsNonThemeKeys(source)) {
18488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kThemesCannotContainExtensions;
18498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
18508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
18518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* theme_value = NULL;
18538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetDictionary(keys::kTheme, &theme_value)) {
18548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidTheme;
18558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
18568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
1857513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    is_theme_ = true;
18588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* images_value = NULL;
18608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) {
18618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Validate that the images are all strings
18628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      for (DictionaryValue::key_iterator iter = images_value->begin_keys();
18638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen           iter != images_value->end_keys(); ++iter) {
18648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        std::string val;
18658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (!images_value->GetString(*iter, &val)) {
18668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          *error = errors::kInvalidThemeImages;
18678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          return false;
18688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
18698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
187072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      theme_images_.reset(images_value->DeepCopy());
18718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
18728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1873ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* colors_value = NULL;
18748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (theme_value->GetDictionary(keys::kThemeColors, &colors_value)) {
18758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Validate that the colors are RGB or RGBA lists
18768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      for (DictionaryValue::key_iterator iter = colors_value->begin_keys();
18778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen           iter != colors_value->end_keys(); ++iter) {
1878ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ListValue* color_list = NULL;
1879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        double alpha = 0.0;
1880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        int alpha_int = 0;
1881ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        int color = 0;
18828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        // The color must be a list
18838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (!colors_value->GetListWithoutPathExpansion(*iter, &color_list) ||
18848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            // And either 3 items (RGB) or 4 (RGBA)
18858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            ((color_list->GetSize() != 3) &&
18868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen             ((color_list->GetSize() != 4) ||
18878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen              // For RGBA, the fourth item must be a real or int alpha value
188872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              (!color_list->GetDouble(3, &alpha) &&
18898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen               !color_list->GetInteger(3, &alpha_int)))) ||
18908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            // For both RGB and RGBA, the first three items must be ints (R,G,B)
18918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            !color_list->GetInteger(0, &color) ||
18928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            !color_list->GetInteger(1, &color) ||
18938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            !color_list->GetInteger(2, &color)) {
18948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          *error = errors::kInvalidThemeColors;
18958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          return false;
18968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
18978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
189872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      theme_colors_.reset(colors_value->DeepCopy());
18998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
19008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1901ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* tints_value = NULL;
19028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (theme_value->GetDictionary(keys::kThemeTints, &tints_value)) {
19038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Validate that the tints are all reals.
19048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      for (DictionaryValue::key_iterator iter = tints_value->begin_keys();
19058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen           iter != tints_value->end_keys(); ++iter) {
1906ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ListValue* tint_list = NULL;
1907ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        double v = 0.0;
1908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        int vi = 0;
19098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (!tints_value->GetListWithoutPathExpansion(*iter, &tint_list) ||
19108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            tint_list->GetSize() != 3 ||
191172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            !(tint_list->GetDouble(0, &v) || tint_list->GetInteger(0, &vi)) ||
191272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            !(tint_list->GetDouble(1, &v) || tint_list->GetInteger(1, &vi)) ||
191372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            !(tint_list->GetDouble(2, &v) || tint_list->GetInteger(2, &vi))) {
19148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          *error = errors::kInvalidThemeTints;
19158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          return false;
19168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
19178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
191872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      theme_tints_.reset(tints_value->DeepCopy());
19198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
19208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1921ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* display_properties_value = NULL;
19228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (theme_value->GetDictionary(keys::kThemeDisplayProperties,
19238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        &display_properties_value)) {
1924513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      theme_display_properties_.reset(
192572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          display_properties_value->DeepCopy());
19268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
19278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
19288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;
19298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
19308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
19318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize plugins (optional).
19328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kPlugins)) {
1933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue* list_value = NULL;
19348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetList(keys::kPlugins, &list_value)) {
19358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPlugins;
19368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
19378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
19388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
19398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t i = 0; i < list_value->GetSize(); ++i) {
1940ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DictionaryValue* plugin_value = NULL;
1941731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      std::string path_str;
19428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      bool is_public = false;
19438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
19448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!list_value->GetDictionary(i, &plugin_value)) {
19458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = errors::kInvalidPlugins;
19468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
19478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
19488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
19498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Get plugins[i].path.
1950731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (!plugin_value->GetString(keys::kPluginsPath, &path_str)) {
19518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
19528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            errors::kInvalidPluginsPath, base::IntToString(i));
19538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
19548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
19558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
19568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Get plugins[i].content (optional).
19578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (plugin_value->HasKey(keys::kPluginsPublic)) {
19588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (!plugin_value->GetBoolean(keys::kPluginsPublic, &is_public)) {
19598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          *error = ExtensionErrorUtils::FormatErrorMessage(
19608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen              errors::kInvalidPluginsPublic, base::IntToString(i));
19618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          return false;
19628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
19638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
19648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1965ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // We don't allow extension plugins to run on Chrome OS. We still
1966ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // parse the manifest entry so that error messages are consistently
1967ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // displayed across platforms.
1968ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if !defined(OS_CHROMEOS)
1969513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      plugins_.push_back(PluginInfo());
1970513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      plugins_.back().path = path().AppendASCII(path_str);
1971513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      plugins_.back().is_public = is_public;
1972ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif
19738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
19748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
19758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
1976ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (CommandLine::ForCurrentProcess()->HasSwitch(
1977ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          switches::kEnableExperimentalExtensionApis) &&
1978ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      source.HasKey(keys::kNaClModules)) {
1979ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue* list_value = NULL;
1980ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!source.GetList(keys::kNaClModules, &list_value)) {
1981ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = errors::kInvalidNaClModules;
19828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
19838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
1984ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1985ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (size_t i = 0; i < list_value->GetSize(); ++i) {
1986ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DictionaryValue* module_value = NULL;
1987ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::string path_str;
1988ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::string mime_type;
1989ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1990ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!list_value->GetDictionary(i, &module_value)) {
1991ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = errors::kInvalidNaClModules;
1992ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return false;
1993ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
1994ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1995ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Get nacl_modules[i].path.
1996ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!module_value->GetString(keys::kNaClModulesPath, &path_str)) {
1997ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
1998ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            errors::kInvalidNaClModulesPath, base::IntToString(i));
1999ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return false;
2000ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
2001ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2002ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Get nacl_modules[i].mime_type.
2003ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!module_value->GetString(keys::kNaClModulesMIMEType, &mime_type)) {
2004ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
2005ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            errors::kInvalidNaClModulesMIMEType, base::IntToString(i));
2006ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return false;
2007ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
2008ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2009ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      nacl_modules_.push_back(NaClModuleInfo());
2010ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      nacl_modules_.back().url = GetResourceURL(path_str);
2011ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      nacl_modules_.back().mime_type = mime_type;
2012ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
20138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
20148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize toolstrips.  This is deprecated for public use.
20168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // NOTE(erikkay) Although deprecated, we intend to preserve this parsing
20178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // code indefinitely.  Please contact me or Joi for details as to why.
20188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (CommandLine::ForCurrentProcess()->HasSwitch(
20198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          switches::kEnableExperimentalExtensionApis) &&
20208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      source.HasKey(keys::kToolstrips)) {
2021ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue* list_value = NULL;
20228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetList(keys::kToolstrips, &list_value)) {
20238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidToolstrips;
20248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
20258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
20268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t i = 0; i < list_value->GetSize(); ++i) {
20288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      GURL toolstrip;
2029ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DictionaryValue* toolstrip_value = NULL;
20308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string toolstrip_path;
20318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (list_value->GetString(i, &toolstrip_path)) {
20328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        // Support a simple URL value for backwards compatibility.
20338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        toolstrip = GetResourceURL(toolstrip_path);
20348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      } else if (list_value->GetDictionary(i, &toolstrip_value)) {
20358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (!toolstrip_value->GetString(keys::kToolstripPath,
20368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                        &toolstrip_path)) {
20378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          *error = ExtensionErrorUtils::FormatErrorMessage(
20388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen              errors::kInvalidToolstrip, base::IntToString(i));
20398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          return false;
20408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
20418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        toolstrip = GetResourceURL(toolstrip_path);
20428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      } else {
20438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
20448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            errors::kInvalidToolstrip, base::IntToString(i));
20458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
20468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
2047513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      toolstrips_.push_back(toolstrip);
20488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
20498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
20508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize content scripts (optional).
20528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kContentScripts)) {
20538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    ListValue* list_value;
20548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetList(keys::kContentScripts, &list_value)) {
20558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidContentScriptsList;
20568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
20578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
20588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t i = 0; i < list_value->GetSize(); ++i) {
2060ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DictionaryValue* content_script = NULL;
20618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!list_value->GetDictionary(i, &content_script)) {
20628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
20638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            errors::kInvalidContentScript, base::IntToString(i));
20648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
20658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
20668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      UserScript script;
2068ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!LoadUserScriptHelper(content_script, i, flags, error, &script))
2069731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        return false;  // Failed to parse script context definition.
20708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      script.set_extension_id(id());
2071513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (converted_from_user_script_) {
20728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        script.set_emulate_greasemonkey(true);
2073731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        script.set_match_all_frames(true);  // Greasemonkey matches all frames.
20748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
2075513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      content_scripts_.push_back(script);
20768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
20778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
20788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize page action (optional).
20808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DictionaryValue* page_action_value = NULL;
20818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kPageActions)) {
2083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue* list_value = NULL;
20848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetList(keys::kPageActions, &list_value)) {
20858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageActionsList;
20868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
20878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
20888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    size_t list_value_length = list_value->GetSize();
20908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
20918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (list_value_length == 0u) {
20928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // A list with zero items is allowed, and is equivalent to not having
20938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // a page_actions key in the manifest.  Don't set |page_action_value|.
20948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else if (list_value_length == 1u) {
20958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!list_value->GetDictionary(0, &page_action_value)) {
20968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = errors::kInvalidPageAction;
20978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
20988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
20998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else {  // list_value_length > 1u.
21008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageActionsListSize;
21018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
21028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
21038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  } else if (source.HasKey(keys::kPageAction)) {
21048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetDictionary(keys::kPageAction, &page_action_value)) {
21058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidPageAction;
21068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
21078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
21088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
21098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
21108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // If page_action_value is not NULL, then there was a valid page action.
21118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (page_action_value) {
2112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    page_action_.reset(
21138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        LoadExtensionActionHelper(page_action_value, error));
2114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!page_action_.get())
21158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;  // Failed to parse page action definition.
21168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
21178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
21188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize browser action (optional).
21198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kBrowserAction)) {
2120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* browser_action_value = NULL;
21218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetDictionary(keys::kBrowserAction, &browser_action_value)) {
21228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidBrowserAction;
21238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
21248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
21258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    browser_action_.reset(
21278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        LoadExtensionActionHelper(browser_action_value, error));
2128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!browser_action_.get())
21298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;  // Failed to parse browser action definition.
21308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
21318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Initialize file browser actions (optional).
2133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (source.HasKey(keys::kFileBrowserHandlers)) {
2134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue* file_browser_handlers_value = NULL;
2135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!source.GetList(keys::kFileBrowserHandlers,
2136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              &file_browser_handlers_value)) {
2137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = errors::kInvalidFileBrowserHandler;
2138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
2139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
2140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_browser_handlers_.reset(
2142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        LoadFileBrowserHandlers(file_browser_handlers_value, error));
2143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!file_browser_handlers_.get())
2144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;  // Failed to parse file browser actions definition.
2145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
2146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
21478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Load App settings.
2148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!LoadIsApp(manifest_value_.get(), error) ||
2149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      !LoadExtent(manifest_value_.get(), keys::kWebURLs,
2150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                  &extent_,
2151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  errors::kInvalidWebURLs, errors::kInvalidWebURL,
2152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  parse_strictness, error) ||
2153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      !EnsureNotHybridApp(manifest_value_.get(), error) ||
2154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      !LoadLaunchURL(manifest_value_.get(), error) ||
2155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !LoadLaunchContainer(manifest_value_.get(), error) ||
2156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !LoadAppIsolation(manifest_value_.get(), error)) {
21578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return false;
21588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
21598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
21608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize options page url (optional).
2161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Funtion LoadIsApp() set is_app_ above.
21628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kOptionsPage)) {
21638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string options_str;
21648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetString(keys::kOptionsPage, &options_str)) {
21658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidOptionsPage;
21668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
21678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
21688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
21698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (is_hosted_app()) {
21708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // hosted apps require an absolute URL.
21718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      GURL options_url(options_str);
21728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!options_url.is_valid() ||
21738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          !(options_url.SchemeIs("http") || options_url.SchemeIs("https"))) {
21748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = errors::kInvalidOptionsPageInHostedApp;
21758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
21768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
2177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      options_url_ = options_url;
21788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else {
21798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      GURL absolute(options_str);
21808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (absolute.is_valid()) {
21818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = errors::kInvalidOptionsPageExpectUrlInPackage;
21828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
21838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
2184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      options_url_ = GetResourceURL(options_str);
2185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (!options_url_.is_valid()) {
21868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = errors::kInvalidOptionsPage;
21878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
21888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
21898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
21908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
21918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
21928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize the permissions (optional).
21938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kPermissions)) {
21948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    ListValue* permissions = NULL;
21958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetList(keys::kPermissions, &permissions)) {
21968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = ExtensionErrorUtils::FormatErrorMessage(
21978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          errors::kInvalidPermissions, "");
21988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
21998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
22008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
22018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (size_t i = 0; i < permissions->GetSize(); ++i) {
22028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string permission_str;
22038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (!permissions->GetString(i, &permission_str)) {
22048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = ExtensionErrorUtils::FormatErrorMessage(
22058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen            errors::kInvalidPermission, base::IntToString(i));
22068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
22078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
22088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Only COMPONENT extensions can use private APIs.
22108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // TODO(asargent) - We want a more general purpose mechanism for this,
22118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // and better error messages. (http://crbug.com/54013)
2212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!IsComponentOnlyPermission(permission_str)
2213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#ifndef NDEBUG
2214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           && !CommandLine::ForCurrentProcess()->HasSwitch(
2215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                 switches::kExposePrivateExtensionApi)
2216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif
2217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ) {
22188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        continue;
22198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
22208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
22218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Remap the old unlimited storage permission name.
22228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (permission_str == kOldUnlimitedStoragePermission)
22238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        permission_str = kUnlimitedStoragePermission;
22248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
22258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (web_extent().is_empty() || location() == Extension::COMPONENT) {
22268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        // Check if it's a module permission.  If so, enable that permission.
22278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (IsAPIPermission(permission_str)) {
222821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          // Only allow the experimental API permission if the command line
222921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          // flag is present, or if the extension is a component of Chrome.
223021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          if (permission_str == Extension::kExperimentalPermission &&
223121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen              !CommandLine::ForCurrentProcess()->HasSwitch(
223221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                switches::kEnableExperimentalExtensionApis) &&
223321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen              location() != Extension::COMPONENT) {
223421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            *error = errors::kExperimentalFlagRequired;
223521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            return false;
223621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          }
2237513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          api_permissions_.insert(permission_str);
22388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          continue;
22398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
22408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      } else {
22418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        // Hosted apps only get access to a subset of the valid permissions.
22428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        if (IsHostedAppPermission(permission_str)) {
2243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          api_permissions_.insert(permission_str);
22448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          continue;
22458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        }
22468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
22478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // Check if it's a host pattern permission.
2249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ?
2250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          URLPattern::SCHEME_ALL : kValidHostPermissionSchemes);
2251731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      URLPattern::ParseResult parse_result = pattern.Parse(permission_str,
2253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                           parse_strictness);
2254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (parse_result == URLPattern::PARSE_SUCCESS) {
2255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        if (!CanSpecifyHostPermission(pattern)) {
2256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          *error = ExtensionErrorUtils::FormatErrorMessage(
2257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch              errors::kInvalidPermissionScheme, base::IntToString(i));
2258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          return false;
2259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        }
22608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        // The path component is not used for host permissions, so we force it
2262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        // to match all paths.
2263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        pattern.SetPath("/*");
2264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
2265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (pattern.MatchesScheme(chrome::kFileScheme) &&
2266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            !CanExecuteScriptEverywhere()) {
2267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          wants_file_access_ = true;
2268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          if (!(flags & ALLOW_FILE_ACCESS))
2269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            pattern.set_valid_schemes(
2270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
2271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
2272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2273201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        host_permissions_.push_back(pattern);
2274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      }
22758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // If it's not a host permission, then it's probably an unknown API
2277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // permission. Do not throw an error so extensions can retain
2278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // backwards compatability (http://crbug.com/42742).
2279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // TODO(jstritar): We can improve error messages by adding better
2280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // validation of API permissions here.
2281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // TODO(skerner): Consider showing the reason |permission_str| is not
2282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // a valid URL pattern if it is almost valid.  For example, if it has
2283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // a valid scheme, and failed to parse because it has a port, show an
2284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // error.
22858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
22868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
22878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Initialize background url (optional).
2289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (source.HasKey(keys::kBackground)) {
2290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string background_str;
2291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!source.GetString(keys::kBackground, &background_str)) {
2292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *error = errors::kInvalidBackground;
2293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
2294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
2295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (is_hosted_app()) {
2297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Make sure "background" permission is set.
2298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (api_permissions_.find(kBackgroundPermission) ==
2299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          api_permissions_.end()) {
2300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = errors::kBackgroundPermissionNeeded;
2301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return false;
2302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
2303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Hosted apps require an absolute URL.
2304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      GURL bg_page(background_str);
2305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!bg_page.is_valid()) {
2306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = errors::kInvalidBackgroundInHostedApp;
2307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return false;
2308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
2309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!(bg_page.SchemeIs("https") ||
2311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           (CommandLine::ForCurrentProcess()->HasSwitch(
2312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                switches::kAllowHTTPBackgroundPage) &&
2313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            bg_page.SchemeIs("http")))) {
2314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = errors::kInvalidBackgroundInHostedApp;
2315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return false;
2316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
2317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      background_url_ = bg_page;
2318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
2319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      background_url_ = GetResourceURL(background_str);
2320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
2321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
2322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
23238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kDefaultLocale)) {
232421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!source.GetString(keys::kDefaultLocale, &default_locale_) ||
232521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        !l10n_util::IsValidLocaleSyntax(default_locale_)) {
23268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidDefaultLocale;
23278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
23288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
23298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
23308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
23318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Chrome URL overrides (optional)
23328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kChromeURLOverrides)) {
2333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* overrides = NULL;
23348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetDictionary(keys::kChromeURLOverrides, &overrides)) {
23358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidChromeURLOverrides;
23368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
23378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
23388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
23398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // Validate that the overrides are all strings
23408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (DictionaryValue::key_iterator iter = overrides->begin_keys();
23418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         iter != overrides->end_keys(); ++iter) {
23428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string page = *iter;
23438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string val;
23448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Restrict override pages to a list of supported URLs.
23458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if ((page != chrome::kChromeUINewTabHost &&
23468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#if defined(TOUCH_UI)
23478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen           page != chrome::kChromeUIKeyboardHost &&
23488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#endif
234972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_CHROMEOS)
235072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           page != chrome::kChromeUIActivationMessageHost &&
235172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
23528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen           page != chrome::kChromeUIBookmarksHost &&
23538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen           page != chrome::kChromeUIHistoryHost) ||
23548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen          !overrides->GetStringWithoutPathExpansion(*iter, &val)) {
23558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        *error = errors::kInvalidChromeURLOverrides;
23568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        return false;
23578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      }
23588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      // Replace the entry with a fully qualified chrome-extension:// URL.
2359513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      chrome_url_overrides_[page] = GetResourceURL(val);
23608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
23618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
23628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // An extension may override at most one page.
23638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (overrides->size() > 1) {
23648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kMultipleOverrides;
23658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
23668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
23678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
23688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
23694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (source.HasKey(keys::kOmnibox)) {
23704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!source.GetString(keys::kOmniboxKeyword, &omnibox_keyword_) ||
2371513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        omnibox_keyword_.empty()) {
23728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidOmniboxKeyword;
23738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
23748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
23758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
23768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
23778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize devtools page url (optional).
23788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kDevToolsPage)) {
23798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string devtools_str;
23808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetString(keys::kDevToolsPage, &devtools_str)) {
23818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidDevToolsPage;
23828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
23838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
23848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!HasApiPermission(Extension::kExperimentalPermission)) {
23858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kDevToolsExperimental;
23868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
23878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
2388513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    devtools_url_ = GetResourceURL(devtools_str);
23898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
23908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
239172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Initialize sidebar action (optional).
239272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (source.HasKey(keys::kSidebar)) {
2393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* sidebar_value = NULL;
239472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!source.GetDictionary(keys::kSidebar, &sidebar_value)) {
239572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      *error = errors::kInvalidSidebar;
239672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return false;
239772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
239872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!HasApiPermission(Extension::kExperimentalPermission)) {
239972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      *error = errors::kSidebarExperimental;
240072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return false;
240172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
240272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sidebar_defaults_.reset(LoadExtensionSidebarDefaults(sidebar_value, error));
240372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!sidebar_defaults_.get())
240472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return false;  // Failed to parse sidebar definition.
240572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
240672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
240721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Initialize text-to-speech voices (optional).
240821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (source.HasKey(keys::kTts)) {
2409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* tts_dict = NULL;
241021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!source.GetDictionary(keys::kTts, &tts_dict)) {
241121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *error = errors::kInvalidTts;
241221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return false;
241321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
241421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
241521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (tts_dict->HasKey(keys::kTtsVoices)) {
2416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ListValue* tts_voices = NULL;
241721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) {
241821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        *error = errors::kInvalidTtsVoices;
241921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return false;
242021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
242121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
242221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      for (size_t i = 0; i < tts_voices->GetSize(); i++) {
2423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        DictionaryValue* one_tts_voice = NULL;
242421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (!tts_voices->GetDictionary(i, &one_tts_voice)) {
242521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          *error = errors::kInvalidTtsVoices;
242621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          return false;
242721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
242821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
242921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        TtsVoice voice_data;
243021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (one_tts_voice->HasKey(keys::kTtsVoicesVoiceName)) {
243121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          if (!one_tts_voice->GetString(
243221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                  keys::kTtsVoicesVoiceName, &voice_data.voice_name)) {
243321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            *error = errors::kInvalidTtsVoicesVoiceName;
243421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            return false;
243521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          }
243621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
243721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (one_tts_voice->HasKey(keys::kTtsVoicesLocale)) {
243821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          if (!one_tts_voice->GetString(
243921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                  keys::kTtsVoicesLocale, &voice_data.locale) ||
244021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen              !l10n_util::IsValidLocaleSyntax(voice_data.locale)) {
244121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            *error = errors::kInvalidTtsVoicesLocale;
244221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            return false;
244321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          }
244421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
244521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (one_tts_voice->HasKey(keys::kTtsVoicesGender)) {
244621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          if (!one_tts_voice->GetString(
244721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                  keys::kTtsVoicesGender, &voice_data.gender) ||
244821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen              (voice_data.gender != keys::kTtsGenderMale &&
244921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen               voice_data.gender != keys::kTtsGenderFemale)) {
245021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            *error = errors::kInvalidTtsVoicesGender;
245121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            return false;
245221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          }
245321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
245421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
245521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        tts_voices_.push_back(voice_data);
245621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
245721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
245821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
245921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
24608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Initialize incognito behavior. Apps default to split mode, extensions
24618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // default to spanning.
2462513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  incognito_split_mode_ = is_app();
24638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (source.HasKey(keys::kIncognito)) {
24648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    std::string value;
24658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (!source.GetString(keys::kIncognito, &value)) {
24668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidIncognitoBehavior;
24678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
24688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
24698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (value == values::kIncognitoSpanning) {
2470513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      incognito_split_mode_ = false;
24718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else if (value == values::kIncognitoSplit) {
2472513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      incognito_split_mode_ = true;
24738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    } else {
24748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      *error = errors::kInvalidIncognitoBehavior;
24758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return false;
24768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
24778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
24788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2479731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (HasMultipleUISurfaces()) {
2480731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    *error = errors::kOneUISurfaceOnly;
2481731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
2482731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
2483731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2484731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  InitEffectiveHostPermissions();
2485731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
24868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Although |source| is passed in as a const, it's still possible to modify
24878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // it.  This is dangerous since the utility process re-uses |source| after
24888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // it calls InitFromValue, passing it up to the browser process which calls
24898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // InitFromValue again.  As a result, we need to make sure that nobody
24908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // accidentally modifies it.
2491513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(source.Equals(manifest_value_.get()));
24928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
24938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
24948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
24958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
24968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static
2497731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string Extension::ChromeStoreLaunchURL() {
24988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string gallery_prefix = extension_urls::kGalleryBrowsePrefix;
24998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppsGalleryURL))
25008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    gallery_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
25018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        switches::kAppsGalleryURL);
25028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (EndsWith(gallery_prefix, "/", true))
25038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    gallery_prefix = gallery_prefix.substr(0, gallery_prefix.length() - 1);
25048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return gallery_prefix;
25058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
25068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2507513209b27ff55e2841eac0e4120199c23acce758Ben MurdochGURL Extension::GetHomepageURL() const {
2508513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (homepage_url_.is_valid())
2509513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return homepage_url_;
2510513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
25114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!UpdatesFromGallery())
25128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return GURL();
25138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2514731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(erikkay): This may not be entirely correct with the webstore.
2515731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // I think it will have a mixture of /extensions/detail and /webstore/detail
2516731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // URLs.  Perhaps they'll handle this nicely with redirects?
2517731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  GURL url(ChromeStoreLaunchURL() + std::string("/detail/") + id());
25188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return url;
25198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
25208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2521513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstd::set<FilePath> Extension::GetBrowserImages() const {
25228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::set<FilePath> image_paths;
25238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // TODO(viettrungluu): These |FilePath::FromWStringHack(UTF8ToWide())|
25248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // indicate that we're doing something wrong.
25258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
25268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Extension icons.
2527731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (ExtensionIconSet::IconMap::const_iterator iter = icons().map().begin();
2528731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       iter != icons().map().end(); ++iter) {
25298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(iter->second)));
25308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
25318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
25328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Theme images.
25338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DictionaryValue* theme_images = GetThemeImages();
25348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (theme_images) {
25358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (DictionaryValue::key_iterator it = theme_images->begin_keys();
25368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         it != theme_images->end_keys(); ++it) {
25378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      std::string val;
25388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      if (theme_images->GetStringWithoutPathExpansion(*it, &val))
25398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(val)));
25408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
25418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
25428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
25438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Page action icons.
2544731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (page_action()) {
2545731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::vector<std::string>* icon_paths = page_action()->icon_paths();
25468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (std::vector<std::string>::iterator iter = icon_paths->begin();
25478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         iter != icon_paths->end(); ++iter) {
25488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(*iter)));
25498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
25508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
25518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
25528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Browser action icons.
2553731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (browser_action()) {
2554731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::vector<std::string>* icon_paths = browser_action()->icon_paths();
25558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (std::vector<std::string>::iterator iter = icon_paths->begin();
25568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         iter != icon_paths->end(); ++iter) {
25578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      image_paths.insert(FilePath::FromWStringHack(UTF8ToWide(*iter)));
25588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
25598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
25608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
25618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return image_paths;
25628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
25638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
25648ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenGURL Extension::GetFullLaunchURL() const {
2565731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!launch_local_path().empty())
2566731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return url().Resolve(launch_local_path());
25678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  else
2568731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return GURL(launch_web_url());
25698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
25708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
25718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenstatic std::string SizeToString(const gfx::Size& max_size) {
25728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return base::IntToString(max_size.width()) + "x" +
25738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen         base::IntToString(max_size.height());
25748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
25758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2576731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
2577731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid Extension::SetScriptingWhitelist(
257872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const Extension::ScriptingWhitelist& whitelist) {
2579731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ScriptingWhitelist* current_whitelist =
258021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ExtensionConfig::GetInstance()->whitelist();
2581731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  current_whitelist->clear();
2582731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (ScriptingWhitelist::const_iterator it = whitelist.begin();
2583731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       it != whitelist.end(); ++it) {
2584731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    current_whitelist->push_back(*it);
2585731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
2586731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
2587731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
258872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
258972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst Extension::ScriptingWhitelist* Extension::GetScriptingWhitelist() {
259072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ExtensionConfig::GetInstance()->whitelist();
259172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
259272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
25938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvoid Extension::SetCachedImage(const ExtensionResource& source,
25948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                               const SkBitmap& image,
2595513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                               const gfx::Size& original_size) const {
25968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DCHECK(source.extension_root() == path());  // The resource must come from
25978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                              // this extension.
25988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  const FilePath& path = source.relative_path();
25998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  gfx::Size actual_size(image.width(), image.height());
26008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (actual_size == original_size) {
2601513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    image_cache_[ImageCacheKey(path, std::string())] = image;
26028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  } else {
2603513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    image_cache_[ImageCacheKey(path, SizeToString(actual_size))] = image;
26048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
26058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
26068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::HasCachedImage(const ExtensionResource& source,
2608513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                               const gfx::Size& max_size) const {
26098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DCHECK(source.extension_root() == path());  // The resource must come from
26108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                              // this extension.
26118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return GetCachedImageImpl(source, max_size) != NULL;
26128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
26138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26148ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenSkBitmap Extension::GetCachedImage(const ExtensionResource& source,
2615513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   const gfx::Size& max_size) const {
26168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  DCHECK(source.extension_root() == path());  // The resource must come from
26178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                                              // this extension.
26188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  SkBitmap* image = GetCachedImageImpl(source, max_size);
26198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return image ? *image : SkBitmap();
26208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
26218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26228ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenSkBitmap* Extension::GetCachedImageImpl(const ExtensionResource& source,
2623513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                        const gfx::Size& max_size) const {
26248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  const FilePath& path = source.relative_path();
26258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Look for exact size match.
2627513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ImageCache::iterator i = image_cache_.find(
2628513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ImageCacheKey(path, SizeToString(max_size)));
2629513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (i != image_cache_.end())
26308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return &(i->second);
26318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // If we have the original size version cached, return that if it's small
26338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // enough.
2634513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  i = image_cache_.find(ImageCacheKey(path, std::string()));
2635513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (i != image_cache_.end()) {
26368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    SkBitmap& image = i->second;
26378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (image.width() <= max_size.width() &&
26388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        image.height() <= max_size.height())
26398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return &(i->second);
26408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
26418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return NULL;
26438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
26448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26458ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenExtensionResource Extension::GetIconResource(
2646513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int size, ExtensionIconSet::MatchType match_type) const {
2647731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string path = icons().Get(size, match_type);
26488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (path.empty())
26498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return ExtensionResource();
26508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return GetResource(path);
26518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
26528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2653513209b27ff55e2841eac0e4120199c23acce758Ben MurdochGURL Extension::GetIconURL(int size,
2654513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                           ExtensionIconSet::MatchType match_type) const {
2655731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string path = icons().Get(size, match_type);
26568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (path.empty())
26578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return GURL();
26588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  else
26598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return GetResourceURL(path);
26608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
26618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2662513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool Extension::CanSpecifyHostPermission(const URLPattern& pattern) const {
2663731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!pattern.match_all_urls() &&
2664731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      pattern.MatchesScheme(chrome::kChromeUIScheme)) {
26658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // Only allow access to chrome://favicon to regular extensions. Component
26668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    // extensions can have access to all of chrome://*.
2667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return (pattern.host() == chrome::kChromeUIFaviconHost ||
2668731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            CanExecuteScriptEverywhere());
26698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
26708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Otherwise, the valid schemes were handled by URLPattern.
26728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return true;
26738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
26748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2675513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
26768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::HasApiPermission(
26778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    const std::set<std::string>& api_permissions,
26788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    const std::string& function_name) {
26798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  std::string permission_name = function_name;
26808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < kNumNonPermissionFunctionNames; ++i) {
26828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (permission_name == kNonPermissionFunctionNames[i])
26838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
26848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
26858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // See if this is a function or event name first and strip out the package.
26878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Functions will be of the form package.function
26888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // Events will be of the form package/id or package.optional.stuff
26898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  size_t separator = function_name.find_first_of("./");
26908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (separator != std::string::npos)
26918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    permission_name = function_name.substr(0, separator);
26928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  // windows and tabs are the same permission.
26948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (permission_name == kWindowPermission)
26958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    permission_name = Extension::kTabPermission;
26968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
26978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (api_permissions.count(permission_name))
26988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    return true;
26998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
27008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < kNumNonPermissionModuleNames; ++i) {
27018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (permission_name == kNonPermissionModuleNames[i]) {
27028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
27038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
27048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
27058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
27068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
27078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
27088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
27098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool Extension::HasHostPermission(const GURL& url) const {
2710731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (URLPatternList::const_iterator host = host_permissions().begin();
2711731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       host != host_permissions().end(); ++host) {
2712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Non-component extensions can only access chrome://favicon and no other
2713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // chrome:// scheme urls.
2714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (url.SchemeIs(chrome::kChromeUIScheme) &&
2715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        url.host() != chrome::kChromeUIFaviconHost &&
2716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        location() != Extension::COMPONENT)
2717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
2718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
27198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (host->MatchesUrl(url))
27208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
27218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
27228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
27238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
27248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2725731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid Extension::InitEffectiveHostPermissions() {
2726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Some APIs effectively grant access to every site.  New ones should be
2727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // added here.  (I'm looking at you, network API)
2728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (HasApiPermission(api_permissions_, kProxyPermission) ||
2729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !devtools_url_.is_empty()) {
2730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    URLPattern all_urls(URLPattern::SCHEME_ALL);
2731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    all_urls.set_match_all_urls(true);
2732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    effective_host_permissions_.AddPattern(all_urls);
2733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
2734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
2735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2736731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (URLPatternList::const_iterator host = host_permissions().begin();
2737731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       host != host_permissions().end(); ++host)
2738513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    effective_host_permissions_.AddPattern(*host);
27398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2740731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (UserScriptList::const_iterator content_script =
2741731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick           content_scripts().begin();
2742731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       content_script != content_scripts().end(); ++content_script) {
27438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    UserScript::PatternList::const_iterator pattern =
27448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen        content_script->url_patterns().begin();
27458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    for (; pattern != content_script->url_patterns().end(); ++pattern)
2746513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      effective_host_permissions_.AddPattern(*pattern);
2747731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
2748731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
2749731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool Extension::IsComponentOnlyPermission
2751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (const std::string& permission) const {
2752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (location() == Extension::COMPONENT)
2753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
2754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Non-component extensions are not allowed to access private apis.
2756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < Extension::kNumComponentPrivatePermissions; ++i) {
2757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (permission == Extension::kComponentPrivatePermissionNames[i])
2758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
2759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
2760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
2761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
2762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2763731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool Extension::HasMultipleUISurfaces() const {
2764731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int num_surfaces = 0;
2765731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2766731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (page_action())
2767731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ++num_surfaces;
2768731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2769731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (browser_action())
2770731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ++num_surfaces;
2771731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2772731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (is_app())
2773731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ++num_surfaces;
2774731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2775731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return num_surfaces > 1;
2776731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
2777731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
277872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool Extension::CanExecuteScriptOnPage(const GURL& page_url,
2779ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       const UserScript* script,
278072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       std::string* error) const {
2781731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // The gallery is special-cased as a restricted URL for scripting to prevent
2782731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // access to special JS bindings we expose to the gallery (and avoid things
2783731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // like extensions removing the "report abuse" link).
2784731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(erikkay): This seems like the wrong test.  Shouldn't we we testing
2785731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // against the store app extent?
2786731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if ((page_url.host() == GURL(Extension::ChromeStoreLaunchURL()).host()) &&
278772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      !CanExecuteScriptEverywhere() &&
2788731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      !CommandLine::ForCurrentProcess()->HasSwitch(
2789731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          switches::kAllowScriptingGallery)) {
2790731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (error)
2791731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      *error = errors::kCannotScriptGallery;
2792731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
27938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
27948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2795ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (page_url.SchemeIs(chrome::kChromeUIScheme) &&
2796ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !CanExecuteScriptEverywhere())
2797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
2798ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
279972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If a script is specified, use its matches.
280072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (script)
280172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return script->MatchesUrl(page_url);
280272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
280372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Otherwise, see if this extension has permission to execute script
280472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // programmatically on pages.
280572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < host_permissions_.size(); ++i) {
280672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (host_permissions_[i].MatchesUrl(page_url))
2807731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
2808731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
2809731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2810731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (error) {
2811731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
2812731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                     page_url.spec());
2813731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
2814731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2815731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return false;
28168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
28178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2818201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// static
2819201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool Extension::HasEffectiveAccessToAllHosts(
2820201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const ExtensionExtent& effective_host_permissions,
2821201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const std::set<std::string>& api_permissions) {
2822201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const URLPatternList patterns = effective_host_permissions.patterns();
2823201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (URLPatternList::const_iterator host = patterns.begin();
2824201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch       host != patterns.end(); ++host) {
2825ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (host->match_all_urls() ||
2826ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        (host->match_subdomains() && host->host().empty()))
28278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      return true;
28288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
28298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
28308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
28318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
28328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2833201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool Extension::HasEffectiveAccessToAllHosts() const {
2834201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return HasEffectiveAccessToAllHosts(GetEffectiveHostPermissions(),
2835201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      api_permissions());
2836201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
2837201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
2838201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool Extension::HasFullPermissions() const {
2839dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return !plugins().empty();
2840201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
2841201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
284272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool Extension::ShowConfigureContextMenus() const {
284372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Don't show context menu for component extensions. We might want to show
284472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // options for component extension button but now there is no component
284572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // extension with options. All other menu items like uninstall have
284672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // no sense for component extensions.
284772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return location() != Extension::COMPONENT;
284872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
284972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2850513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool Extension::IsAPIPermission(const std::string& str) const {
28518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
28528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    if (str == Extension::kPermissions[i].name) {
285321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return true;
28548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    }
28558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  }
28568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  return false;
28578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
28588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2859731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool Extension::CanExecuteScriptEverywhere() const {
2860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (location() == Extension::COMPONENT
2861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#ifndef NDEBUG
2862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      || CommandLine::ForCurrentProcess()->HasSwitch(
2863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          switches::kExposePrivateExtensionApi)
2864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif
2865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      )
2866731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return true;
2867731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2868731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ScriptingWhitelist* whitelist =
286921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ExtensionConfig::GetInstance()->whitelist();
2870731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2871731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (ScriptingWhitelist::const_iterator it = whitelist->begin();
2872731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       it != whitelist->end(); ++it) {
2873731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (id() == *it) {
2874731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
2875731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
2876731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
2877731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2878731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return false;
2879731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
2880731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2881dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool Extension::CanCaptureVisiblePage(const GURL& page_url,
2882dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                      std::string *error) const {
2883dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (HasHostPermission(page_url) || page_url.GetOrigin() == url())
2884dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return true;
2885dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
2886dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (error) {
2887dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    *error = ExtensionErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
2888dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                     page_url.spec());
2889dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
2890dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return false;
2891dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
2892dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
28934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool Extension::UpdatesFromGallery() const {
2894201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return update_url() == GalleryUpdateUrl(false) ||
2895201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch         update_url() == GalleryUpdateUrl(true);
28964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
28974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2898dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool Extension::OverlapsWithOrigin(const GURL& origin) const {
2899dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (url() == origin)
2900dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return true;
2901dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
2902dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (web_extent().is_empty())
2903dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
2904dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
2905dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Note: patterns and extents ignore port numbers.
2906dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  URLPattern origin_only_pattern(kValidWebExtentSchemes);
2907dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!origin_only_pattern.SetScheme(origin.scheme()))
2908dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
2909dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  origin_only_pattern.set_host(origin.host());
2910dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  origin_only_pattern.SetPath("/*");
2911dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
2912dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ExtensionExtent origin_only_pattern_list;
2913dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  origin_only_pattern_list.AddPattern(origin_only_pattern);
2914dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
2915dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return web_extent().OverlapsWith(origin_only_pattern_list);
2916dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
2917dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
29188ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenExtensionInfo::ExtensionInfo(const DictionaryValue* manifest,
29198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                             const std::string& id,
29208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                             const FilePath& path,
29218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen                             Extension::Location location)
29228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen    : extension_id(id),
29238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      extension_path(path),
29248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen      extension_location(location) {
29258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen  if (manifest)
292672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    extension_manifest.reset(manifest->DeepCopy());
29278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}
29288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen
2929731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionInfo::~ExtensionInfo() {}
2930731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2931731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickUninstalledExtensionInfo::UninstalledExtensionInfo(
2932731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const Extension& extension)
2933731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : extension_id(extension.id()),
2934731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      extension_api_permissions(extension.api_permissions()),
293521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      extension_type(extension.GetType()),
2936731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      update_url(extension.update_url()) {}
2937731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2938731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickUninstalledExtensionInfo::~UninstalledExtensionInfo() {}
293921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
294021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
294121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenUnloadedExtensionInfo::UnloadedExtensionInfo(
294221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const Extension* extension,
294321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    Reason reason)
294421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  : reason(reason),
294521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    already_disabled(false),
294621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    extension(extension) {}
2947