Move extension_messages.h to extensions/common.
[chromium-blink-merge.git] / chrome / common / extensions / manifest_handlers / settings_overrides_handler.cc
blob772c6e21a830a0d3d17f4dd0bff70758db8b8c5b
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/common/extensions/permissions/settings_override_permission.h"
13 #include "extensions/common/error_utils.h"
14 #include "extensions/common/extension_messages.h"
15 #include "extensions/common/feature_switch.h"
16 #include "extensions/common/manifest_constants.h"
17 #include "extensions/common/permissions/api_permission_set.h"
18 #include "extensions/common/permissions/manifest_permission.h"
19 #include "extensions/common/permissions/permissions_data.h"
20 #include "extensions/common/permissions/permissions_info.h"
21 #include "grit/generated_resources.h"
22 #include "ipc/ipc_message.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "url/gurl.h"
26 using extensions::api::manifest_types::ChromeSettingsOverrides;
28 namespace extensions {
29 namespace {
31 const char* kWwwPrefix = "www.";
33 scoped_ptr<GURL> CreateManifestURL(const std::string& url) {
34 scoped_ptr<GURL> manifest_url(new GURL(url));
35 if (!manifest_url->is_valid() ||
36 !manifest_url->SchemeIsHTTPOrHTTPS())
37 return scoped_ptr<GURL>();
38 return manifest_url.Pass();
41 scoped_ptr<GURL> ParseHomepage(const ChromeSettingsOverrides& overrides,
42 base::string16* error) {
43 if (!overrides.homepage)
44 return scoped_ptr<GURL>();
45 scoped_ptr<GURL> manifest_url = CreateManifestURL(*overrides.homepage);
46 if (!manifest_url) {
47 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
48 manifest_errors::kInvalidHomepageOverrideURL, *overrides.homepage);
50 return manifest_url.Pass();
53 std::vector<GURL> ParseStartupPage(const ChromeSettingsOverrides& overrides,
54 base::string16* error) {
55 std::vector<GURL> urls;
56 if (!overrides.startup_pages)
57 return urls;
59 for (std::vector<std::string>::const_iterator i =
60 overrides.startup_pages->begin(); i != overrides.startup_pages->end();
61 ++i) {
62 scoped_ptr<GURL> manifest_url = CreateManifestURL(*i);
63 if (!manifest_url) {
64 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
65 manifest_errors::kInvalidStartupOverrideURL, *i);
66 } else {
67 urls.push_back(GURL());
68 urls.back().Swap(manifest_url.get());
71 return urls;
74 scoped_ptr<ChromeSettingsOverrides::Search_provider> ParseSearchEngine(
75 ChromeSettingsOverrides* overrides,
76 base::string16* error) {
77 if (!overrides->search_provider)
78 return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
79 if (!CreateManifestURL(overrides->search_provider->favicon_url)) {
80 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
81 manifest_errors::kInvalidSearchEngineURL,
82 overrides->search_provider->favicon_url);
83 return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
85 if (!CreateManifestURL(overrides->search_provider->search_url)) {
86 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
87 manifest_errors::kInvalidSearchEngineURL,
88 overrides->search_provider->search_url);
89 return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
91 return overrides->search_provider.Pass();
94 // A www. prefix is not informative and thus not worth the limited real estate
95 // in the permissions UI.
96 std::string RemoveWwwPrefix(const std::string& url) {
97 if (StartsWithASCII(url, kWwwPrefix, false))
98 return url.substr(strlen(kWwwPrefix));
99 return url;
102 } // namespace
104 // The manifest permission implementation supports a permission for overriding
105 // the bookmark UI.
106 class SettingsOverridesHandler::ManifestPermissionImpl
107 : public ManifestPermission {
108 public:
109 explicit ManifestPermissionImpl(bool override_bookmarks_ui_permission)
110 : override_bookmarks_ui_permission_(override_bookmarks_ui_permission) {}
112 // extensions::ManifestPermission overrides.
113 virtual std::string name() const OVERRIDE {
114 return manifest_keys::kSettingsOverride;
117 virtual std::string id() const OVERRIDE {
118 return name();
121 virtual bool HasMessages() const OVERRIDE {
122 return override_bookmarks_ui_permission_;
125 virtual PermissionMessages GetMessages() const OVERRIDE {
126 PermissionMessages result;
127 if (override_bookmarks_ui_permission_) {
128 result.push_back(PermissionMessage(
129 PermissionMessage::kOverrideBookmarksUI,
130 l10n_util::GetStringUTF16(
131 IDS_EXTENSION_PROMPT_WARNING_OVERRIDE_BOOKMARKS_UI)));
133 return result;
136 virtual bool FromValue(const base::Value* value) OVERRIDE {
137 return value && value->GetAsBoolean(&override_bookmarks_ui_permission_);
140 virtual scoped_ptr<base::Value> ToValue() const OVERRIDE {
141 return scoped_ptr<base::Value>(
142 new base::FundamentalValue(override_bookmarks_ui_permission_)).Pass();
145 virtual ManifestPermission* Clone() const OVERRIDE {
146 return scoped_ptr<ManifestPermissionImpl>(
147 new ManifestPermissionImpl(
148 override_bookmarks_ui_permission_)).release();
151 virtual ManifestPermission* Diff(const ManifestPermission* rhs) const
152 OVERRIDE {
153 const ManifestPermissionImpl* other =
154 static_cast<const ManifestPermissionImpl*>(rhs);
156 return scoped_ptr<ManifestPermissionImpl>(new ManifestPermissionImpl(
157 override_bookmarks_ui_permission_ &&
158 !other->override_bookmarks_ui_permission_)).release();
161 virtual ManifestPermission* Union(const ManifestPermission* rhs) const
162 OVERRIDE {
163 const ManifestPermissionImpl* other =
164 static_cast<const ManifestPermissionImpl*>(rhs);
166 return scoped_ptr<ManifestPermissionImpl>(new ManifestPermissionImpl(
167 override_bookmarks_ui_permission_ ||
168 other->override_bookmarks_ui_permission_)).release();
171 virtual ManifestPermission* Intersect(const ManifestPermission* rhs) const
172 OVERRIDE {
173 const ManifestPermissionImpl* other =
174 static_cast<const ManifestPermissionImpl*>(rhs);
176 return scoped_ptr<ManifestPermissionImpl>(new ManifestPermissionImpl(
177 override_bookmarks_ui_permission_ &&
178 other->override_bookmarks_ui_permission_)).release();
181 virtual bool Contains(const ManifestPermission* rhs) const OVERRIDE {
182 const ManifestPermissionImpl* other =
183 static_cast<const ManifestPermissionImpl*>(rhs);
185 return !other->override_bookmarks_ui_permission_ ||
186 override_bookmarks_ui_permission_;
189 virtual bool Equal(const ManifestPermission* rhs) const OVERRIDE {
190 const ManifestPermissionImpl* other =
191 static_cast<const ManifestPermissionImpl*>(rhs);
193 return override_bookmarks_ui_permission_ ==
194 other->override_bookmarks_ui_permission_;
197 virtual void Write(IPC::Message* m) const OVERRIDE {
198 IPC::WriteParam(m, override_bookmarks_ui_permission_);
201 virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE {
202 return IPC::ReadParam(m, iter, &override_bookmarks_ui_permission_);
205 virtual void Log(std::string* log) const OVERRIDE {
206 IPC::LogParam(override_bookmarks_ui_permission_, log);
209 private:
210 bool override_bookmarks_ui_permission_;
213 SettingsOverrides::SettingsOverrides() {}
215 SettingsOverrides::~SettingsOverrides() {}
217 const SettingsOverrides* SettingsOverrides::Get(
218 const Extension* extension) {
219 return static_cast<SettingsOverrides*>(
220 extension->GetManifestData(manifest_keys::kSettingsOverride));
223 bool SettingsOverrides::RemovesBookmarkButton(
224 const SettingsOverrides& settings_overrides) {
225 return settings_overrides.bookmarks_ui &&
226 settings_overrides.bookmarks_ui->remove_button &&
227 *settings_overrides.bookmarks_ui->remove_button;
230 bool SettingsOverrides::RemovesBookmarkShortcut(
231 const SettingsOverrides& settings_overrides) {
232 return settings_overrides.bookmarks_ui &&
233 settings_overrides.bookmarks_ui->remove_bookmark_shortcut &&
234 *settings_overrides.bookmarks_ui->remove_bookmark_shortcut;
237 SettingsOverridesHandler::SettingsOverridesHandler() {}
239 SettingsOverridesHandler::~SettingsOverridesHandler() {}
241 bool SettingsOverridesHandler::Parse(Extension* extension,
242 base::string16* error) {
243 const base::Value* dict = NULL;
244 CHECK(extension->manifest()->Get(manifest_keys::kSettingsOverride, &dict));
245 scoped_ptr<ChromeSettingsOverrides> settings(
246 ChromeSettingsOverrides::FromValue(*dict, error));
247 if (!settings)
248 return false;
250 scoped_ptr<SettingsOverrides> info(new SettingsOverrides);
251 info->bookmarks_ui.swap(settings->bookmarks_ui);
252 // Support backward compatibility for deprecated key
253 // chrome_settings_overrides.bookmarks_ui.hide_bookmark_button.
254 if (info->bookmarks_ui && !info->bookmarks_ui->remove_button &&
255 info->bookmarks_ui->hide_bookmark_button) {
256 info->bookmarks_ui->remove_button.reset(
257 new bool(*info->bookmarks_ui->hide_bookmark_button));
259 info->homepage = ParseHomepage(*settings, error);
260 info->search_engine = ParseSearchEngine(settings.get(), error);
261 info->startup_pages = ParseStartupPage(*settings, error);
262 if (!info->bookmarks_ui && !info->homepage &&
263 !info->search_engine && info->startup_pages.empty()) {
264 *error = ErrorUtils::FormatErrorMessageUTF16(
265 manifest_errors::kInvalidEmptyDictionary,
266 manifest_keys::kSettingsOverride);
267 return false;
269 info->manifest_permission.reset(new ManifestPermissionImpl(
270 SettingsOverrides::RemovesBookmarkButton(*info)));
272 APIPermissionSet* permission_set =
273 PermissionsData::GetInitialAPIPermissions(extension);
274 DCHECK(permission_set);
275 if (info->search_engine) {
276 permission_set->insert(new SettingsOverrideAPIPermission(
277 PermissionsInfo::GetInstance()->GetByID(APIPermission::kSearchProvider),
278 RemoveWwwPrefix(CreateManifestURL(info->search_engine->search_url)->
279 GetOrigin().host())));
281 if (!info->startup_pages.empty()) {
282 permission_set->insert(new SettingsOverrideAPIPermission(
283 PermissionsInfo::GetInstance()->GetByID(APIPermission::kStartupPages),
284 // We only support one startup page even though the type of the manifest
285 // property is a list, only the first one is used.
286 RemoveWwwPrefix(info->startup_pages[0].GetContent())));
288 if (info->homepage) {
289 permission_set->insert(new SettingsOverrideAPIPermission(
290 PermissionsInfo::GetInstance()->GetByID(APIPermission::kHomepage),
291 RemoveWwwPrefix(info->homepage.get()->GetContent())));
293 extension->SetManifestData(manifest_keys::kSettingsOverride,
294 info.release());
295 return true;
298 bool SettingsOverridesHandler::Validate(
299 const Extension* extension,
300 std::string* error,
301 std::vector<InstallWarning>* warnings) const {
302 const SettingsOverrides* settings_overrides =
303 SettingsOverrides::Get(extension);
305 if (settings_overrides && settings_overrides->bookmarks_ui) {
306 if (!FeatureSwitch::enable_override_bookmarks_ui()->IsEnabled()) {
307 warnings->push_back(InstallWarning(
308 ErrorUtils::FormatErrorMessage(
309 manifest_errors::kUnrecognizedManifestKey,
310 manifest_keys::kBookmarkUI)));
311 } else if (settings_overrides->bookmarks_ui->hide_bookmark_button) {
312 warnings->push_back(InstallWarning(
313 ErrorUtils::FormatErrorMessage(
314 manifest_errors::kKeyIsDeprecatedWithReplacement,
315 manifest_keys::kHideBookmarkButton,
316 manifest_keys::kRemoveButton)));
320 return true;
323 ManifestPermission* SettingsOverridesHandler::CreatePermission() {
324 return new ManifestPermissionImpl(false);
327 ManifestPermission* SettingsOverridesHandler::CreateInitialRequiredPermission(
328 const Extension* extension) {
329 const SettingsOverrides* data = SettingsOverrides::Get(extension);
330 if (data)
331 return data->manifest_permission->Clone();
332 return NULL;
334 const std::vector<std::string> SettingsOverridesHandler::Keys() const {
335 return SingleKey(manifest_keys::kSettingsOverride);
338 } // namespace extensions