| Index: chrome/browser/extensions/webstore_data_fetcher.cc
|
| diff --git a/chrome/browser/extensions/webstore_data_fetcher.cc b/chrome/browser/extensions/webstore_data_fetcher.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ca69f90633d094a76f9f536cae48dc818d2a6463
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/webstore_data_fetcher.cc
|
| @@ -0,0 +1,176 @@
|
| +// 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
|
|
|