diff options
author | asargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-08 20:29:05 +0000 |
---|---|---|
committer | asargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-08 20:29:05 +0000 |
commit | 734bcec86bf4716b86891c193277fa9fc502d2c3 (patch) | |
tree | 8e08233d0863ad122a04fba271d06b99d90dc1d9 /chrome/browser/extensions/webstore_inline_installer.cc | |
parent | 94e38532c83f13efa7cf93ff4ff98d24de8eabe4 (diff) | |
download | chromium_src-734bcec86bf4716b86891c193277fa9fc502d2c3.zip chromium_src-734bcec86bf4716b86891c193277fa9fc502d2c3.tar.gz chromium_src-734bcec86bf4716b86891c193277fa9fc502d2c3.tar.bz2 |
Switch install-from-webstore UI to use regular instead of inline install dialog
Also rename WebstoreInlineInstaller to WebstoreStandaloneInstaller, and add
an expectation to a browser test that we don't create any new browser windows.
TBR=sky@chromium.org (for the .gypi changes)
BUG=153000
Review URL: https://codereview.chromium.org/11028070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@160691 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions/webstore_inline_installer.cc')
-rw-r--r-- | chrome/browser/extensions/webstore_inline_installer.cc | 465 |
1 files changed, 0 insertions, 465 deletions
diff --git a/chrome/browser/extensions/webstore_inline_installer.cc b/chrome/browser/extensions/webstore_inline_installer.cc deleted file mode 100644 index 6800b75..0000000 --- a/chrome/browser/extensions/webstore_inline_installer.cc +++ /dev/null @@ -1,465 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/extensions/webstore_inline_installer.h" - -#include <vector> - -#include "base/bind.h" -#include "base/string_util.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/extensions/crx_installer.h" -#include "chrome/browser/extensions/extension_install_dialog.h" -#include "chrome/browser/extensions/extension_install_ui.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_utility_messages.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/extensions/url_pattern.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/utility_process_host.h" -#include "content/public/browser/utility_process_host_client.h" -#include "content/public/browser/web_contents.h" -#include "net/base/escape.h" -#include "net/base/load_flags.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_request_status.h" - -using content::BrowserThread; -using content::OpenURLParams; -using content::UtilityProcessHost; -using content::UtilityProcessHostClient; -using content::WebContents; - -namespace extensions { - -const char kManifestKey[] = "manifest"; -const char kIconUrlKey[] = "icon_url"; -const char kLocalizedNameKey[] = "localized_name"; -const char kLocalizedDescriptionKey[] = "localized_description"; -const char kUsersKey[] = "users"; -const char kAverageRatingKey[] = "average_rating"; -const char kRatingCountKey[] = "rating_count"; -const char kVerifiedSiteKey[] = "verified_site"; -const char kInlineInstallNotSupportedKey[] = "inline_install_not_supported"; -const char kRedirectUrlKey[] = "redirect_url"; - -const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID"; -const char kWebstoreRequestError[] = - "Could not fetch data from the Chrome Web Store"; -const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse"; -const char kInvalidManifestError[] = "Invalid manifest"; -const char kUserCancelledError[] = "User cancelled install"; -const char kNoVerifiedSiteError[] = - "Inline installs can only be initiated for Chrome Web Store items that " - "have a verified site"; -const char kNotFromVerifiedSiteError[] = - "Installs can only be initiated by the Chrome Web Store item's verified " - "site"; -const char kInlineInstallSupportedError[] = - "Inline installation is not supported for this item. The user will be " - "redirected to the Chrome Web Store."; - -class SafeWebstoreResponseParser : public UtilityProcessHostClient { - public: - SafeWebstoreResponseParser(WebstoreInlineInstaller *client, - const std::string& webstore_data) - : client_(client), - webstore_data_(webstore_data) {} - - void Start() { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&SafeWebstoreResponseParser::StartWorkOnIOThread, this)); - } - - void StartWorkOnIOThread() { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - UtilityProcessHost* host = - UtilityProcessHost::Create(this, BrowserThread::IO); - host->EnableZygote(); - host->Send(new ChromeUtilityMsg_ParseJSON(webstore_data_)); - } - - // Implementing pieces of the UtilityProcessHostClient interface. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(SafeWebstoreResponseParser, message) - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, - OnJSONParseSucceeded) - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, - OnJSONParseFailed) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; - } - - void OnJSONParseSucceeded(const ListValue& wrapper) { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - const Value* value = NULL; - CHECK(wrapper.Get(0, &value)); - if (value->IsType(Value::TYPE_DICTIONARY)) { - parsed_webstore_data_.reset( - static_cast<const DictionaryValue*>(value)->DeepCopy()); - } else { - error_ = kInvalidWebstoreResponseError; - } - - ReportResults(); - } - - virtual void OnJSONParseFailed(const std::string& error_message) { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - error_ = error_message; - ReportResults(); - } - - void ReportResults() { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&SafeWebstoreResponseParser::ReportResultOnUIThread, this)); - } - - void ReportResultOnUIThread() { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (error_.empty() && parsed_webstore_data_.get()) { - client_->OnWebstoreResponseParseSuccess(parsed_webstore_data_.release()); - } else { - client_->OnWebstoreResponseParseFailure(error_); - } - } - - private: - virtual ~SafeWebstoreResponseParser() {} - - WebstoreInlineInstaller* client_; - - std::string webstore_data_; - std::string error_; - scoped_ptr<DictionaryValue> parsed_webstore_data_; -}; - -WebstoreInlineInstaller::WebstoreInlineInstaller( - WebContents* web_contents, - std::string webstore_item_id, - VerifiedSiteRequired require_verified_site, - GURL requestor_url, - Callback callback) - : content::WebContentsObserver(web_contents), - id_(webstore_item_id), - require_verified_site_(require_verified_site == REQUIRE_VERIFIED_SITE), - requestor_url_(requestor_url), - callback_(callback), - skip_post_install_ui_(false), - average_rating_(0.0), - rating_count_(0) { - CHECK(!callback.is_null()); -} - -void WebstoreInlineInstaller::BeginInstall() { - AddRef(); // Balanced in CompleteInstall or WebContentsDestroyed. - - if (!Extension::IdIsValid(id_)) { - CompleteInstall(kInvalidWebstoreItemId); - return; - } - - GURL webstore_data_url(extension_urls::GetWebstoreItemJsonDataURL(id_)); - - webstore_data_url_fetcher_.reset(net::URLFetcher::Create( - webstore_data_url, net::URLFetcher::GET, this)); - Profile* profile = Profile::FromBrowserContext( - web_contents()->GetBrowserContext()); - webstore_data_url_fetcher_->SetRequestContext( - profile->GetRequestContext()); - // Use the requesting page as the referrer both since that is more correct - // (it is the page that caused this request to happen) and so that we can - // track top sites that trigger inline install requests. - webstore_data_url_fetcher_->SetReferrer(requestor_url_.spec()); - webstore_data_url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_DISABLE_CACHE); - webstore_data_url_fetcher_->Start(); -} - -WebstoreInlineInstaller::~WebstoreInlineInstaller() {} - -void WebstoreInlineInstaller::OnURLFetchComplete( - const net::URLFetcher* source) { - CHECK_EQ(webstore_data_url_fetcher_.get(), source); - // We shouldn't be getting UrlFetcher callbacks if the WebContents has gone - // away; we stop any in in-progress fetches in WebContentsDestroyed. - CHECK(web_contents()); - - if (!webstore_data_url_fetcher_->GetStatus().is_success() || - webstore_data_url_fetcher_->GetResponseCode() != 200) { - CompleteInstall(kWebstoreRequestError); - return; - } - - std::string webstore_json_data; - webstore_data_url_fetcher_->GetResponseAsString(&webstore_json_data); - webstore_data_url_fetcher_.reset(); - - scoped_refptr<SafeWebstoreResponseParser> parser = - new SafeWebstoreResponseParser(this, webstore_json_data); - // The parser will call us back via OnWebstoreResponseParseSucces or - // OnWebstoreResponseParseFailure. - parser->Start(); -} - -void WebstoreInlineInstaller::OnWebstoreResponseParseSuccess( - DictionaryValue* webstore_data) { - // Check if the tab has gone away in the meantime. - if (!web_contents()) { - CompleteInstall(""); - return; - } - - webstore_data_.reset(webstore_data); - - // The store may not support inline installs for this item, in which case - // we open the store-provided redirect URL in a new tab and abort the - // installation process. - bool inline_install_not_supported = false; - if (webstore_data->HasKey(kInlineInstallNotSupportedKey) && - !webstore_data->GetBoolean( - kInlineInstallNotSupportedKey, &inline_install_not_supported)) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - if (inline_install_not_supported) { - std::string redirect_url; - if (!webstore_data->GetString(kRedirectUrlKey, &redirect_url)) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - - web_contents()->OpenURL(OpenURLParams( - GURL(redirect_url), - content::Referrer(web_contents()->GetURL(), - WebKit::WebReferrerPolicyDefault), - NEW_FOREGROUND_TAB, - content::PAGE_TRANSITION_AUTO_BOOKMARK, - false)); - CompleteInstall(kInlineInstallSupportedError); - return; - } - - // Manifest, number of users, average rating and rating count are required. - std::string manifest; - if (!webstore_data->GetString(kManifestKey, &manifest) || - !webstore_data->GetString(kUsersKey, &localized_user_count_) || - !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) || - !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - - if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating || - average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - - // Localized name and description are optional. - if ((webstore_data->HasKey(kLocalizedNameKey) && - !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) || - (webstore_data->HasKey(kLocalizedDescriptionKey) && - !webstore_data->GetString( - kLocalizedDescriptionKey, &localized_description_))) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - - // Icon URL is optional. - GURL icon_url; - if (webstore_data->HasKey(kIconUrlKey)) { - std::string icon_url_string; - if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve( - icon_url_string); - if (!icon_url.is_valid()) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - } - - // Check for a verified site if required. - if (require_verified_site_) { - if (!webstore_data->HasKey(kVerifiedSiteKey)) { - CompleteInstall(kNoVerifiedSiteError); - return; - } - std::string verified_site; - if (!webstore_data->GetString(kVerifiedSiteKey, &verified_site)) { - CompleteInstall(kInvalidWebstoreResponseError); - return; - } - if (!IsRequestorURLInVerifiedSite(requestor_url_, verified_site)) { - CompleteInstall(kNotFromVerifiedSiteError); - return; - } - } - - scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper( - this, - id_, - manifest, - "", // We don't have any icon data. - icon_url, - Profile::FromBrowserContext(web_contents()->GetBrowserContext())-> - GetRequestContext()); - // The helper will call us back via OnWebstoreParseSucces or - // OnWebstoreParseFailure. - helper->Start(); -} - -void WebstoreInlineInstaller::OnWebstoreResponseParseFailure( - const std::string& error) { - CompleteInstall(error); -} - -void WebstoreInlineInstaller::OnWebstoreParseSuccess( - const std::string& id, - const SkBitmap& icon, - base::DictionaryValue* manifest) { - // Check if the tab has gone away in the meantime. - if (!web_contents()) { - CompleteInstall(""); - return; - } - - CHECK_EQ(id_, id); - manifest_.reset(manifest); - icon_ = icon; - - Profile* profile = Profile::FromBrowserContext( - web_contents()->GetBrowserContext()); - ExtensionInstallPrompt::Prompt prompt( - profile, - ExtensionInstallPrompt::INLINE_INSTALL_PROMPT); - prompt.SetInlineInstallWebstoreData(localized_user_count_, - average_rating_, - rating_count_); - std::string error; - dummy_extension_ = ExtensionInstallPrompt::GetLocalizedExtensionForDisplay( - manifest, - Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE, - id_, - localized_name_, - localized_description_, - &error); - if (!dummy_extension_) { - OnWebstoreParseFailure(id_, WebstoreInstallHelper::Delegate::MANIFEST_ERROR, - kInvalidManifestError); - return; - } - - install_ui_.reset(new ExtensionInstallPrompt(NULL, web_contents(), profile)); - install_ui_->ConfirmInlineInstall(this, dummy_extension_, &icon_, prompt); - // Control flow finishes up in InstallUIProceed or InstallUIAbort. -} - -void WebstoreInlineInstaller::OnWebstoreParseFailure( - const std::string& id, - InstallHelperResultCode result_code, - const std::string& error_message) { - CompleteInstall(error_message); -} - -void WebstoreInlineInstaller::InstallUIProceed() { - // Check if the tab has gone away in the meantime. - if (!web_contents()) { - CompleteInstall(""); - return; - } - - Profile* profile = Profile::FromBrowserContext( - web_contents()->GetBrowserContext()); - - scoped_ptr<WebstoreInstaller::Approval> approval( - WebstoreInstaller::Approval::CreateWithNoInstallPrompt( - profile, - id_, - scoped_ptr<base::DictionaryValue>(manifest_.get()->DeepCopy()))); - if (skip_post_install_ui_) - approval->skip_post_install_ui = true; - else - approval->use_app_installed_bubble = true; - - scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller( - profile, this, &(web_contents()->GetController()), id_, approval.Pass(), - WebstoreInstaller::FLAG_INLINE_INSTALL); - installer->Start(); -} - -void WebstoreInlineInstaller::InstallUIAbort(bool user_initiated) { - CompleteInstall(kUserCancelledError); -} - -void WebstoreInlineInstaller::WebContentsDestroyed(WebContents* web_contents) { - callback_.Reset(); - // Abort any in-progress fetches. - if (webstore_data_url_fetcher_.get()) { - webstore_data_url_fetcher_.reset(); - Release(); // Matches the AddRef in BeginInstall. - } -} - -void WebstoreInlineInstaller::OnExtensionInstallSuccess(const std::string& id) { - CHECK_EQ(id_, id); - CompleteInstall(""); -} - -void WebstoreInlineInstaller::OnExtensionInstallFailure( - const std::string& id, - const std::string& error, - WebstoreInstaller::FailureReason cancelled) { - CHECK_EQ(id_, id); - CompleteInstall(error); -} - -void WebstoreInlineInstaller::CompleteInstall(const std::string& error) { - if (!callback_.is_null()) - callback_.Run(error.empty(), error); - - Release(); // Matches the AddRef in BeginInstall. -} - -// static -bool WebstoreInlineInstaller::IsRequestorURLInVerifiedSite( - const GURL& requestor_url, - const std::string& verified_site) { - // Turn the verified site (which may be a bare domain, or have a port and/or a - // path) into a URL that can be parsed by URLPattern. - std::string verified_site_url = - StringPrintf("http://*.%s%s", - verified_site.c_str(), - verified_site.find('/') == std::string::npos ? "/*" : "*"); - - URLPattern verified_site_pattern( - URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS); - URLPattern::ParseResult parse_result = - verified_site_pattern.Parse(verified_site_url); - if (parse_result != URLPattern::PARSE_SUCCESS) { - DLOG(WARNING) << "Could not parse " << verified_site_url << - " as URL pattern " << parse_result; - return false; - } - verified_site_pattern.SetScheme("*"); - - return verified_site_pattern.MatchesURL(requestor_url); -} - -} // namespace extensions |