Ignore non-active fullscreen windows for shelf state.
[chromium-blink-merge.git] / extensions / common / manifest_handlers / background_info.cc
blob1ec404eaea1826304979e4e594d0e4e8bcc0011d
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 "extensions/common/manifest_handlers/background_info.h"
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/lazy_instance.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "extensions/common/constants.h"
14 #include "extensions/common/error_utils.h"
15 #include "extensions/common/file_util.h"
16 #include "extensions/common/manifest_constants.h"
17 #include "extensions/common/permissions/api_permission_set.h"
18 #include "extensions/common/permissions/permissions_data.h"
19 #include "extensions/common/switches.h"
20 #include "grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util.h"
23 using base::DictionaryValue;
25 namespace extensions {
27 namespace keys = manifest_keys;
28 namespace values = manifest_values;
29 namespace errors = manifest_errors;
31 namespace {
33 const char kBackground[] = "background";
35 static base::LazyInstance<BackgroundInfo> g_empty_background_info =
36 LAZY_INSTANCE_INITIALIZER;
38 const BackgroundInfo& GetBackgroundInfo(const Extension* extension) {
39 BackgroundInfo* info = static_cast<BackgroundInfo*>(
40 extension->GetManifestData(kBackground));
41 if (!info)
42 return g_empty_background_info.Get();
43 return *info;
46 } // namespace
48 BackgroundInfo::BackgroundInfo()
49 : is_persistent_(true),
50 allow_js_access_(true) {
53 BackgroundInfo::~BackgroundInfo() {
56 // static
57 GURL BackgroundInfo::GetBackgroundURL(const Extension* extension) {
58 const BackgroundInfo& info = GetBackgroundInfo(extension);
59 if (info.background_scripts_.empty())
60 return info.background_url_;
61 return extension->GetResourceURL(kGeneratedBackgroundPageFilename);
64 // static
65 bool BackgroundInfo::HasGeneratedBackgroundPage(const Extension* extension) {
66 const BackgroundInfo& info = GetBackgroundInfo(extension);
67 return !info.background_scripts_.empty();
70 // static
71 const std::vector<std::string>& BackgroundInfo::GetBackgroundScripts(
72 const Extension* extension) {
73 return GetBackgroundInfo(extension).background_scripts_;
76 // static
77 bool BackgroundInfo::HasBackgroundPage(const Extension* extension) {
78 return GetBackgroundInfo(extension).has_background_page();
81 // static
82 bool BackgroundInfo::AllowJSAccess(const Extension* extension) {
83 return GetBackgroundInfo(extension).allow_js_access_;
86 // static
87 bool BackgroundInfo::HasPersistentBackgroundPage(const Extension* extension) {
88 return GetBackgroundInfo(extension).has_persistent_background_page();
91 // static
92 bool BackgroundInfo::HasLazyBackgroundPage(const Extension* extension) {
93 return GetBackgroundInfo(extension).has_lazy_background_page();
96 bool BackgroundInfo::Parse(const Extension* extension, string16* error) {
97 const std::string& bg_scripts_key = extension->is_platform_app() ?
98 keys::kPlatformAppBackgroundScripts : keys::kBackgroundScripts;
99 if (!LoadBackgroundScripts(extension, bg_scripts_key, error) ||
100 !LoadBackgroundPage(extension, error) ||
101 !LoadBackgroundPersistent(extension, error) ||
102 !LoadAllowJSAccess(extension, error)) {
103 return false;
105 return true;
108 bool BackgroundInfo::LoadBackgroundScripts(const Extension* extension,
109 const std::string& key,
110 string16* error) {
111 const base::Value* background_scripts_value = NULL;
112 if (!extension->manifest()->Get(key, &background_scripts_value))
113 return true;
115 CHECK(background_scripts_value);
116 if (background_scripts_value->GetType() != base::Value::TYPE_LIST) {
117 *error = ASCIIToUTF16(errors::kInvalidBackgroundScripts);
118 return false;
121 const base::ListValue* background_scripts = NULL;
122 background_scripts_value->GetAsList(&background_scripts);
123 for (size_t i = 0; i < background_scripts->GetSize(); ++i) {
124 std::string script;
125 if (!background_scripts->GetString(i, &script)) {
126 *error = ErrorUtils::FormatErrorMessageUTF16(
127 errors::kInvalidBackgroundScript, base::IntToString(i));
128 return false;
130 background_scripts_.push_back(script);
133 return true;
136 bool BackgroundInfo::LoadBackgroundPage(const Extension* extension,
137 const std::string& key,
138 string16* error) {
139 const base::Value* background_page_value = NULL;
140 if (!extension->manifest()->Get(key, &background_page_value))
141 return true;
143 if (!background_scripts_.empty()) {
144 *error = ASCIIToUTF16(errors::kInvalidBackgroundCombination);
145 return false;
148 std::string background_str;
149 if (!background_page_value->GetAsString(&background_str)) {
150 *error = ASCIIToUTF16(errors::kInvalidBackground);
151 return false;
154 if (extension->is_hosted_app()) {
155 background_url_ = GURL(background_str);
157 if (!PermissionsData::GetInitialAPIPermissions(extension)->count(
158 APIPermission::kBackground)) {
159 *error = ASCIIToUTF16(errors::kBackgroundPermissionNeeded);
160 return false;
162 // Hosted apps require an absolute URL.
163 if (!background_url_.is_valid()) {
164 *error = ASCIIToUTF16(errors::kInvalidBackgroundInHostedApp);
165 return false;
168 if (!(background_url_.SchemeIs("https") ||
169 (CommandLine::ForCurrentProcess()->HasSwitch(
170 switches::kAllowHTTPBackgroundPage) &&
171 background_url_.SchemeIs("http")))) {
172 *error = ASCIIToUTF16(errors::kInvalidBackgroundInHostedApp);
173 return false;
175 } else {
176 background_url_ = extension->GetResourceURL(background_str);
179 return true;
182 bool BackgroundInfo::LoadBackgroundPage(const Extension* extension,
183 string16* error) {
184 if (extension->is_platform_app()) {
185 return LoadBackgroundPage(
186 extension, keys::kPlatformAppBackgroundPage, error);
189 if (!LoadBackgroundPage(extension, keys::kBackgroundPage, error))
190 return false;
191 if (background_url_.is_empty())
192 return LoadBackgroundPage(extension, keys::kBackgroundPageLegacy, error);
193 return true;
196 bool BackgroundInfo::LoadBackgroundPersistent(const Extension* extension,
197 string16* error) {
198 if (extension->is_platform_app()) {
199 is_persistent_ = false;
200 return true;
203 const base::Value* background_persistent = NULL;
204 if (!extension->manifest()->Get(keys::kBackgroundPersistent,
205 &background_persistent))
206 return true;
208 if (!background_persistent->GetAsBoolean(&is_persistent_)) {
209 *error = ASCIIToUTF16(errors::kInvalidBackgroundPersistent);
210 return false;
213 if (!has_background_page()) {
214 *error = ASCIIToUTF16(errors::kInvalidBackgroundPersistentNoPage);
215 return false;
218 return true;
221 bool BackgroundInfo::LoadAllowJSAccess(const Extension* extension,
222 string16* error) {
223 const base::Value* allow_js_access = NULL;
224 if (!extension->manifest()->Get(keys::kBackgroundAllowJsAccess,
225 &allow_js_access))
226 return true;
228 if (!allow_js_access->IsType(base::Value::TYPE_BOOLEAN) ||
229 !allow_js_access->GetAsBoolean(&allow_js_access_)) {
230 *error = ASCIIToUTF16(errors::kInvalidBackgroundAllowJsAccess);
231 return false;
234 return true;
237 BackgroundManifestHandler::BackgroundManifestHandler() {
240 BackgroundManifestHandler::~BackgroundManifestHandler() {
243 bool BackgroundManifestHandler::Parse(Extension* extension, string16* error) {
244 scoped_ptr<BackgroundInfo> info(new BackgroundInfo);
245 if (!info->Parse(extension, error))
246 return false;
248 // Platform apps must have background pages.
249 if (extension->is_platform_app() && !info->has_background_page()) {
250 *error = ASCIIToUTF16(errors::kBackgroundRequiredForPlatformApps);
251 return false;
253 // Lazy background pages are incompatible with the webRequest API.
254 if (info->has_lazy_background_page() &&
255 PermissionsData::GetInitialAPIPermissions(extension)->count(
256 APIPermission::kWebRequest)) {
257 *error = ASCIIToUTF16(errors::kWebRequestConflictsWithLazyBackground);
258 return false;
261 extension->SetManifestData(kBackground, info.release());
262 return true;
265 bool BackgroundManifestHandler::Validate(
266 const Extension* extension,
267 std::string* error,
268 std::vector<InstallWarning>* warnings) const {
269 // Validate that background scripts exist.
270 const std::vector<std::string>& background_scripts =
271 BackgroundInfo::GetBackgroundScripts(extension);
272 for (size_t i = 0; i < background_scripts.size(); ++i) {
273 if (!base::PathExists(
274 extension->GetResource(background_scripts[i]).GetFilePath())) {
275 *error = l10n_util::GetStringFUTF8(
276 IDS_EXTENSION_LOAD_BACKGROUND_SCRIPT_FAILED,
277 UTF8ToUTF16(background_scripts[i]));
278 return false;
282 // Validate background page location, except for hosted apps, which should use
283 // an external URL. Background page for hosted apps are verified when the
284 // extension is created (in Extension::InitFromValue)
285 if (BackgroundInfo::HasBackgroundPage(extension) &&
286 !extension->is_hosted_app() && background_scripts.empty()) {
287 base::FilePath page_path = file_util::ExtensionURLToRelativeFilePath(
288 BackgroundInfo::GetBackgroundURL(extension));
289 const base::FilePath path = extension->GetResource(page_path).GetFilePath();
290 if (path.empty() || !base::PathExists(path)) {
291 *error =
292 l10n_util::GetStringFUTF8(
293 IDS_EXTENSION_LOAD_BACKGROUND_PAGE_FAILED,
294 page_path.LossyDisplayName());
295 return false;
298 return true;
301 bool BackgroundManifestHandler::AlwaysParseForType(Manifest::Type type) const {
302 return type == Manifest::TYPE_PLATFORM_APP;
305 const std::vector<std::string> BackgroundManifestHandler::Keys() const {
306 static const char* keys[] = {
307 keys::kBackgroundAllowJsAccess,
308 keys::kBackgroundPage,
309 keys::kBackgroundPageLegacy,
310 keys::kBackgroundPersistent,
311 keys::kBackgroundScripts,
312 keys::kPlatformAppBackgroundPage,
313 keys::kPlatformAppBackgroundScripts
315 return std::vector<std::string>(keys, keys + arraysize(keys));
318 } // namespace extensions