Commit 7b394105 authored by xiyuan@chromium.org's avatar xiyuan@chromium.org

Move web store data fetching and parsing out of WebstoreStandaloneInstaller.

So that the code could be shared with kiosk apps code.

BUG=173749
TEST=Existing WebstoreStandaloneInstaller test should pass.

R=asargent@chromium.org
TBR=sky@chromium.org for chrome/chrome_browser_extensions.gypi

Review URL: https://chromiumcodereview.appspot.com/12212076

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182081 0039d316-1c4b-4281-b951-d872f2087c98
parent 7d414cf9
// Copyright 2013 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_data_fetcher.h"
#include "base/values.h"
#include "chrome/browser/extensions/webstore_data_fetcher_delegate.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/extensions/extension_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/utility_process_host.h"
#include "content/public/browser/utility_process_host_client.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::UtilityProcessHost;
using content::UtilityProcessHostClient;
namespace {
const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
} // namespace
namespace extensions {
class WebstoreDataFetcher::SafeWebstoreResponseParser
: public UtilityProcessHostClient {
public:
SafeWebstoreResponseParser(const base::WeakPtr<WebstoreDataFetcher>& 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, base::MessageLoopProxy::current());
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 base::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 (!client_)
return;
if (error_.empty() && parsed_webstore_data_.get()) {
client_->OnWebstoreResponseParseSuccess(parsed_webstore_data_.release());
} else {
client_->OnWebstoreResponseParseFailure(error_);
}
}
private:
virtual ~SafeWebstoreResponseParser() {}
base::WeakPtr<WebstoreDataFetcher> client_;
std::string webstore_data_;
std::string error_;
scoped_ptr<DictionaryValue> parsed_webstore_data_;
DISALLOW_COPY_AND_ASSIGN(SafeWebstoreResponseParser);
};
WebstoreDataFetcher::WebstoreDataFetcher(
WebstoreDataFetcherDelegate* delegate,
net::URLRequestContextGetter* request_context,
const GURL& referrer_url,
const std::string webstore_item_id)
: delegate_(delegate),
request_context_(request_context),
referrer_url_(referrer_url),
id_(webstore_item_id) {
}
WebstoreDataFetcher::~WebstoreDataFetcher() {}
void WebstoreDataFetcher::Start() {
GURL webstore_data_url(extension_urls::GetWebstoreItemJsonDataURL(id_));
webstore_data_url_fetcher_.reset(net::URLFetcher::Create(
webstore_data_url, net::URLFetcher::GET, this));
webstore_data_url_fetcher_->SetRequestContext(request_context_);
webstore_data_url_fetcher_->SetReferrer(referrer_url_.spec());
webstore_data_url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DISABLE_CACHE);
webstore_data_url_fetcher_->Start();
}
void WebstoreDataFetcher::OnWebstoreResponseParseSuccess(
base::DictionaryValue* webstore_data) {
delegate_->OnWebstoreResponseParseSuccess(webstore_data);
}
void WebstoreDataFetcher::OnWebstoreResponseParseFailure(
const std::string& error) {
delegate_->OnWebstoreResponseParseFailure(error);
}
void WebstoreDataFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
CHECK_EQ(webstore_data_url_fetcher_.get(), source);
if (!webstore_data_url_fetcher_->GetStatus().is_success() ||
webstore_data_url_fetcher_->GetResponseCode() != 200) {
delegate_->OnWebstoreRequestFailure();
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(AsWeakPtr(), webstore_json_data);
// The parser will call us back via OnWebstoreResponseParseSucces or
// OnWebstoreResponseParseFailure.
parser->Start();
}
} // namespace extensions
// Copyright 2013 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.
#ifndef CHROME_BROWSER_EXTENSIONS_WEBSTORE_DATA_FETCHER_H_
#define CHROME_BROWSER_EXTENSIONS_WEBSTORE_DATA_FETCHER_H_
#include <string>
#include "base/memory/weak_ptr.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_fetcher_delegate.h"
namespace base {
class DictionaryValue;
}
namespace net {
class URLFetcher;
class URLRequestContextGetter;
}
namespace extensions {
class WebstoreDataFetcherDelegate;
// WebstoreDataFetcher fetches web store data and parses it into a
// DictionaryValue.
class WebstoreDataFetcher : public base::SupportsWeakPtr<WebstoreDataFetcher>,
public net::URLFetcherDelegate {
public:
WebstoreDataFetcher(WebstoreDataFetcherDelegate* delegate,
net::URLRequestContextGetter* request_context,
const GURL& referrer_url,
const std::string webstore_item_id);
virtual ~WebstoreDataFetcher();
void Start();
private:
class SafeWebstoreResponseParser;
// Client callbacks for SafeWebstoreResponseParser when parsing is complete.
void OnWebstoreResponseParseSuccess(base::DictionaryValue* webstore_data);
void OnWebstoreResponseParseFailure(const std::string& error);
// net::URLFetcherDelegate overrides:
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
WebstoreDataFetcherDelegate* delegate_;
net::URLRequestContextGetter* request_context_;
GURL referrer_url_;
std::string id_;
// For fetching webstore JSON data.
scoped_ptr<net::URLFetcher> webstore_data_url_fetcher_;
DISALLOW_COPY_AND_ASSIGN(WebstoreDataFetcher);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_DATA_FETCHER_H_
// Copyright 2013 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.
#ifndef CHROME_BROWSER_EXTENSIONS_WEBSTORE_DATA_FETCHER_DELEGATE_H_
#define CHROME_BROWSER_EXTENSIONS_WEBSTORE_DATA_FETCHER_DELEGATE_H_
#include <string>
namespace base {
class DictionaryValue;
}
namespace extensions {
class WebstoreDataFetcherDelegate {
public:
// Invoked when the web store data request failed.
virtual void OnWebstoreRequestFailure() = 0;
// Invoked when the web store response parsing is successful. Delegate takes
// ownership of |webstore_data|.
virtual void OnWebstoreResponseParseSuccess(
base::DictionaryValue* webstore_data) = 0;
// Invoked when the web store response parsing is failed.
virtual void OnWebstoreResponseParseFailure(const std::string& error) = 0;
protected:
virtual ~WebstoreDataFetcherDelegate() {}
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_DATA_FETCHER_DELEGATE_H_
......@@ -6,32 +6,19 @@
#include <vector>
#include "base/bind.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/webstore_data_fetcher.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/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 "content/public/browser/web_contents_view.h"
#include "extensions/common/url_pattern.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 {
......@@ -63,91 +50,6 @@ 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(WebstoreStandaloneInstaller *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, base::MessageLoopProxy::current());
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() {}
WebstoreStandaloneInstaller* client_;
std::string webstore_data_;
std::string error_;
scoped_ptr<DictionaryValue> parsed_webstore_data_;
};
WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
WebContents* web_contents,
std::string webstore_item_id,
......@@ -175,47 +77,23 @@ void WebstoreStandaloneInstaller::BeginInstall() {
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();
webstore_data_fetcher_.reset(new WebstoreDataFetcher(
this,
profile->GetRequestContext(),
requestor_url_,
id_));
webstore_data_fetcher_->Start();
}
WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {}
void WebstoreStandaloneInstaller::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 WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
CompleteInstall(kWebstoreRequestError);
}
void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
......@@ -425,8 +303,8 @@ void WebstoreStandaloneInstaller::WebContentsDestroyed(
WebContents* web_contents) {
callback_.Reset();
// Abort any in-progress fetches.
if (webstore_data_url_fetcher_.get()) {
webstore_data_url_fetcher_.reset();
if (webstore_data_fetcher_.get()) {
webstore_data_fetcher_.reset();
Release(); // Matches the AddRef in BeginInstall.
}
}
......
......@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/webstore_data_fetcher_delegate.h"
#include "chrome/browser/extensions/webstore_install_helper.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "content/public/browser/web_contents_observer.h"
......@@ -26,7 +27,7 @@ class URLFetcher;
namespace extensions {
class Extension;
class SafeWebstoreResponseParser;
class WebstoreDataFetcher;
// Manages inline installs requested by a page (downloads and parses metadata
// from the webstore, shows the install UI, starts the download once the user
......@@ -38,7 +39,7 @@ class WebstoreStandaloneInstaller
: public base::RefCountedThreadSafe<WebstoreStandaloneInstaller>,
public ExtensionInstallPrompt::Delegate,
public content::WebContentsObserver,
public net::URLFetcherDelegate,
public WebstoreDataFetcherDelegate,
public WebstoreInstaller::Delegate,
public WebstoreInstallHelper::Delegate {
public:
......@@ -71,7 +72,6 @@ class WebstoreStandaloneInstaller
private:
friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
friend class SafeWebstoreResponseParser;
FRIEND_TEST_ALL_PREFIXES(WebstoreStandaloneInstallerTest, DomainVerification);
virtual ~WebstoreStandaloneInstaller();
......@@ -89,12 +89,12 @@ class WebstoreStandaloneInstaller
// All flows (whether successful or not) end up in CompleteInstall, which
// informs our delegate of success/failure.
// net::URLFetcherDelegate interface implementation.
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
// Client callbacks for SafeWebstoreResponseParser when parsing is complete.
void OnWebstoreResponseParseSuccess(DictionaryValue* webstore_data);
void OnWebstoreResponseParseFailure(const std::string& error);
// WebstoreDataFetcherDelegate interface implementation.
virtual void OnWebstoreRequestFailure() OVERRIDE;
virtual void OnWebstoreResponseParseSuccess(
base::DictionaryValue* webstore_data) OVERRIDE;
virtual void OnWebstoreResponseParseFailure(
const std::string& error) OVERRIDE;
// WebstoreInstallHelper::Delegate interface implementation.
virtual void OnWebstoreParseSuccess(
......@@ -137,7 +137,7 @@ class WebstoreStandaloneInstaller
bool skip_post_install_ui_;
// For fetching webstore JSON data.
scoped_ptr<net::URLFetcher> webstore_data_url_fetcher_;
scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher_;
// Extracted from the webstore JSON data response.
std::string localized_name_;
......
......@@ -705,6 +705,9 @@
'browser/extensions/user_script_master.h',
'browser/extensions/web_accessible_resources_parser.cc',
'browser/extensions/web_accessible_resources_parser.h',
'browser/extensions/webstore_data_fetcher.cc',
'browser/extensions/webstore_data_fetcher.h',
'browser/extensions/webstore_data_fetcher_delegate.h',
'browser/extensions/webstore_install_helper.cc',
'browser/extensions/webstore_install_helper.h',
'browser/extensions/webstore_installer.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment