1 // Copyright 2014 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/browser/apps/install_chrome_app.h" 6 7 #include "base/basictypes.h" 8 #include "base/command_line.h" 9 #include "base/strings/stringprintf.h" 10 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/extensions/webstore_install_with_prompt.h" 12 #include "chrome/browser/extensions/webstore_standalone_installer.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/browser_list.h" 16 #include "chrome/browser/ui/browser_window.h" 17 #include "chrome/common/extensions/webstore_install_result.h" 18 #include "components/crx_file/id_util.h" 19 #include "extensions/browser/extension_registry.h" 20 #include "extensions/common/manifest_constants.h" 21 22 using extensions::ExtensionRegistry; 23 24 namespace { 25 26 // The URL to the webstore page for a specific app. 27 const char kWebstoreUrlFormat[] = 28 "https://chrome.google.com/webstore/detail/%s"; 29 30 // Error given when the extension is not an app. 31 const char kInstallChromeAppErrorNotAnApp[] = 32 "--install-chrome-app can only be used to install apps."; 33 34 // Returns the webstore URL for an app. 35 GURL GetAppInstallUrl(const std::string& app_id) { 36 return GURL(base::StringPrintf(kWebstoreUrlFormat, app_id.c_str())); 37 } 38 39 // Checks the manifest and completes the installation with NOT_PERMITTED if the 40 // extension is not an app. 41 class WebstoreInstallWithPromptAppsOnly 42 : public extensions::WebstoreInstallWithPrompt { 43 public: 44 WebstoreInstallWithPromptAppsOnly(const std::string& app_id, 45 Profile* profile, 46 gfx::NativeWindow parent_window) 47 : WebstoreInstallWithPrompt( 48 app_id, 49 profile, 50 parent_window, 51 extensions::WebstoreStandaloneInstaller::Callback()) {} 52 53 private: 54 virtual ~WebstoreInstallWithPromptAppsOnly() {} 55 56 // extensions::WebstoreStandaloneInstaller overrides: 57 virtual void OnManifestParsed() OVERRIDE; 58 59 DISALLOW_COPY_AND_ASSIGN(WebstoreInstallWithPromptAppsOnly); 60 }; 61 62 void WebstoreInstallWithPromptAppsOnly::OnManifestParsed() { 63 if (!manifest()->HasKey(extensions::manifest_keys::kApp)) { 64 CompleteInstall(extensions::webstore_install::NOT_PERMITTED, 65 kInstallChromeAppErrorNotAnApp); 66 return; 67 } 68 69 ProceedWithInstallPrompt(); 70 } 71 72 } // namespace 73 74 namespace install_chrome_app { 75 76 void InstallChromeApp(const std::string& app_id) { 77 if (!crx_file::id_util::IdIsValid(app_id)) 78 return; 79 80 // At the moment InstallChromeApp() is called immediately after handling 81 // startup URLs, so a browser is guaranteed to be created. If that changes we 82 // may need to start a browser or browser session here. 83 Browser* browser = 84 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->get(0); 85 DCHECK(browser); 86 87 content::OpenURLParams params(GetAppInstallUrl(app_id), 88 content::Referrer(), 89 NEW_FOREGROUND_TAB, 90 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, 91 false); 92 browser->OpenURL(params); 93 94 ExtensionRegistry* registry = ExtensionRegistry::Get(browser->profile()); 95 // Skip if this app is already installed or blacklisted. For disabled or 96 // or terminated apps, going through the installation flow should re-enable 97 // them. 98 const extensions::Extension* installed_extension = registry->GetExtensionById( 99 app_id, ExtensionRegistry::ENABLED | ExtensionRegistry::BLACKLISTED); 100 // TODO(jackhou): For installed apps, maybe we should do something better, 101 // e.g. show the app list (and re-add it to the taskbar). 102 if (installed_extension) 103 return; 104 105 WebstoreInstallWithPromptAppsOnly* installer = 106 new WebstoreInstallWithPromptAppsOnly( 107 app_id, browser->profile(), browser->window()->GetNativeWindow()); 108 installer->BeginInstall(); 109 } 110 111 } // namespace install_chrome_app 112