Chromium Code Reviews| 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..31065bda6eb83bd7470061f64b05f0e6ccf7ca27 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/webstore_data_fetcher.cc |
| @@ -0,0 +1,179 @@ |
| +// 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 { |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// WebstoreDataFetcher::SafeWebstoreResponseParser |
|
asargent_no_longer_on_chrome
2013/02/12 18:40:10
nit: Is this comment needed/helpful? There's only
xiyuan
2013/02/12 18:49:03
Removed.
|
| + |
| +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 |