15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/webstore_standalone_installer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/crx_installer.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_install_prompt.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_install_ui.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/webstore_data_fetcher.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kManifestKey[] = "manifest";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kIconUrlKey[] = "icon_url";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kLocalizedNameKey[] = "localized_name";
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kLocalizedDescriptionKey[] = "localized_description";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUsersKey[] = "users";
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kShowUserCountKey[] = "show_user_count";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAverageRatingKey[] = "average_rating";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRatingCountKey[] = "rating_count";
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRedirectUrlKey[] = "redirect_url";
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kWebstoreRequestError[] =
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Could not fetch data from the Chrome Web Store";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidManifestError[] = "Invalid manifest";
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserCancelledError[] = "User cancelled install";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& webstore_item_id,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile,
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Callback& callback)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : id_(webstore_item_id),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(callback),
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_(profile),
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      show_user_count_(true),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      average_rating_(0.0),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rating_count_(0) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(!callback_.is_null());
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Private interface implementation.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::BeginInstall() {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddRef();  // Balanced in CompleteInstall or WebContentsDestroyed.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Extension::IdIsValid(id_)) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteInstall(kInvalidWebstoreItemId);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the requesting page as the referrer both since that is more correct
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (it is the page that caused this request to happen) and so that we can
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // track top sites that trigger inline install requests.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webstore_data_fetcher_.reset(new WebstoreDataFetcher(
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_->GetRequestContext(),
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetRequestorURL(),
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      id_));
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webstore_data_fetcher_->Start();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<ExtensionInstallPrompt>
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochWebstoreStandaloneInstaller::CreateInstallUI() {
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return make_scoped_ptr(new ExtensionInstallPrompt(GetWebContents()));
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CompleteInstall(kWebstoreRequestError);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* webstore_data) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CheckRequestorAlive()) {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CompleteInstall(std::string());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CheckInlineInstallPermitted(*webstore_data, &error)) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteInstall(error);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CheckRequestorPermitted(*webstore_data, &error)) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteInstall(error);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Manifest, number of users, average rating and rating count are required.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string manifest;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!webstore_data->GetString(kManifestKey, &manifest) ||
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteInstall(kInvalidWebstoreResponseError);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Optional.
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  show_user_count_ = true;
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  webstore_data->GetBoolean(kShowUserCountKey, &show_user_count_);
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating ||
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteInstall(kInvalidWebstoreResponseError);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Localized name and description are optional.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((webstore_data->HasKey(kLocalizedNameKey) &&
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (webstore_data->HasKey(kLocalizedDescriptionKey) &&
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !webstore_data->GetString(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kLocalizedDescriptionKey, &localized_description_))) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompleteInstall(kInvalidWebstoreResponseError);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Icon URL is optional.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL icon_url;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (webstore_data->HasKey(kIconUrlKey)) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string icon_url_string;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CompleteInstall(kInvalidWebstoreResponseError);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        icon_url_string);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!icon_url.is_valid()) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CompleteInstall(kInvalidWebstoreResponseError);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Assume ownership of webstore_data.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webstore_data_.reset(webstore_data);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebstoreInstallHelper> helper =
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new WebstoreInstallHelper(this,
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                id_,
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                manifest,
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                std::string(),  // We don't have any icon data.
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                icon_url,
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                profile_->GetRequestContext());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The helper will call us back via OnWebstoreParseSucces or
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnWebstoreParseFailure.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper->Start();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteInstall(error);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SkBitmap& icon,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::DictionaryValue* manifest) {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_EQ(id_, id);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CheckRequestorAlive()) {
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CompleteInstall(std::string());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_.reset(manifest);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon_ = icon;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  install_prompt_ = CreateInstallPrompt();
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (install_prompt_) {
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ShowInstallUI();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Control flow finishes up in InstallUIProceed or InstallUIAbort.
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InstallUIProceed();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::OnWebstoreParseFailure(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InstallHelperResultCode result_code,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_message) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteInstall(error_message);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::InstallUIProceed() {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CheckRequestorAlive()) {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CompleteInstall(std::string());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebstoreInstaller::Approval> approval(
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          profile_,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          id_,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          scoped_ptr<base::DictionaryValue>(manifest_.get()->DeepCopy())));
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  approval->skip_post_install_ui = !ShouldShowPostInstallUI();
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  approval->use_app_installed_bubble = ShouldShowAppInstalledBubble();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_,
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &(GetWebContents()->GetController()),
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      id_,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      approval.Pass(),
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebstoreInstaller::FLAG_INLINE_INSTALL);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  installer->Start();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::InstallUIAbort(bool user_initiated) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteInstall(kUserCancelledError);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::OnExtensionInstallSuccess(
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(id_, id);
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteInstall(std::string());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebstoreInstaller::FailureReason cancelled) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(id_, id);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteInstall(error);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebstoreStandaloneInstaller::AbortInstall() {
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_.Reset();
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Abort any in-progress fetches.
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (webstore_data_fetcher_) {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    webstore_data_fetcher_.reset();
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Release();  // Matches the AddRef in BeginInstall.
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebstoreStandaloneInstaller::CompleteInstall(const std::string& error) {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clear webstore_data_fetcher_ so that WebContentsDestroyed will no longer
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // call Release in case the WebContents is destroyed before this object.
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher(
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webstore_data_fetcher_.Pass());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback_.is_null())
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Run(error.empty(), error);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Release();  // Matches the AddRef in BeginInstall.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochWebstoreStandaloneInstaller::ShowInstallUI() {
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  localized_extension_for_display_ =
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          manifest_.get(),
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          id_,
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          localized_name_,
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          localized_description_,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &error);
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!localized_extension_for_display_.get()) {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CompleteInstall(kInvalidManifestError);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  install_ui_ = CreateInstallUI();
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  install_ui_->ConfirmStandaloneInstall(
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      this, localized_extension_for_display_.get(), &icon_, *install_prompt_);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
286