Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / manifest_handlers / settings_overrides_handler.cc
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.
4
5 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
6
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/extension_messages.h"
13 #include "chrome/common/extensions/permissions/settings_override_permission.h"
14 #include "extensions/common/error_utils.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"
25
26 using extensions::api::manifest_types::ChromeSettingsOverrides;
27
28 namespace extensions {
29 namespace {
30
31 const char* kWwwPrefix = "www.";
32
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();
39 }
40
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);
49   }
50   return manifest_url.Pass();
51 }
52
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;
58
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());
69     }
70   }
71   return urls;
72 }
73
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>();
84   }
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>();
90   }
91   return overrides->search_provider.Pass();
92 }
93
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;
100 }
101
102 }  // namespace
103
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) {}
111
112   // extensions::ManifestPermission overrides.
113   virtual std::string name() const OVERRIDE {
114     return manifest_keys::kSettingsOverride;
115   }
116
117   virtual std::string id() const OVERRIDE {
118     return name();
119   }
120
121   virtual bool HasMessages() const OVERRIDE {
122     return override_bookmarks_ui_permission_;
123   }
124
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)));
132     }
133     return result;
134   }
135
136   virtual bool FromValue(const base::Value* value) OVERRIDE {
137     return value && value->GetAsBoolean(&override_bookmarks_ui_permission_);
138   }
139
140   virtual scoped_ptr<base::Value> ToValue() const OVERRIDE {
141     return scoped_ptr<base::Value>(
142         new base::FundamentalValue(override_bookmarks_ui_permission_)).Pass();
143   }
144
145   virtual ManifestPermission* Clone() const OVERRIDE {
146     return scoped_ptr<ManifestPermissionImpl>(
147         new ManifestPermissionImpl(
148             override_bookmarks_ui_permission_)).release();
149   }
150
151   virtual ManifestPermission* Diff(const ManifestPermission* rhs) const
152       OVERRIDE {
153     const ManifestPermissionImpl* other =
154         static_cast<const ManifestPermissionImpl*>(rhs);
155
156     return scoped_ptr<ManifestPermissionImpl>(new ManifestPermissionImpl(
157         override_bookmarks_ui_permission_ &&
158         !other->override_bookmarks_ui_permission_)).release();
159   }
160
161   virtual ManifestPermission* Union(const ManifestPermission* rhs) const
162       OVERRIDE {
163     const ManifestPermissionImpl* other =
164         static_cast<const ManifestPermissionImpl*>(rhs);
165
166     return scoped_ptr<ManifestPermissionImpl>(new ManifestPermissionImpl(
167         override_bookmarks_ui_permission_ ||
168         other->override_bookmarks_ui_permission_)).release();
169   }
170
171   virtual ManifestPermission* Intersect(const ManifestPermission* rhs) const
172       OVERRIDE {
173     const ManifestPermissionImpl* other =
174         static_cast<const ManifestPermissionImpl*>(rhs);
175
176     return scoped_ptr<ManifestPermissionImpl>(new ManifestPermissionImpl(
177         override_bookmarks_ui_permission_ &&
178         other->override_bookmarks_ui_permission_)).release();
179   }
180
181   virtual bool Contains(const ManifestPermission* rhs) const OVERRIDE {
182     const ManifestPermissionImpl* other =
183         static_cast<const ManifestPermissionImpl*>(rhs);
184
185     return !other->override_bookmarks_ui_permission_ ||
186         override_bookmarks_ui_permission_;
187   }
188
189   virtual bool Equal(const ManifestPermission* rhs) const OVERRIDE {
190     const ManifestPermissionImpl* other =
191         static_cast<const ManifestPermissionImpl*>(rhs);
192
193     return override_bookmarks_ui_permission_ ==
194         other->override_bookmarks_ui_permission_;
195   }
196
197   virtual void Write(IPC::Message* m) const OVERRIDE {
198     IPC::WriteParam(m, override_bookmarks_ui_permission_);
199   }
200
201   virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE {
202     return IPC::ReadParam(m, iter, &override_bookmarks_ui_permission_);
203   }
204
205   virtual void Log(std::string* log) const OVERRIDE {
206     IPC::LogParam(override_bookmarks_ui_permission_, log);
207   }
208
209  private:
210   bool override_bookmarks_ui_permission_;
211 };
212
213 SettingsOverrides::SettingsOverrides() {}
214
215 SettingsOverrides::~SettingsOverrides() {}
216
217 const SettingsOverrides* SettingsOverrides::Get(
218     const Extension* extension) {
219   return static_cast<SettingsOverrides*>(
220       extension->GetManifestData(manifest_keys::kSettingsOverride));
221 }
222
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;
228 }
229
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;
235 }
236
237 SettingsOverridesHandler::SettingsOverridesHandler() {}
238
239 SettingsOverridesHandler::~SettingsOverridesHandler() {}
240
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;
249
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));
258   }
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 =
265         base::ASCIIToUTF16(manifest_errors::kInvalidEmptySettingsOverrides);
266     return false;
267   }
268   info->manifest_permission.reset(new ManifestPermissionImpl(
269       SettingsOverrides::RemovesBookmarkButton(*info)));
270
271   APIPermissionSet* permission_set =
272       PermissionsData::GetInitialAPIPermissions(extension);
273   DCHECK(permission_set);
274   if (info->search_engine) {
275     permission_set->insert(new SettingsOverrideAPIPermission(
276         PermissionsInfo::GetInstance()->GetByID(APIPermission::kSearchProvider),
277         RemoveWwwPrefix(CreateManifestURL(info->search_engine->search_url)->
278             GetOrigin().host())));
279   }
280   if (!info->startup_pages.empty()) {
281     permission_set->insert(new SettingsOverrideAPIPermission(
282         PermissionsInfo::GetInstance()->GetByID(APIPermission::kStartupPages),
283         // We only support one startup page even though the type of the manifest
284         // property is a list, only the first one is used.
285         RemoveWwwPrefix(info->startup_pages[0].GetContent())));
286   }
287   if (info->homepage) {
288     permission_set->insert(new SettingsOverrideAPIPermission(
289         PermissionsInfo::GetInstance()->GetByID(APIPermission::kHomepage),
290         RemoveWwwPrefix(info->homepage.get()->GetContent())));
291   }
292   extension->SetManifestData(manifest_keys::kSettingsOverride,
293                              info.release());
294   return true;
295 }
296
297 bool SettingsOverridesHandler::Validate(
298     const Extension* extension,
299     std::string* error,
300     std::vector<InstallWarning>* warnings) const {
301   const SettingsOverrides* settings_overrides =
302       SettingsOverrides::Get(extension);
303
304   if (settings_overrides && settings_overrides->bookmarks_ui) {
305     if (!FeatureSwitch::enable_override_bookmarks_ui()->IsEnabled()) {
306       warnings->push_back(InstallWarning(
307           ErrorUtils::FormatErrorMessage(
308               manifest_errors::kUnrecognizedManifestKey,
309               manifest_keys::kBookmarkUI)));
310     } else if (settings_overrides->bookmarks_ui->hide_bookmark_button) {
311       warnings->push_back(InstallWarning(
312             ErrorUtils::FormatErrorMessage(
313                 manifest_errors::kKeyIsDeprecatedWithReplacement,
314                 manifest_keys::kHideBookmarkButton,
315                 manifest_keys::kRemoveButton)));
316     }
317   }
318
319   return true;
320 }
321
322 ManifestPermission* SettingsOverridesHandler::CreatePermission() {
323   return new ManifestPermissionImpl(false);
324 }
325
326 ManifestPermission* SettingsOverridesHandler::CreateInitialRequiredPermission(
327     const Extension* extension) {
328   const SettingsOverrides* data = SettingsOverrides::Get(extension);
329   if (data)
330     return data->manifest_permission->Clone();
331   return NULL;
332 }
333 const std::vector<std::string> SettingsOverridesHandler::Keys() const {
334   return SingleKey(manifest_keys::kSettingsOverride);
335 }
336
337 }  // namespace extensions