• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "extensions/common/error_utils.h"
13 #include "extensions/common/extension_set.h"
14 #include "extensions/common/feature_switch.h"
15 #include "extensions/common/manifest_constants.h"
16 #include "extensions/common/manifest_handlers/permissions_parser.h"
17 #include "extensions/common/permissions/api_permission_set.h"
18 #include "extensions/common/permissions/manifest_permission.h"
19 #include "extensions/common/permissions/permissions_info.h"
20 #include "extensions/common/permissions/settings_override_permission.h"
21 #include "grit/generated_resources.h"
22 #include "ipc/ipc_message.h"
23 #include "ipc/ipc_message_utils.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "url/gurl.h"
26 
27 using extensions::api::manifest_types::ChromeSettingsOverrides;
28 
29 namespace extensions {
30 namespace {
31 
32 const char* kWwwPrefix = "www.";
33 
CreateManifestURL(const std::string & url)34 scoped_ptr<GURL> CreateManifestURL(const std::string& url) {
35   scoped_ptr<GURL> manifest_url(new GURL(url));
36   if (!manifest_url->is_valid() ||
37       !manifest_url->SchemeIsHTTPOrHTTPS())
38     return scoped_ptr<GURL>();
39   return manifest_url.Pass();
40 }
41 
ParseHomepage(const ChromeSettingsOverrides & overrides,base::string16 * error)42 scoped_ptr<GURL> ParseHomepage(const ChromeSettingsOverrides& overrides,
43                                base::string16* error) {
44   if (!overrides.homepage)
45     return scoped_ptr<GURL>();
46   scoped_ptr<GURL> manifest_url = CreateManifestURL(*overrides.homepage);
47   if (!manifest_url) {
48     *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
49         manifest_errors::kInvalidHomepageOverrideURL, *overrides.homepage);
50   }
51   return manifest_url.Pass();
52 }
53 
ParseStartupPage(const ChromeSettingsOverrides & overrides,base::string16 * error)54 std::vector<GURL> ParseStartupPage(const ChromeSettingsOverrides& overrides,
55                                    base::string16* error) {
56   std::vector<GURL> urls;
57   if (!overrides.startup_pages)
58     return urls;
59 
60   for (std::vector<std::string>::const_iterator i =
61        overrides.startup_pages->begin(); i != overrides.startup_pages->end();
62        ++i) {
63     scoped_ptr<GURL> manifest_url = CreateManifestURL(*i);
64     if (!manifest_url) {
65       *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
66           manifest_errors::kInvalidStartupOverrideURL, *i);
67     } else {
68       urls.push_back(GURL());
69       urls.back().Swap(manifest_url.get());
70     }
71   }
72   return urls;
73 }
74 
ParseSearchEngine(ChromeSettingsOverrides * overrides,base::string16 * error)75 scoped_ptr<ChromeSettingsOverrides::Search_provider> ParseSearchEngine(
76     ChromeSettingsOverrides* overrides,
77     base::string16* error) {
78   if (!overrides->search_provider)
79     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
80   if (!CreateManifestURL(overrides->search_provider->search_url)) {
81     *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
82         manifest_errors::kInvalidSearchEngineURL,
83         overrides->search_provider->search_url);
84     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
85   }
86   if (overrides->search_provider->prepopulated_id)
87     return overrides->search_provider.Pass();
88   if (!overrides->search_provider->name ||
89       !overrides->search_provider->keyword ||
90       !overrides->search_provider->encoding ||
91       !overrides->search_provider->favicon_url) {
92     *error =
93         base::ASCIIToUTF16(manifest_errors::kInvalidSearchEngineMissingKeys);
94     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
95   }
96   if (!CreateManifestURL(*overrides->search_provider->favicon_url)) {
97     *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
98         manifest_errors::kInvalidSearchEngineURL,
99         *overrides->search_provider->favicon_url);
100     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
101   }
102   return overrides->search_provider.Pass();
103 }
104 
105 // A www. prefix is not informative and thus not worth the limited real estate
106 // in the permissions UI.
RemoveWwwPrefix(const std::string & url)107 std::string RemoveWwwPrefix(const std::string& url) {
108   if (StartsWithASCII(url, kWwwPrefix, false))
109     return url.substr(strlen(kWwwPrefix));
110   return url;
111 }
112 
113 }  // namespace
114 
SettingsOverrides()115 SettingsOverrides::SettingsOverrides() {}
116 
~SettingsOverrides()117 SettingsOverrides::~SettingsOverrides() {}
118 
119 // static
Get(const Extension * extension)120 const SettingsOverrides* SettingsOverrides::Get(
121     const Extension* extension) {
122   return static_cast<SettingsOverrides*>(
123       extension->GetManifestData(manifest_keys::kSettingsOverride));
124 }
125 
SettingsOverridesHandler()126 SettingsOverridesHandler::SettingsOverridesHandler() {}
127 
~SettingsOverridesHandler()128 SettingsOverridesHandler::~SettingsOverridesHandler() {}
129 
Parse(Extension * extension,base::string16 * error)130 bool SettingsOverridesHandler::Parse(Extension* extension,
131                                      base::string16* error) {
132   const base::Value* dict = NULL;
133   CHECK(extension->manifest()->Get(manifest_keys::kSettingsOverride, &dict));
134   scoped_ptr<ChromeSettingsOverrides> settings(
135       ChromeSettingsOverrides::FromValue(*dict, error));
136   if (!settings)
137     return false;
138 
139   scoped_ptr<SettingsOverrides> info(new SettingsOverrides);
140   info->homepage = ParseHomepage(*settings, error);
141   info->search_engine = ParseSearchEngine(settings.get(), error);
142   info->startup_pages = ParseStartupPage(*settings, error);
143   if (!info->homepage && !info->search_engine && info->startup_pages.empty()) {
144     *error = ErrorUtils::FormatErrorMessageUTF16(
145         manifest_errors::kInvalidEmptyDictionary,
146         manifest_keys::kSettingsOverride);
147     return false;
148   }
149 
150   if (info->search_engine) {
151     PermissionsParser::AddAPIPermission(
152         extension,
153         new SettingsOverrideAPIPermission(
154             PermissionsInfo::GetInstance()->GetByID(
155                 APIPermission::kSearchProvider),
156             RemoveWwwPrefix(CreateManifestURL(info->search_engine->search_url)
157                                 ->GetOrigin()
158                                 .host())));
159   }
160   if (!info->startup_pages.empty()) {
161     PermissionsParser::AddAPIPermission(
162         extension,
163         new SettingsOverrideAPIPermission(
164             PermissionsInfo::GetInstance()->GetByID(
165                 APIPermission::kStartupPages),
166             // We only support one startup page even though the type of the
167             // manifest
168             // property is a list, only the first one is used.
169             RemoveWwwPrefix(info->startup_pages[0].GetContent())));
170   }
171   if (info->homepage) {
172     PermissionsParser::AddAPIPermission(
173         extension,
174         new SettingsOverrideAPIPermission(
175             PermissionsInfo::GetInstance()->GetByID(APIPermission::kHomepage),
176             RemoveWwwPrefix(info->homepage.get()->GetContent())));
177   }
178   extension->SetManifestData(manifest_keys::kSettingsOverride,
179                              info.release());
180   return true;
181 }
182 
Keys() const183 const std::vector<std::string> SettingsOverridesHandler::Keys() const {
184   return SingleKey(manifest_keys::kSettingsOverride);
185 }
186 
187 }  // namespace extensions
188