Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / chrome / common / extensions / manifest_handlers / app_launch_info.cc
blob21381c32abecbb89ce75bd4bdf4a19511935ee8c
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/app_launch_info.h"
7 #include "base/command_line.h"
8 #include "base/lazy_instance.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/extensions/extension_constants.h"
14 #include "chrome/common/url_constants.h"
15 #include "components/cloud_devices/common/cloud_devices_urls.h"
16 #include "extensions/common/constants.h"
17 #include "extensions/common/error_utils.h"
18 #include "extensions/common/manifest_constants.h"
20 namespace extensions {
22 namespace keys = manifest_keys;
23 namespace values = manifest_values;
24 namespace errors = manifest_errors;
26 namespace {
28 bool ReadLaunchDimension(const extensions::Manifest* manifest,
29 const char* key,
30 int* target,
31 bool is_valid_container,
32 base::string16* error) {
33 const base::Value* temp = NULL;
34 if (manifest->Get(key, &temp)) {
35 if (!is_valid_container) {
36 *error = ErrorUtils::FormatErrorMessageUTF16(
37 errors::kInvalidLaunchValueContainer,
38 key);
39 return false;
41 if (!temp->GetAsInteger(target) || *target < 0) {
42 *target = 0;
43 *error = ErrorUtils::FormatErrorMessageUTF16(
44 errors::kInvalidLaunchValue,
45 key);
46 return false;
49 return true;
52 static base::LazyInstance<AppLaunchInfo> g_empty_app_launch_info =
53 LAZY_INSTANCE_INITIALIZER;
55 const AppLaunchInfo& GetAppLaunchInfo(const Extension* extension) {
56 AppLaunchInfo* info = static_cast<AppLaunchInfo*>(
57 extension->GetManifestData(keys::kLaunch));
58 return info ? *info : g_empty_app_launch_info.Get();
61 } // namespace
63 AppLaunchInfo::AppLaunchInfo()
64 : launch_container_(LAUNCH_CONTAINER_TAB),
65 launch_width_(0),
66 launch_height_(0) {
69 AppLaunchInfo::~AppLaunchInfo() {
72 // static
73 const std::string& AppLaunchInfo::GetLaunchLocalPath(
74 const Extension* extension) {
75 return GetAppLaunchInfo(extension).launch_local_path_;
78 // static
79 const GURL& AppLaunchInfo::GetLaunchWebURL(
80 const Extension* extension) {
81 return GetAppLaunchInfo(extension).launch_web_url_;
84 // static
85 extensions::LaunchContainer AppLaunchInfo::GetLaunchContainer(
86 const Extension* extension) {
87 return GetAppLaunchInfo(extension).launch_container_;
90 // static
91 int AppLaunchInfo::GetLaunchWidth(const Extension* extension) {
92 return GetAppLaunchInfo(extension).launch_width_;
95 // static
96 int AppLaunchInfo::GetLaunchHeight(const Extension* extension) {
97 return GetAppLaunchInfo(extension).launch_height_;
100 // static
101 GURL AppLaunchInfo::GetFullLaunchURL(const Extension* extension) {
102 const AppLaunchInfo& info = GetAppLaunchInfo(extension);
103 if (info.launch_local_path_.empty())
104 return info.launch_web_url_;
105 else
106 return extension->url().Resolve(info.launch_local_path_);
109 bool AppLaunchInfo::Parse(Extension* extension, base::string16* error) {
110 if (!LoadLaunchURL(extension, error) ||
111 !LoadLaunchContainer(extension, error))
112 return false;
113 return true;
116 bool AppLaunchInfo::LoadLaunchURL(Extension* extension, base::string16* error) {
117 const base::Value* temp = NULL;
119 // Launch URL can be either local (to chrome-extension:// root) or an absolute
120 // web URL.
121 if (extension->manifest()->Get(keys::kLaunchLocalPath, &temp)) {
122 if (extension->manifest()->Get(keys::kLaunchWebURL, NULL)) {
123 *error = base::ASCIIToUTF16(errors::kLaunchPathAndURLAreExclusive);
124 return false;
127 if (extension->manifest()->Get(keys::kWebURLs, NULL)) {
128 *error = base::ASCIIToUTF16(errors::kLaunchPathAndExtentAreExclusive);
129 return false;
132 std::string launch_path;
133 if (!temp->GetAsString(&launch_path)) {
134 *error = ErrorUtils::FormatErrorMessageUTF16(
135 errors::kInvalidLaunchValue,
136 keys::kLaunchLocalPath);
137 return false;
140 // Ensure the launch path is a valid relative URL.
141 GURL resolved = extension->url().Resolve(launch_path);
142 if (!resolved.is_valid() || resolved.GetOrigin() != extension->url()) {
143 *error = ErrorUtils::FormatErrorMessageUTF16(
144 errors::kInvalidLaunchValue,
145 keys::kLaunchLocalPath);
146 return false;
149 launch_local_path_ = launch_path;
150 } else if (extension->manifest()->Get(keys::kLaunchWebURL, &temp)) {
151 std::string launch_url;
152 if (!temp->GetAsString(&launch_url)) {
153 *error = ErrorUtils::FormatErrorMessageUTF16(
154 errors::kInvalidLaunchValue,
155 keys::kLaunchWebURL);
156 return false;
159 // Ensure the launch web URL is a valid absolute URL and web extent scheme.
160 GURL url(launch_url);
161 URLPattern pattern(Extension::kValidWebExtentSchemes);
162 if (!url.is_valid() || !pattern.SetScheme(url.scheme())) {
163 *error = ErrorUtils::FormatErrorMessageUTF16(
164 errors::kInvalidLaunchValue,
165 keys::kLaunchWebURL);
166 return false;
169 launch_web_url_ = url;
170 } else if (extension->is_legacy_packaged_app()) {
171 *error = base::ASCIIToUTF16(errors::kLaunchURLRequired);
172 return false;
175 // For the Chrome component app, override launch url to new tab.
176 if (extension->id() == extension_misc::kChromeAppId) {
177 launch_web_url_ = GURL(chrome::kChromeUINewTabURL);
178 return true;
181 // If there is no extent, we default the extent based on the launch URL.
182 if (extension->web_extent().is_empty() && !launch_web_url_.is_empty()) {
183 URLPattern pattern(Extension::kValidWebExtentSchemes);
184 if (!pattern.SetScheme("*")) {
185 *error = ErrorUtils::FormatErrorMessageUTF16(
186 errors::kInvalidLaunchValue,
187 keys::kLaunchWebURL);
188 return false;
190 pattern.SetHost(launch_web_url_.host());
191 pattern.SetPath("/*");
192 extension->AddWebExtentPattern(pattern);
195 // In order for the --apps-gallery-url switch to work with the gallery
196 // process isolation, we must insert any provided value into the component
197 // app's launch url and web extent.
198 if (extension->id() == extensions::kWebStoreAppId) {
199 std::string gallery_url_str =
200 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
201 switches::kAppsGalleryURL);
203 // Empty string means option was not used.
204 if (!gallery_url_str.empty()) {
205 GURL gallery_url(gallery_url_str);
206 OverrideLaunchURL(extension, gallery_url);
208 } else if (extension->id() == extension_misc::kCloudPrintAppId) {
209 // In order for the --cloud-print-service switch to work, we must update
210 // the launch URL and web extent.
211 GURL url =
212 cloud_devices::GetCloudPrintRelativeURL("enable_chrome_connector");
213 if (!url.is_empty()) {
214 OverrideLaunchURL(extension, url);
218 return true;
221 bool AppLaunchInfo::LoadLaunchContainer(Extension* extension,
222 base::string16* error) {
223 const base::Value* tmp_launcher_container = NULL;
224 if (!extension->manifest()->Get(keys::kLaunchContainer,
225 &tmp_launcher_container))
226 return true;
228 std::string launch_container_string;
229 if (!tmp_launcher_container->GetAsString(&launch_container_string)) {
230 *error = base::ASCIIToUTF16(errors::kInvalidLaunchContainer);
231 return false;
234 if (launch_container_string == values::kLaunchContainerPanel) {
235 launch_container_ = LAUNCH_CONTAINER_PANEL;
236 } else if (launch_container_string == values::kLaunchContainerTab) {
237 launch_container_ = LAUNCH_CONTAINER_TAB;
238 } else {
239 *error = base::ASCIIToUTF16(errors::kInvalidLaunchContainer);
240 return false;
243 bool can_specify_initial_size = launch_container_ == LAUNCH_CONTAINER_PANEL;
245 // Validate the container width if present.
246 if (!ReadLaunchDimension(extension->manifest(),
247 keys::kLaunchWidth,
248 &launch_width_,
249 can_specify_initial_size,
250 error)) {
251 return false;
254 // Validate container height if present.
255 if (!ReadLaunchDimension(extension->manifest(),
256 keys::kLaunchHeight,
257 &launch_height_,
258 can_specify_initial_size,
259 error)) {
260 return false;
263 return true;
266 void AppLaunchInfo::OverrideLaunchURL(Extension* extension,
267 GURL override_url) {
268 if (!override_url.is_valid()) {
269 DLOG(WARNING) << "Invalid override url given for " << extension->name();
270 return;
272 if (override_url.has_port()) {
273 DLOG(WARNING) << "Override URL passed for " << extension->name()
274 << " should not contain a port. Removing it.";
276 GURL::Replacements remove_port;
277 remove_port.ClearPort();
278 override_url = override_url.ReplaceComponents(remove_port);
281 launch_web_url_ = override_url;
283 URLPattern pattern(Extension::kValidWebExtentSchemes);
284 URLPattern::ParseResult result = pattern.Parse(override_url.spec());
285 DCHECK_EQ(result, URLPattern::PARSE_SUCCESS);
286 pattern.SetPath(pattern.path() + '*');
287 extension->AddWebExtentPattern(pattern);
290 AppLaunchManifestHandler::AppLaunchManifestHandler() {
293 AppLaunchManifestHandler::~AppLaunchManifestHandler() {
296 bool AppLaunchManifestHandler::Parse(Extension* extension,
297 base::string16* error) {
298 scoped_ptr<AppLaunchInfo> info(new AppLaunchInfo);
299 if (!info->Parse(extension, error))
300 return false;
301 extension->SetManifestData(keys::kLaunch, info.release());
302 return true;
305 bool AppLaunchManifestHandler::AlwaysParseForType(Manifest::Type type) const {
306 return type == Manifest::TYPE_LEGACY_PACKAGED_APP;
309 const std::vector<std::string> AppLaunchManifestHandler::Keys() const {
310 static const char* const keys[] = {
311 keys::kLaunchLocalPath,
312 keys::kLaunchWebURL,
313 keys::kLaunchContainer,
314 keys::kLaunchHeight,
315 keys::kLaunchWidth
317 return std::vector<std::string>(keys, keys + arraysize(keys));
320 } // namespace extensions