1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/webstore_install_helper.h"
10 #include "base/values.h"
11 #include "chrome/common/chrome_utility_messages.h"
12 #include "chrome/common/extensions/chrome_utility_extensions_messages.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/utility_process_host.h"
15 #include "net/base/load_flags.h"
16 #include "net/url_request/url_fetcher.h"
17 #include "net/url_request/url_request_context_getter.h"
18 #include "net/url_request/url_request_status.h"
20 using content::BrowserThread
;
21 using content::UtilityProcessHost
;
25 const char kImageDecodeError
[] = "Image decode failed";
29 namespace extensions
{
31 WebstoreInstallHelper::WebstoreInstallHelper(
33 const std::string
& id
,
34 const std::string
& manifest
,
36 net::URLRequestContextGetter
* context_getter
)
38 content::BrowserThread::GetMessageLoopProxyForThread(
39 content::BrowserThread::IO
)),
44 context_getter_(context_getter
),
45 icon_decode_complete_(false),
46 manifest_parse_complete_(false),
47 parse_error_(Delegate::UNKNOWN_ERROR
) {
50 WebstoreInstallHelper::~WebstoreInstallHelper() {}
52 void WebstoreInstallHelper::Start() {
53 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
55 if (icon_url_
.is_empty())
56 icon_decode_complete_
= true;
58 BrowserThread::PostTask(
61 base::Bind(&WebstoreInstallHelper::StartWorkOnIOThread
, this));
63 if (!icon_url_
.is_empty()) {
64 CHECK(context_getter_
);
65 url_fetcher_
.reset(net::URLFetcher::Create(
66 icon_url_
, net::URLFetcher::GET
, this));
67 url_fetcher_
->SetRequestContext(context_getter_
);
68 url_fetcher_
->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES
|
69 net::LOAD_DO_NOT_SEND_COOKIES
);
71 url_fetcher_
->Start();
72 // We'll get called back in OnURLFetchComplete.
76 void WebstoreInstallHelper::StartWorkOnIOThread() {
77 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
78 utility_host_
= UtilityProcessHost::Create(
79 this, base::MessageLoopProxy::current().get())->AsWeakPtr();
80 utility_host_
->StartBatchMode();
82 utility_host_
->Send(new ChromeUtilityMsg_ParseJSON(manifest_
));
85 void WebstoreInstallHelper::OnURLFetchComplete(
86 const net::URLFetcher
* source
) {
87 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
88 CHECK(source
== url_fetcher_
.get());
90 source
->GetStatus().is_success() ? source
->GetResponseCode() : 0;
91 if (!source
->GetStatus().is_success() ||
92 response_code
/ 100 == 4 || response_code
/ 100 == 5) {
93 BrowserThread::PostTask(
94 BrowserThread::IO
, FROM_HERE
,
95 base::Bind(&WebstoreInstallHelper::OnDecodeImageFailed
, this));
97 std::string response_data
;
98 source
->GetResponseAsString(&response_data
);
100 ImageDecoder::Start(this, response_data
);
102 url_fetcher_
.reset();
105 bool WebstoreInstallHelper::OnMessageReceived(const IPC::Message
& message
) {
107 IPC_BEGIN_MESSAGE_MAP(WebstoreInstallHelper
, message
)
108 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded
,
109 OnJSONParseSucceeded
)
110 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed
,
112 IPC_MESSAGE_UNHANDLED(handled
= false)
113 IPC_END_MESSAGE_MAP()
117 void WebstoreInstallHelper::OnImageDecoded(const SkBitmap
& decoded_image
) {
118 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
119 icon_
= decoded_image
;
120 icon_decode_complete_
= true;
121 ReportResultsIfComplete();
124 void WebstoreInstallHelper::OnDecodeImageFailed() {
125 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
126 icon_decode_complete_
= true;
127 error_
= kImageDecodeError
;
128 parse_error_
= Delegate::ICON_ERROR
;
129 ReportResultsIfComplete();
132 void WebstoreInstallHelper::OnJSONParseSucceeded(
133 const base::ListValue
& wrapper
) {
134 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
135 manifest_parse_complete_
= true;
136 const base::Value
* value
= NULL
;
137 CHECK(wrapper
.Get(0, &value
));
138 if (value
->IsType(base::Value::TYPE_DICTIONARY
)) {
139 parsed_manifest_
.reset(
140 static_cast<const base::DictionaryValue
*>(value
)->DeepCopy());
142 parse_error_
= Delegate::MANIFEST_ERROR
;
144 ReportResultsIfComplete();
147 void WebstoreInstallHelper::OnJSONParseFailed(
148 const std::string
& error_message
) {
149 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
150 manifest_parse_complete_
= true;
151 error_
= error_message
;
152 parse_error_
= Delegate::MANIFEST_ERROR
;
153 ReportResultsIfComplete();
156 void WebstoreInstallHelper::ReportResultsIfComplete() {
157 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
159 if (!icon_decode_complete_
|| !manifest_parse_complete_
)
162 // The utility_host_ will take care of deleting itself after this call.
163 if (utility_host_
.get()) {
164 utility_host_
->EndBatchMode();
165 utility_host_
.reset();
168 BrowserThread::PostTask(
171 base::Bind(&WebstoreInstallHelper::ReportResultFromUIThread
, this));
174 void WebstoreInstallHelper::ReportResultFromUIThread() {
175 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
176 if (error_
.empty() && parsed_manifest_
)
177 delegate_
->OnWebstoreParseSuccess(id_
, icon_
, parsed_manifest_
.release());
179 delegate_
->OnWebstoreParseFailure(id_
, parse_error_
, error_
);
182 } // namespace extensions