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/thread_task_runner_handle.h"
11 #include "base/values.h"
12 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
13 #include "chrome/common/chrome_utility_messages.h"
14 #include "chrome/common/extensions/chrome_utility_extensions_messages.h"
15 #include "chrome/grit/generated_resources.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/utility_process_host.h"
18 #include "net/base/load_flags.h"
19 #include "net/url_request/url_request.h"
20 #include "ui/base/l10n/l10n_util.h"
22 using content::BrowserThread
;
23 using content::UtilityProcessHost
;
27 const char kImageDecodeError
[] = "Image decode failed";
31 namespace extensions
{
33 WebstoreInstallHelper::WebstoreInstallHelper(
35 const std::string
& id
,
36 const std::string
& manifest
,
38 net::URLRequestContextGetter
* context_getter
)
39 : delegate_(delegate
),
43 context_getter_(context_getter
),
44 icon_decode_complete_(false),
45 manifest_parse_complete_(false),
46 parse_error_(Delegate::UNKNOWN_ERROR
) {
49 WebstoreInstallHelper::~WebstoreInstallHelper() {}
51 void WebstoreInstallHelper::Start() {
52 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
54 if (icon_url_
.is_empty()) {
55 icon_decode_complete_
= true;
57 // No existing |icon_fetcher_| to avoid unbalanced AddRef().
58 CHECK(!icon_fetcher_
.get());
59 AddRef(); // Balanced in OnFetchComplete().
60 icon_fetcher_
.reset(new chrome::BitmapFetcher(icon_url_
, this));
62 context_getter_
, std::string(),
63 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE
,
64 net::LOAD_DO_NOT_SAVE_COOKIES
| net::LOAD_DO_NOT_SEND_COOKIES
);
67 BrowserThread::PostTask(
70 base::Bind(&WebstoreInstallHelper::StartWorkOnIOThread
, this));
73 void WebstoreInstallHelper::StartWorkOnIOThread() {
74 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
75 utility_host_
= UtilityProcessHost::Create(
76 this, base::ThreadTaskRunnerHandle::Get().get())->AsWeakPtr();
77 utility_host_
->SetName(l10n_util::GetStringUTF16(
78 IDS_UTILITY_PROCESS_JSON_PARSER_NAME
));
79 utility_host_
->StartBatchMode();
81 utility_host_
->Send(new ChromeUtilityMsg_ParseJSON(manifest_
));
84 bool WebstoreInstallHelper::OnMessageReceived(const IPC::Message
& message
) {
86 IPC_BEGIN_MESSAGE_MAP(WebstoreInstallHelper
, message
)
87 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded
,
89 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed
,
91 IPC_MESSAGE_UNHANDLED(handled
= false)
96 void WebstoreInstallHelper::OnFetchComplete(const GURL
& url
,
97 const SkBitmap
* image
) {
98 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
99 // OnFetchComplete should only be called as icon_fetcher_ delegate to avoid
100 // unbalanced Release().
101 CHECK(icon_fetcher_
.get());
105 icon_decode_complete_
= true;
107 error_
= kImageDecodeError
;
108 parse_error_
= Delegate::ICON_ERROR
;
110 icon_fetcher_
.reset();
111 BrowserThread::PostTask(
114 base::Bind(&WebstoreInstallHelper::ReportResultsIfComplete
, this));
115 Release(); // Balanced in Start().
118 void WebstoreInstallHelper::OnJSONParseSucceeded(
119 const base::ListValue
& wrapper
) {
120 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
121 manifest_parse_complete_
= true;
122 const base::Value
* value
= NULL
;
123 CHECK(wrapper
.Get(0, &value
));
124 if (value
->IsType(base::Value::TYPE_DICTIONARY
)) {
125 parsed_manifest_
.reset(
126 static_cast<const base::DictionaryValue
*>(value
)->DeepCopy());
128 parse_error_
= Delegate::MANIFEST_ERROR
;
130 ReportResultsIfComplete();
133 void WebstoreInstallHelper::OnJSONParseFailed(
134 const std::string
& error_message
) {
135 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
136 manifest_parse_complete_
= true;
137 error_
= error_message
;
138 parse_error_
= Delegate::MANIFEST_ERROR
;
139 ReportResultsIfComplete();
142 void WebstoreInstallHelper::ReportResultsIfComplete() {
143 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
145 if (!icon_decode_complete_
|| !manifest_parse_complete_
)
148 // The utility_host_ will take care of deleting itself after this call.
149 if (utility_host_
.get()) {
150 utility_host_
->EndBatchMode();
151 utility_host_
.reset();
154 BrowserThread::PostTask(
157 base::Bind(&WebstoreInstallHelper::ReportResultFromUIThread
, this));
160 void WebstoreInstallHelper::ReportResultFromUIThread() {
161 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
162 if (error_
.empty() && parsed_manifest_
)
163 delegate_
->OnWebstoreParseSuccess(id_
, icon_
, parsed_manifest_
.release());
165 delegate_
->OnWebstoreParseFailure(id_
, parse_error_
, error_
);
168 } // namespace extensions