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/ui/browser_list.h"
     12 #include "chrome/browser/ui/browser_navigator.h"
     13 #include "extensions/common/extension.h"
     14 #include "google_apis/gaia/gaia_urls.h"
     15 #include "net/url_request/url_fetcher.h"
     16 #include "net/url_request/url_fetcher_delegate.h"
     17 
     18 namespace {
     19 
     20 // The URL to the webstore page for a specific app. "_asi=1" instructs webstore
     21 // to immediately try to install the app if the referrer is the sign in page.
     22 // This is actually the short form of the URL which just redirects to the full
     23 // URL. Since "_asi=1" only works on the full url, we need to resolve it first
     24 // before navigating the user to it.
     25 const char kWebstoreUrlFormat[] =
     26     "https://chrome.google.com/webstore/detail/%s?_asi=1";
     27 
     28 // The URL for the sign in page, set as the referrer to webstore.
     29 const char kAccountsUrl[] = "https://accounts.google.com/ServiceLogin";
     30 
     31 // Returns the webstore URL for an app.
     32 GURL GetAppInstallUrl(const std::string& app_id) {
     33   return GURL(base::StringPrintf(kWebstoreUrlFormat, app_id.c_str()));
     34 }
     35 
     36 void NavigateToUrlWithAccountsReferrer(const GURL& url) {
     37   Browser* browser =
     38       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->get(0);
     39   if (!browser)
     40     return;
     41 
     42   chrome::NavigateParams params(
     43       browser, url, content::PAGE_TRANSITION_AUTO_TOPLEVEL);
     44   params.disposition = NEW_FOREGROUND_TAB;
     45   params.window_action = chrome::NavigateParams::SHOW_WINDOW;
     46   params.referrer = content::Referrer();
     47   params.referrer.url = GURL(kAccountsUrl);
     48   chrome::Navigate(&params);
     49 }
     50 
     51 class AppURLFetcher : net::URLFetcherDelegate {
     52  public:
     53   explicit AppURLFetcher(const std::string& app_id);
     54 
     55   // net::URLFetcherDelegate OVERRIDES:
     56   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
     57 
     58  private:
     59   virtual ~AppURLFetcher();
     60 
     61   scoped_ptr<net::URLFetcher> url_fetcher_;
     62 
     63   DISALLOW_COPY_AND_ASSIGN(AppURLFetcher);
     64 };
     65 
     66 AppURLFetcher::AppURLFetcher(const std::string& app_id) {
     67   url_fetcher_.reset(net::URLFetcher::Create(
     68       GetAppInstallUrl(app_id), net::URLFetcher::GET, this));
     69   url_fetcher_->SetRequestContext(g_browser_process->system_request_context());
     70   url_fetcher_->SetStopOnRedirect(true);
     71   url_fetcher_->Start();
     72 }
     73 
     74 AppURLFetcher::~AppURLFetcher() {
     75 }
     76 
     77 void AppURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
     78   if (source->GetResponseCode() == 301) {
     79     // Moved permanently.
     80     NavigateToUrlWithAccountsReferrer(source->GetURL());
     81   }
     82 
     83   delete this;
     84 }
     85 
     86 }  // namespace
     87 
     88 namespace install_chrome_app {
     89 
     90 void InstallChromeApp(const std::string& app_id) {
     91   if (!extensions::Extension::IdIsValid(app_id))
     92     return;
     93 
     94   new AppURLFetcher(app_id);
     95 }
     96 
     97 }  // namespace install_chrome_app
     98