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 "content/public/browser/browser_thread.h"
13 #include "content/public/browser/utility_process_host.h"
14 #include "net/base/load_flags.h"
15 #include "net/url_request/url_fetcher.h"
16 #include "net/url_request/url_request_context_getter.h"
17 #include "net/url_request/url_request_status.h"
19 using content::BrowserThread
;
20 using content::UtilityProcessHost
;
24 const char kImageDecodeError
[] = "Image decode failed";
28 namespace extensions
{
30 WebstoreInstallHelper::WebstoreInstallHelper(
32 const std::string
& id
,
33 const std::string
& manifest
,
34 const std::string
& icon_data
,
36 net::URLRequestContextGetter
* context_getter
)
37 : delegate_(delegate
),
40 icon_base64_data_(icon_data
),
42 context_getter_(context_getter
),
43 icon_decode_complete_(false),
44 manifest_parse_complete_(false),
45 parse_error_(Delegate::UNKNOWN_ERROR
) {}
47 WebstoreInstallHelper::~WebstoreInstallHelper() {}
49 void WebstoreInstallHelper::Start() {
50 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
51 CHECK(icon_base64_data_
.empty() || icon_url_
.is_empty());
53 if (icon_base64_data_
.empty() && icon_url_
.is_empty())
54 icon_decode_complete_
= true;
56 BrowserThread::PostTask(
59 base::Bind(&WebstoreInstallHelper::StartWorkOnIOThread
, this));
61 if (!icon_url_
.is_empty()) {
62 CHECK(context_getter_
);
63 url_fetcher_
.reset(net::URLFetcher::Create(
64 icon_url_
, net::URLFetcher::GET
, this));
65 url_fetcher_
->SetRequestContext(context_getter_
);
66 url_fetcher_
->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES
|
67 net::LOAD_DO_NOT_SEND_COOKIES
);
69 url_fetcher_
->Start();
70 // We'll get called back in OnURLFetchComplete.
74 void WebstoreInstallHelper::StartWorkOnIOThread() {
75 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
76 utility_host_
= UtilityProcessHost::Create(
77 this, base::MessageLoopProxy::current().get())->AsWeakPtr();
78 utility_host_
->StartBatchMode();
80 if (!icon_base64_data_
.empty())
82 new ChromeUtilityMsg_DecodeImageBase64(icon_base64_data_
));
84 utility_host_
->Send(new ChromeUtilityMsg_ParseJSON(manifest_
));
87 void WebstoreInstallHelper::OnURLFetchComplete(
88 const net::URLFetcher
* source
) {
89 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
90 CHECK(source
== url_fetcher_
.get());
91 if (source
->GetStatus().status() != net::URLRequestStatus::SUCCESS
||
92 source
->GetResponseCode() != 200) {
93 BrowserThread::PostTask(
96 base::Bind(&WebstoreInstallHelper::OnDecodeImageFailed
, this));
98 std::string response_data
;
99 source
->GetResponseAsString(&response_data
);
100 fetched_icon_data_
.insert(fetched_icon_data_
.begin(),
101 response_data
.begin(),
102 response_data
.end());
103 BrowserThread::PostTask(
106 base::Bind(&WebstoreInstallHelper::StartFetchedImageDecode
, this));
108 url_fetcher_
.reset();
111 void WebstoreInstallHelper::StartFetchedImageDecode() {
112 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
113 CHECK(utility_host_
.get());
114 utility_host_
->Send(new ChromeUtilityMsg_DecodeImage(fetched_icon_data_
));
118 bool WebstoreInstallHelper::OnMessageReceived(const IPC::Message
& message
) {
120 IPC_BEGIN_MESSAGE_MAP(WebstoreInstallHelper
, message
)
121 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Succeeded
,
122 OnDecodeImageSucceeded
)
123 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Failed
,
125 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded
,
126 OnJSONParseSucceeded
)
127 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed
,
129 IPC_MESSAGE_UNHANDLED(handled
= false)
130 IPC_END_MESSAGE_MAP()
135 void WebstoreInstallHelper::OnDecodeImageSucceeded(
136 const SkBitmap
& decoded_image
) {
137 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
138 icon_
= decoded_image
;
139 icon_decode_complete_
= true;
140 ReportResultsIfComplete();
143 void WebstoreInstallHelper::OnDecodeImageFailed() {
144 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
145 icon_decode_complete_
= true;
146 error_
= kImageDecodeError
;
147 parse_error_
= Delegate::ICON_ERROR
;
148 ReportResultsIfComplete();
151 void WebstoreInstallHelper::OnJSONParseSucceeded(
152 const base::ListValue
& wrapper
) {
153 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
154 manifest_parse_complete_
= true;
155 const base::Value
* value
= NULL
;
156 CHECK(wrapper
.Get(0, &value
));
157 if (value
->IsType(base::Value::TYPE_DICTIONARY
)) {
158 parsed_manifest_
.reset(
159 static_cast<const base::DictionaryValue
*>(value
)->DeepCopy());
161 parse_error_
= Delegate::MANIFEST_ERROR
;
163 ReportResultsIfComplete();
166 void WebstoreInstallHelper::OnJSONParseFailed(
167 const std::string
& error_message
) {
168 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
169 manifest_parse_complete_
= true;
170 error_
= error_message
;
171 parse_error_
= Delegate::MANIFEST_ERROR
;
172 ReportResultsIfComplete();
175 void WebstoreInstallHelper::ReportResultsIfComplete() {
176 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
178 if (!icon_decode_complete_
|| !manifest_parse_complete_
)
181 // The utility_host_ will take care of deleting itself after this call.
182 if (utility_host_
.get()) {
183 utility_host_
->EndBatchMode();
184 utility_host_
.reset();
187 BrowserThread::PostTask(
190 base::Bind(&WebstoreInstallHelper::ReportResultFromUIThread
, this));
193 void WebstoreInstallHelper::ReportResultFromUIThread() {
194 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
195 if (error_
.empty() && parsed_manifest_
)
196 delegate_
->OnWebstoreParseSuccess(id_
, icon_
, parsed_manifest_
.release());
198 delegate_
->OnWebstoreParseFailure(id_
, parse_error_
, error_
);
201 } // namespace extensions