OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_webstore_private_api.h" | 5 #include "chrome/browser/extensions/extension_webstore_private_api.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/scoped_temp_dir.h" | 10 #include "base/scoped_temp_dir.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "chrome/common/chrome_notification_types.h" | 23 #include "chrome/common/chrome_notification_types.h" |
24 #include "chrome/common/chrome_switches.h" | 24 #include "chrome/common/chrome_switches.h" |
25 #include "chrome/common/chrome_utility_messages.h" | 25 #include "chrome/common/chrome_utility_messages.h" |
26 #include "chrome/common/extensions/extension_constants.h" | 26 #include "chrome/common/extensions/extension_constants.h" |
27 #include "chrome/common/extensions/extension_error_utils.h" | 27 #include "chrome/common/extensions/extension_error_utils.h" |
28 #include "chrome/common/extensions/extension_l10n_util.h" | 28 #include "chrome/common/extensions/extension_l10n_util.h" |
29 #include "chrome/common/net/gaia/gaia_constants.h" | 29 #include "chrome/common/net/gaia/gaia_constants.h" |
30 #include "content/browser/tab_contents/tab_contents.h" | 30 #include "content/browser/tab_contents/tab_contents.h" |
31 #include "content/common/notification_details.h" | 31 #include "content/common/notification_details.h" |
32 #include "content/common/notification_source.h" | 32 #include "content/common/notification_source.h" |
| 33 #include "content/common/url_fetcher.h" |
33 #include "grit/chromium_strings.h" | 34 #include "grit/chromium_strings.h" |
34 #include "grit/generated_resources.h" | 35 #include "grit/generated_resources.h" |
| 36 #include "net/url_request/url_request_status.h" |
35 #include "ui/base/l10n/l10n_util.h" | 37 #include "ui/base/l10n/l10n_util.h" |
36 | 38 |
37 namespace { | 39 namespace { |
38 | 40 |
39 const char kAppInstallBubbleKey[] = "appInstallBubble"; | 41 const char kAppInstallBubbleKey[] = "appInstallBubble"; |
40 const char kIconDataKey[] = "iconData"; | 42 const char kIconDataKey[] = "iconData"; |
| 43 const char kIconUrlKey[] = "iconUrl"; |
41 const char kIdKey[] = "id"; | 44 const char kIdKey[] = "id"; |
42 const char kLocalizedNameKey[] = "localizedName"; | 45 const char kLocalizedNameKey[] = "localizedName"; |
43 const char kLoginKey[] = "login"; | 46 const char kLoginKey[] = "login"; |
44 const char kManifestKey[] = "manifest"; | 47 const char kManifestKey[] = "manifest"; |
45 const char kTokenKey[] = "token"; | 48 const char kTokenKey[] = "token"; |
46 | 49 |
| 50 const char kCannotSpecifyIconDataAndUrlError[] = |
| 51 "You cannot specify both icon data and an icon url"; |
47 const char kImageDecodeError[] = "Image decode failed"; | 52 const char kImageDecodeError[] = "Image decode failed"; |
| 53 const char kInvalidIconUrlError[] = "Invalid icon url"; |
48 const char kInvalidIdError[] = "Invalid id"; | 54 const char kInvalidIdError[] = "Invalid id"; |
49 const char kInvalidManifestError[] = "Invalid manifest"; | 55 const char kInvalidManifestError[] = "Invalid manifest"; |
50 const char kNoPreviousBeginInstallError[] = | 56 const char kNoPreviousBeginInstallError[] = |
51 "* does not match a previous call to beginInstall"; | 57 "* does not match a previous call to beginInstall"; |
52 const char kUserCancelledError[] = "User cancelled install"; | 58 const char kUserCancelledError[] = "User cancelled install"; |
53 const char kUserGestureRequiredError[] = | 59 const char kUserGestureRequiredError[] = |
54 "This function must be called during a user gesture"; | 60 "This function must be called during a user gesture"; |
55 | 61 |
56 ProfileSyncService* test_sync_service = NULL; | 62 ProfileSyncService* test_sync_service = NULL; |
57 BrowserSignin* test_signin = NULL; | 63 BrowserSignin* test_signin = NULL; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 } | 151 } |
146 | 152 |
147 // This gets cleared in CrxInstaller::ConfirmInstall(). TODO(asargent) - in | 153 // This gets cleared in CrxInstaller::ConfirmInstall(). TODO(asargent) - in |
148 // the future we may also want to add time-based expiration, where a whitelist | 154 // the future we may also want to add time-based expiration, where a whitelist |
149 // entry is only valid for some number of minutes. | 155 // entry is only valid for some number of minutes. |
150 CrxInstaller::SetWhitelistedInstallId(id); | 156 CrxInstaller::SetWhitelistedInstallId(id); |
151 return true; | 157 return true; |
152 } | 158 } |
153 | 159 |
154 // This is a class to help BeginInstallWithManifestFunction manage sending | 160 // This is a class to help BeginInstallWithManifestFunction manage sending |
155 // JSON manifests and base64-encoded icon data to the utility process for | 161 // work to the utility process for parsing manifests and fetching/decoding |
156 // parsing. | 162 // icon data. |
157 class SafeBeginInstallHelper : public UtilityProcessHost::Client { | 163 class SafeBeginInstallHelper : public UtilityProcessHost::Client, |
| 164 public URLFetcher::Delegate { |
158 public: | 165 public: |
| 166 // Only one of icon_data or icon_url should be non-empty. If icon_url is |
| 167 // non-empty, context_getter should be filled in, but otherwise NULL. |
159 SafeBeginInstallHelper(BeginInstallWithManifestFunction* client, | 168 SafeBeginInstallHelper(BeginInstallWithManifestFunction* client, |
| 169 const std::string& manifest, |
160 const std::string& icon_data, | 170 const std::string& icon_data, |
161 const std::string& manifest) | 171 const GURL& icon_url, |
| 172 net::URLRequestContextGetter* context_getter) |
162 : client_(client), | 173 : client_(client), |
163 icon_data_(icon_data), | |
164 manifest_(manifest), | 174 manifest_(manifest), |
| 175 icon_base64_data_(icon_data), |
| 176 icon_url_(icon_url), |
| 177 context_getter_(context_getter), |
165 utility_host_(NULL), | 178 utility_host_(NULL), |
166 icon_decode_complete_(false), | 179 icon_decode_complete_(false), |
167 manifest_parse_complete_(false), | 180 manifest_parse_complete_(false), |
168 parse_error_(BeginInstallWithManifestFunction::UNKNOWN_ERROR) {} | 181 parse_error_(BeginInstallWithManifestFunction::UNKNOWN_ERROR) {} |
169 | 182 |
170 void Start() { | 183 void Start() { |
171 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 184 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 185 CHECK(icon_base64_data_.empty() || icon_url_.is_empty()); |
| 186 |
| 187 if (icon_base64_data_.empty() && icon_url_.is_empty()) |
| 188 icon_decode_complete_ = true; |
| 189 |
172 BrowserThread::PostTask( | 190 BrowserThread::PostTask( |
173 BrowserThread::IO, | 191 BrowserThread::IO, |
174 FROM_HERE, | 192 FROM_HERE, |
175 NewRunnableMethod(this, | 193 NewRunnableMethod(this, |
176 &SafeBeginInstallHelper::StartWorkOnIOThread)); | 194 &SafeBeginInstallHelper::StartWorkOnIOThread)); |
| 195 |
| 196 if (!icon_url_.is_empty()) { |
| 197 CHECK(context_getter_); |
| 198 url_fetcher_.reset(new URLFetcher(icon_url_, URLFetcher::GET, this)); |
| 199 url_fetcher_->set_request_context(context_getter_); |
| 200 |
| 201 url_fetcher_->Start(); |
| 202 // We'll get called back in OnURLFetchComplete. |
| 203 } |
177 } | 204 } |
178 | 205 |
179 void StartWorkOnIOThread() { | 206 void StartWorkOnIOThread() { |
180 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 207 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
181 utility_host_ = new UtilityProcessHost(this, BrowserThread::IO); | 208 utility_host_ = new UtilityProcessHost(this, BrowserThread::IO); |
182 utility_host_->StartBatchMode(); | 209 utility_host_->StartBatchMode(); |
183 if (icon_data_.empty()) | 210 |
184 icon_decode_complete_ = true; | 211 if (!icon_base64_data_.empty()) |
185 else | 212 utility_host_->Send( |
186 utility_host_->Send(new ChromeUtilityMsg_DecodeImageBase64(icon_data_)); | 213 new ChromeUtilityMsg_DecodeImageBase64(icon_base64_data_)); |
| 214 |
187 utility_host_->Send(new ChromeUtilityMsg_ParseJSON(manifest_)); | 215 utility_host_->Send(new ChromeUtilityMsg_ParseJSON(manifest_)); |
188 } | 216 } |
189 | 217 |
| 218 // Implementing the URLFetcher::Delegate interface. |
| 219 virtual void OnURLFetchComplete(const URLFetcher* source) OVERRIDE { |
| 220 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 221 CHECK(source == url_fetcher_.get()); |
| 222 if (source->status().status() != net::URLRequestStatus::SUCCESS || |
| 223 source->response_code() != 200) { |
| 224 BrowserThread::PostTask( |
| 225 BrowserThread::IO, |
| 226 FROM_HERE, |
| 227 NewRunnableMethod(this, |
| 228 &SafeBeginInstallHelper::OnDecodeImageFailed)); |
| 229 } else { |
| 230 std::string response_data; |
| 231 source->GetResponseAsString(&response_data); |
| 232 fetched_icon_data_.insert(fetched_icon_data_.begin(), |
| 233 response_data.begin(), |
| 234 response_data.end()); |
| 235 BrowserThread::PostTask( |
| 236 BrowserThread::IO, |
| 237 FROM_HERE, |
| 238 NewRunnableMethod(this, |
| 239 &SafeBeginInstallHelper::StartFetchedImageDecode)); |
| 240 } |
| 241 url_fetcher_.reset(); |
| 242 } |
| 243 |
| 244 void StartFetchedImageDecode() { |
| 245 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 246 CHECK(utility_host_); |
| 247 utility_host_->Send(new ChromeUtilityMsg_DecodeImage(fetched_icon_data_)); |
| 248 } |
| 249 |
190 // Implementing pieces of the UtilityProcessHost::Client interface. | 250 // Implementing pieces of the UtilityProcessHost::Client interface. |
191 virtual bool OnMessageReceived(const IPC::Message& message) { | 251 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
192 bool handled = true; | 252 bool handled = true; |
193 IPC_BEGIN_MESSAGE_MAP(SafeBeginInstallHelper, message) | 253 IPC_BEGIN_MESSAGE_MAP(SafeBeginInstallHelper, message) |
194 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Succeeded, | 254 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Succeeded, |
195 OnDecodeImageSucceeded) | 255 OnDecodeImageSucceeded) |
196 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Failed, | 256 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Failed, |
197 OnDecodeImageFailed) | 257 OnDecodeImageFailed) |
198 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, | 258 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, |
199 OnJSONParseSucceeded) | 259 OnJSONParseSucceeded) |
200 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, | 260 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, |
201 OnJSONParseFailed) | 261 OnJSONParseFailed) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 else | 325 else |
266 client_->OnParseFailure(parse_error_, error_); | 326 client_->OnParseFailure(parse_error_, error_); |
267 } | 327 } |
268 | 328 |
269 private: | 329 private: |
270 ~SafeBeginInstallHelper() {} | 330 ~SafeBeginInstallHelper() {} |
271 | 331 |
272 // The client who we'll report results back to. | 332 // The client who we'll report results back to. |
273 BeginInstallWithManifestFunction* client_; | 333 BeginInstallWithManifestFunction* client_; |
274 | 334 |
275 // The data to parse. | 335 // The manifest to parse. |
276 std::string icon_data_; | |
277 std::string manifest_; | 336 std::string manifest_; |
278 | 337 |
| 338 // Only one of these should be non-empty. If |icon_base64_data_| is non-emtpy, |
| 339 // it's a base64-encoded string that needs to be parsed into an SkBitmap. If |
| 340 // |icon_url_| is non-empty, it needs to be fetched and decoded into an |
| 341 // SkBitmap. |
| 342 std::string icon_base64_data_; |
| 343 GURL icon_url_; |
| 344 std::vector<unsigned char> fetched_icon_data_; |
| 345 |
| 346 // For fetching the icon, if needed. |
| 347 scoped_ptr<URLFetcher> url_fetcher_; |
| 348 net::URLRequestContextGetter* context_getter_; // Only usable on UI thread. |
| 349 |
279 UtilityProcessHost* utility_host_; | 350 UtilityProcessHost* utility_host_; |
280 | 351 |
281 // Flags for whether we're done doing icon decoding and manifest parsing. | 352 // Flags for whether we're done doing icon decoding and manifest parsing. |
282 bool icon_decode_complete_; | 353 bool icon_decode_complete_; |
283 bool manifest_parse_complete_; | 354 bool manifest_parse_complete_; |
284 | 355 |
285 // The results of succesful decoding/parsing. | 356 // The results of succesful decoding/parsing. |
286 SkBitmap icon_; | 357 SkBitmap icon_; |
287 scoped_ptr<DictionaryValue> parsed_manifest_; | 358 scoped_ptr<DictionaryValue> parsed_manifest_; |
288 | 359 |
(...skipping 28 matching lines...) Expand all Loading... |
317 | 388 |
318 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIdKey, &id_)); | 389 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIdKey, &id_)); |
319 if (!Extension::IdIsValid(id_)) { | 390 if (!Extension::IdIsValid(id_)) { |
320 SetResult(INVALID_ID); | 391 SetResult(INVALID_ID); |
321 error_ = kInvalidIdError; | 392 error_ = kInvalidIdError; |
322 return false; | 393 return false; |
323 } | 394 } |
324 | 395 |
325 EXTENSION_FUNCTION_VALIDATE(details->GetString(kManifestKey, &manifest_)); | 396 EXTENSION_FUNCTION_VALIDATE(details->GetString(kManifestKey, &manifest_)); |
326 | 397 |
| 398 if (details->HasKey(kIconDataKey) && details->HasKey(kIconUrlKey)) { |
| 399 SetResult(ICON_ERROR); |
| 400 error_ = kCannotSpecifyIconDataAndUrlError; |
| 401 return false; |
| 402 } |
| 403 |
327 if (details->HasKey(kIconDataKey)) | 404 if (details->HasKey(kIconDataKey)) |
328 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIconDataKey, &icon_data_)); | 405 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIconDataKey, &icon_data_)); |
329 | 406 |
| 407 GURL icon_url; |
| 408 if (details->HasKey(kIconUrlKey)) { |
| 409 std::string tmp_url; |
| 410 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIconUrlKey, &tmp_url)); |
| 411 icon_url = source_url().Resolve(tmp_url); |
| 412 if (!icon_url.is_valid()) { |
| 413 SetResult(INVALID_ICON_URL); |
| 414 error_ = kInvalidIconUrlError; |
| 415 return false; |
| 416 } |
| 417 } |
| 418 |
330 if (details->HasKey(kLocalizedNameKey)) | 419 if (details->HasKey(kLocalizedNameKey)) |
331 EXTENSION_FUNCTION_VALIDATE(details->GetString(kLocalizedNameKey, | 420 EXTENSION_FUNCTION_VALIDATE(details->GetString(kLocalizedNameKey, |
332 &localized_name_)); | 421 &localized_name_)); |
333 | 422 |
334 if (details->HasKey(kAppInstallBubbleKey)) | 423 if (details->HasKey(kAppInstallBubbleKey)) |
335 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean( | 424 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean( |
336 kAppInstallBubbleKey, &use_app_installed_bubble_)); | 425 kAppInstallBubbleKey, &use_app_installed_bubble_)); |
337 | 426 |
338 scoped_refptr<SafeBeginInstallHelper> helper = | 427 net::URLRequestContextGetter* context_getter = NULL; |
339 new SafeBeginInstallHelper(this, icon_data_, manifest_); | 428 if (!icon_url.is_empty()) |
340 // The helper will call us back via OnParseSucces or OnParseFailure. | 429 context_getter = profile()->GetRequestContext(); |
| 430 |
| 431 scoped_refptr<SafeBeginInstallHelper> helper = new SafeBeginInstallHelper( |
| 432 this, manifest_, icon_data_, icon_url, context_getter); |
| 433 |
| 434 // The helper will call us back via OnParseSuccess or OnParseFailure. |
341 helper->Start(); | 435 helper->Start(); |
342 | 436 |
343 // Matched with a Release in OnSuccess/OnFailure. | 437 // Matched with a Release in OnParseSuccess/OnParseFailure. |
344 AddRef(); | 438 AddRef(); |
345 | 439 |
346 // The response is sent asynchronously in OnSuccess/OnFailure. | 440 // The response is sent asynchronously in OnParseSuccess/OnParseFailure. |
347 return true; | 441 return true; |
348 } | 442 } |
349 | 443 |
350 | 444 |
351 void BeginInstallWithManifestFunction::SetResult(ResultCode code) { | 445 void BeginInstallWithManifestFunction::SetResult(ResultCode code) { |
352 switch (code) { | 446 switch (code) { |
353 case ERROR_NONE: | 447 case ERROR_NONE: |
354 result_.reset(Value::CreateStringValue("")); | 448 result_.reset(Value::CreateStringValue("")); |
355 break; | 449 break; |
356 case UNKNOWN_ERROR: | 450 case UNKNOWN_ERROR: |
(...skipping 10 matching lines...) Expand all Loading... |
367 break; | 461 break; |
368 case INVALID_ID: | 462 case INVALID_ID: |
369 result_.reset(Value::CreateStringValue("invalid_id")); | 463 result_.reset(Value::CreateStringValue("invalid_id")); |
370 break; | 464 break; |
371 case PERMISSION_DENIED: | 465 case PERMISSION_DENIED: |
372 result_.reset(Value::CreateStringValue("permission_denied")); | 466 result_.reset(Value::CreateStringValue("permission_denied")); |
373 break; | 467 break; |
374 case NO_GESTURE: | 468 case NO_GESTURE: |
375 result_.reset(Value::CreateStringValue("no_gesture")); | 469 result_.reset(Value::CreateStringValue("no_gesture")); |
376 break; | 470 break; |
| 471 case INVALID_ICON_URL: |
| 472 result_.reset(Value::CreateStringValue("invalid_icon_url")); |
| 473 break; |
377 default: | 474 default: |
378 CHECK(false); | 475 CHECK(false); |
379 } | 476 } |
380 } | 477 } |
381 | 478 |
382 // static | 479 // static |
383 void BeginInstallWithManifestFunction::SetIgnoreUserGestureForTests( | 480 void BeginInstallWithManifestFunction::SetIgnoreUserGestureForTests( |
384 bool ignore) { | 481 bool ignore) { |
385 ignore_user_gesture_for_tests = ignore; | 482 ignore_user_gesture_for_tests = ignore; |
386 } | 483 } |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 } | 766 } |
670 | 767 |
671 DCHECK(waiting_for_token_); | 768 DCHECK(waiting_for_token_); |
672 | 769 |
673 result_.reset(CreateLoginResult(profile_->GetOriginalProfile())); | 770 result_.reset(CreateLoginResult(profile_->GetOriginalProfile())); |
674 SendResponse(true); | 771 SendResponse(true); |
675 | 772 |
676 // Matches the AddRef in RunImpl(). | 773 // Matches the AddRef in RunImpl(). |
677 Release(); | 774 Release(); |
678 } | 775 } |
OLD | NEW |