1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/command_line.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/lazy_instance.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/values.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/url_constants.h"
150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/cloud_devices/common/cloud_devices_urls.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/constants.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "extensions/common/error_utils.h"
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace extensions {
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace keys = manifest_keys;
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace values = manifest_values;
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors;
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ReadLaunchDimension(const extensions::Manifest* manifest,
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         const char* key,
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         int* target,
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         bool is_valid_container,
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         base::string16* error) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Value* temp = NULL;
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (manifest->Get(key, &temp)) {
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_valid_container) {
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          errors::kInvalidLaunchValueContainer,
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          key);
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!temp->GetAsInteger(target) || *target < 0) {
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *target = 0;
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          errors::kInvalidLaunchValue,
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          key);
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static base::LazyInstance<AppLaunchInfo> g_empty_app_launch_info =
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const AppLaunchInfo& GetAppLaunchInfo(const Extension* extension) {
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AppLaunchInfo* info = static_cast<AppLaunchInfo*>(
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      extension->GetManifestData(keys::kLaunch));
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return info ? *info : g_empty_app_launch_info.Get();
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AppLaunchInfo::AppLaunchInfo()
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : launch_container_(LAUNCH_CONTAINER_TAB),
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      launch_width_(0),
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      launch_height_(0) {
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AppLaunchInfo::~AppLaunchInfo() {
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const std::string& AppLaunchInfo::GetLaunchLocalPath(
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const Extension* extension) {
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAppLaunchInfo(extension).launch_local_path_;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const GURL& AppLaunchInfo::GetLaunchWebURL(
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const Extension* extension) {
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAppLaunchInfo(extension).launch_web_url_;
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)extensions::LaunchContainer AppLaunchInfo::GetLaunchContainer(
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const Extension* extension) {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAppLaunchInfo(extension).launch_container_;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int AppLaunchInfo::GetLaunchWidth(const Extension* extension) {
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAppLaunchInfo(extension).launch_width_;
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int AppLaunchInfo::GetLaunchHeight(const Extension* extension) {
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetAppLaunchInfo(extension).launch_height_;
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)GURL AppLaunchInfo::GetFullLaunchURL(const Extension* extension) {
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const AppLaunchInfo& info = GetAppLaunchInfo(extension);
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (info.launch_local_path_.empty())
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return info.launch_web_url_;
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return extension->url().Resolve(info.launch_local_path_);
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool AppLaunchInfo::Parse(Extension* extension, base::string16* error) {
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!LoadLaunchURL(extension, error) ||
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !LoadLaunchContainer(extension, error))
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool AppLaunchInfo::LoadLaunchURL(Extension* extension, base::string16* error) {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Value* temp = NULL;
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Launch URL can be either local (to chrome-extension:// root) or an absolute
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // web URL.
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (extension->manifest()->Get(keys::kLaunchLocalPath, &temp)) {
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (extension->manifest()->Get(keys::kLaunchWebURL, NULL)) {
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *error = base::ASCIIToUTF16(errors::kLaunchPathAndURLAreExclusive);
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (extension->manifest()->Get(keys::kWebURLs, NULL)) {
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *error = base::ASCIIToUTF16(errors::kLaunchPathAndExtentAreExclusive);
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string launch_path;
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!temp->GetAsString(&launch_path)) {
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          errors::kInvalidLaunchValue,
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          keys::kLaunchLocalPath);
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Ensure the launch path is a valid relative URL.
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GURL resolved = extension->url().Resolve(launch_path);
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!resolved.is_valid() || resolved.GetOrigin() != extension->url()) {
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          errors::kInvalidLaunchValue,
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          keys::kLaunchLocalPath);
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    launch_local_path_ = launch_path;
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (extension->manifest()->Get(keys::kLaunchWebURL, &temp)) {
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string launch_url;
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!temp->GetAsString(&launch_url)) {
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          errors::kInvalidLaunchValue,
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          keys::kLaunchWebURL);
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Ensure the launch web URL is a valid absolute URL and web extent scheme.
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GURL url(launch_url);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    URLPattern pattern(Extension::kValidWebExtentSchemes);
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!url.is_valid() || !pattern.SetScheme(url.scheme())) {
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          errors::kInvalidLaunchValue,
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          keys::kLaunchWebURL);
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    launch_web_url_ = url;
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (extension->is_legacy_packaged_app()) {
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *error = base::ASCIIToUTF16(errors::kLaunchURLRequired);
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // For the Chrome component app, override launch url to new tab.
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (extension->id() == extension_misc::kChromeAppId) {
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    launch_web_url_ = GURL(chrome::kChromeUINewTabURL);
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If there is no extent, we default the extent based on the launch URL.
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (extension->web_extent().is_empty() && !launch_web_url_.is_empty()) {
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    URLPattern pattern(Extension::kValidWebExtentSchemes);
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!pattern.SetScheme("*")) {
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          errors::kInvalidLaunchValue,
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          keys::kLaunchWebURL);
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pattern.SetHost(launch_web_url_.host());
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pattern.SetPath("/*");
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    extension->AddWebExtentPattern(pattern);
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // In order for the --apps-gallery-url switch to work with the gallery
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // process isolation, we must insert any provided value into the component
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // app's launch url and web extent.
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (extension->id() == extensions::kWebStoreAppId) {
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string gallery_url_str = CommandLine::ForCurrentProcess()->
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GetSwitchValueASCII(switches::kAppsGalleryURL);
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Empty string means option was not used.
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!gallery_url_str.empty()) {
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GURL gallery_url(gallery_url_str);
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      OverrideLaunchURL(extension, gallery_url);
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (extension->id() == extension_misc::kCloudPrintAppId) {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // In order for the --cloud-print-service switch to work, we must update
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // the launch URL and web extent.
2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    GURL url =
2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        cloud_devices::GetCloudPrintRelativeURL("enable_chrome_connector");
2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!url.is_empty()) {
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      OverrideLaunchURL(extension, url);
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool AppLaunchInfo::LoadLaunchContainer(Extension* extension,
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                        base::string16* error) {
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Value* tmp_launcher_container = NULL;
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!extension->manifest()->Get(keys::kLaunchContainer,
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  &tmp_launcher_container))
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string launch_container_string;
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!tmp_launcher_container->GetAsString(&launch_container_string)) {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *error = base::ASCIIToUTF16(errors::kInvalidLaunchContainer);
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (launch_container_string == values::kLaunchContainerPanel) {
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    launch_container_ = LAUNCH_CONTAINER_PANEL;
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (launch_container_string == values::kLaunchContainerTab) {
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    launch_container_ = LAUNCH_CONTAINER_TAB;
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *error = base::ASCIIToUTF16(errors::kInvalidLaunchContainer);
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool can_specify_initial_size = launch_container_ == LAUNCH_CONTAINER_PANEL;
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Validate the container width if present.
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ReadLaunchDimension(extension->manifest(),
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           keys::kLaunchWidth,
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           &launch_width_,
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           can_specify_initial_size,
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           error)) {
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Validate container height if present.
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ReadLaunchDimension(extension->manifest(),
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           keys::kLaunchHeight,
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           &launch_height_,
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           can_specify_initial_size,
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           error)) {
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AppLaunchInfo::OverrideLaunchURL(Extension* extension,
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      GURL override_url) {
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!override_url.is_valid()) {
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DLOG(WARNING) << "Invalid override url given for " << extension->name();
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (override_url.has_port()) {
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DLOG(WARNING) << "Override URL passed for " << extension->name()
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  << " should not contain a port.  Removing it.";
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GURL::Replacements remove_port;
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    remove_port.ClearPort();
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    override_url = override_url.ReplaceComponents(remove_port);
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  launch_web_url_ = override_url;
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  URLPattern pattern(Extension::kValidWebExtentSchemes);
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  URLPattern::ParseResult result = pattern.Parse(override_url.spec());
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(result, URLPattern::PARSE_SUCCESS);
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  pattern.SetPath(pattern.path() + '*');
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extension->AddWebExtentPattern(pattern);
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AppLaunchManifestHandler::AppLaunchManifestHandler() {
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AppLaunchManifestHandler::~AppLaunchManifestHandler() {
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool AppLaunchManifestHandler::Parse(Extension* extension,
296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                     base::string16* error) {
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<AppLaunchInfo> info(new AppLaunchInfo);
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!info->Parse(extension, error))
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extension->SetManifestData(keys::kLaunch, info.release());
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool AppLaunchManifestHandler::AlwaysParseForType(Manifest::Type type) const {
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return type == Manifest::TYPE_LEGACY_PACKAGED_APP;
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const std::vector<std::string> AppLaunchManifestHandler::Keys() const {
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static const char* keys[] = {
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    keys::kLaunchLocalPath,
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    keys::kLaunchWebURL,
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    keys::kLaunchContainer,
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    keys::kLaunchHeight,
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    keys::kLaunchWidth
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return std::vector<std::string>(keys, keys + arraysize(keys));
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace extensions
320