// 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_install_helper.h" #include #include "base/bind.h" #include "base/values.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" #include "chrome/common/chrome_utility_messages.h" #include "chrome/common/extensions/chrome_utility_extensions_messages.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/utility_process_host.h" #include "net/base/load_flags.h" #include "net/url_request/url_request.h" #include "ui/base/l10n/l10n_util.h" using content::BrowserThread; using content::UtilityProcessHost; namespace { const char kImageDecodeError[] = "Image decode failed"; } // namespace namespace extensions { WebstoreInstallHelper::WebstoreInstallHelper( Delegate* delegate, const std::string& id, const std::string& manifest, const GURL& icon_url, net::URLRequestContextGetter* context_getter) : delegate_(delegate), id_(id), manifest_(manifest), icon_url_(icon_url), context_getter_(context_getter), icon_decode_complete_(false), manifest_parse_complete_(false), parse_error_(Delegate::UNKNOWN_ERROR) { } WebstoreInstallHelper::~WebstoreInstallHelper() {} void WebstoreInstallHelper::Start() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (icon_url_.is_empty()) { icon_decode_complete_ = true; } else { icon_fetcher_.reset(new chrome::BitmapFetcher(icon_url_, this)); icon_fetcher_->Start( context_getter_, std::string(), net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES); } BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&WebstoreInstallHelper::StartWorkOnIOThread, this)); } void WebstoreInstallHelper::StartWorkOnIOThread() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); utility_host_ = UtilityProcessHost::Create( this, base::MessageLoopProxy::current().get())->AsWeakPtr(); utility_host_->SetName(l10n_util::GetStringUTF16( IDS_UTILITY_PROCESS_JSON_PARSER_NAME)); utility_host_->StartBatchMode(); utility_host_->Send(new ChromeUtilityMsg_ParseJSON(manifest_)); } bool WebstoreInstallHelper::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(WebstoreInstallHelper, 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 WebstoreInstallHelper::OnFetchComplete(const GURL& url, const SkBitmap* image) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (image) icon_ = *image; icon_decode_complete_ = true; if (icon_.empty()) { error_ = kImageDecodeError; parse_error_ = Delegate::ICON_ERROR; } icon_fetcher_.reset(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&WebstoreInstallHelper::ReportResultsIfComplete, this)); } void WebstoreInstallHelper::OnJSONParseSucceeded( const base::ListValue& wrapper) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); manifest_parse_complete_ = true; const base::Value* value = NULL; CHECK(wrapper.Get(0, &value)); if (value->IsType(base::Value::TYPE_DICTIONARY)) { parsed_manifest_.reset( static_cast(value)->DeepCopy()); } else { parse_error_ = Delegate::MANIFEST_ERROR; } ReportResultsIfComplete(); } void WebstoreInstallHelper::OnJSONParseFailed( const std::string& error_message) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); manifest_parse_complete_ = true; error_ = error_message; parse_error_ = Delegate::MANIFEST_ERROR; ReportResultsIfComplete(); } void WebstoreInstallHelper::ReportResultsIfComplete() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (!icon_decode_complete_ || !manifest_parse_complete_) return; // The utility_host_ will take care of deleting itself after this call. if (utility_host_.get()) { utility_host_->EndBatchMode(); utility_host_.reset(); } BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&WebstoreInstallHelper::ReportResultFromUIThread, this)); } void WebstoreInstallHelper::ReportResultFromUIThread() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (error_.empty() && parsed_manifest_) delegate_->OnWebstoreParseSuccess(id_, icon_, parsed_manifest_.release()); else delegate_->OnWebstoreParseFailure(id_, parse_error_, error_); } } // namespace extensions