Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / webstore_install_helper.cc
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.
4
5 #include "chrome/browser/extensions/webstore_install_helper.h"
6
7 #include <string>
8
9 #include "base/bind.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"
19
20 using content::BrowserThread;
21 using content::UtilityProcessHost;
22
23 namespace {
24
25 const char kImageDecodeError[] = "Image decode failed";
26
27 }  // namespace
28
29 namespace extensions {
30
31 WebstoreInstallHelper::WebstoreInstallHelper(
32     Delegate* delegate,
33     const std::string& id,
34     const std::string& manifest,
35     const std::string& icon_data,
36     const GURL& icon_url,
37     net::URLRequestContextGetter* context_getter)
38     : delegate_(delegate),
39       id_(id),
40       manifest_(manifest),
41       icon_base64_data_(icon_data),
42       icon_url_(icon_url),
43       context_getter_(context_getter),
44       icon_decode_complete_(false),
45       manifest_parse_complete_(false),
46       parse_error_(Delegate::UNKNOWN_ERROR) {}
47
48 WebstoreInstallHelper::~WebstoreInstallHelper() {}
49
50 void WebstoreInstallHelper::Start() {
51   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
52   CHECK(icon_base64_data_.empty() || icon_url_.is_empty());
53
54   if (icon_base64_data_.empty() && icon_url_.is_empty())
55     icon_decode_complete_ = true;
56
57   BrowserThread::PostTask(
58       BrowserThread::IO,
59       FROM_HERE,
60       base::Bind(&WebstoreInstallHelper::StartWorkOnIOThread, this));
61
62   if (!icon_url_.is_empty()) {
63     CHECK(context_getter_);
64     url_fetcher_.reset(net::URLFetcher::Create(
65         icon_url_, net::URLFetcher::GET, this));
66     url_fetcher_->SetRequestContext(context_getter_);
67     url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
68                                net::LOAD_DO_NOT_SEND_COOKIES);
69
70     url_fetcher_->Start();
71     // We'll get called back in OnURLFetchComplete.
72   }
73 }
74
75 void WebstoreInstallHelper::StartWorkOnIOThread() {
76   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
77   utility_host_ = UtilityProcessHost::Create(
78       this, base::MessageLoopProxy::current().get())->AsWeakPtr();
79   utility_host_->StartBatchMode();
80
81   if (!icon_base64_data_.empty())
82     utility_host_->Send(
83         new ChromeUtilityMsg_DecodeImageBase64(icon_base64_data_));
84
85   utility_host_->Send(new ChromeUtilityMsg_ParseJSON(manifest_));
86 }
87
88 void WebstoreInstallHelper::OnURLFetchComplete(
89     const net::URLFetcher* source) {
90   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
91   CHECK(source == url_fetcher_.get());
92   int response_code =
93       source->GetStatus().is_success() ? source->GetResponseCode() : 0;
94   if (!source->GetStatus().is_success() ||
95       response_code / 100 == 4 || response_code / 100 == 5) {
96     BrowserThread::PostTask(
97         BrowserThread::IO,
98         FROM_HERE,
99         base::Bind(&WebstoreInstallHelper::OnDecodeImageFailed, this));
100   } else {
101     std::string response_data;
102     source->GetResponseAsString(&response_data);
103     fetched_icon_data_.insert(fetched_icon_data_.begin(),
104                               response_data.begin(),
105                               response_data.end());
106     BrowserThread::PostTask(
107         BrowserThread::IO,
108         FROM_HERE,
109         base::Bind(&WebstoreInstallHelper::StartFetchedImageDecode, this));
110   }
111   url_fetcher_.reset();
112 }
113
114 void WebstoreInstallHelper::StartFetchedImageDecode() {
115   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
116   CHECK(utility_host_.get());
117   utility_host_->Send(new ChromeUtilityMsg_DecodeImage(fetched_icon_data_));
118 }
119
120
121 bool WebstoreInstallHelper::OnMessageReceived(const IPC::Message& message) {
122   bool handled = true;
123   IPC_BEGIN_MESSAGE_MAP(WebstoreInstallHelper, message)
124     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Succeeded,
125                         OnDecodeImageSucceeded)
126     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Failed,
127                         OnDecodeImageFailed)
128     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded,
129                         OnJSONParseSucceeded)
130     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed,
131                         OnJSONParseFailed)
132     IPC_MESSAGE_UNHANDLED(handled = false)
133   IPC_END_MESSAGE_MAP()
134   return handled;
135 }
136
137
138 void WebstoreInstallHelper::OnDecodeImageSucceeded(
139     const SkBitmap& decoded_image) {
140   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
141   icon_ = decoded_image;
142   icon_decode_complete_ = true;
143   ReportResultsIfComplete();
144 }
145
146 void WebstoreInstallHelper::OnDecodeImageFailed() {
147   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
148   icon_decode_complete_ = true;
149   error_ = kImageDecodeError;
150   parse_error_ = Delegate::ICON_ERROR;
151   ReportResultsIfComplete();
152 }
153
154 void WebstoreInstallHelper::OnJSONParseSucceeded(
155     const base::ListValue& wrapper) {
156   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
157   manifest_parse_complete_ = true;
158   const base::Value* value = NULL;
159   CHECK(wrapper.Get(0, &value));
160   if (value->IsType(base::Value::TYPE_DICTIONARY)) {
161     parsed_manifest_.reset(
162         static_cast<const base::DictionaryValue*>(value)->DeepCopy());
163   } else {
164     parse_error_ = Delegate::MANIFEST_ERROR;
165   }
166   ReportResultsIfComplete();
167 }
168
169 void WebstoreInstallHelper::OnJSONParseFailed(
170     const std::string& error_message) {
171   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
172   manifest_parse_complete_ = true;
173   error_ = error_message;
174   parse_error_ = Delegate::MANIFEST_ERROR;
175   ReportResultsIfComplete();
176 }
177
178 void WebstoreInstallHelper::ReportResultsIfComplete() {
179   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
180
181   if (!icon_decode_complete_ || !manifest_parse_complete_)
182     return;
183
184   // The utility_host_ will take care of deleting itself after this call.
185   if (utility_host_.get()) {
186     utility_host_->EndBatchMode();
187     utility_host_.reset();
188   }
189
190   BrowserThread::PostTask(
191       BrowserThread::UI,
192       FROM_HERE,
193       base::Bind(&WebstoreInstallHelper::ReportResultFromUIThread, this));
194 }
195
196 void WebstoreInstallHelper::ReportResultFromUIThread() {
197   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198   if (error_.empty() && parsed_manifest_)
199     delegate_->OnWebstoreParseSuccess(id_, icon_, parsed_manifest_.release());
200   else
201     delegate_->OnWebstoreParseFailure(id_, parse_error_, error_);
202 }
203
204 }  // namespace extensions