Home | History | Annotate | Download | only in apps
      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