Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/api/downloads/downloads_api.h" | 5 #include "chrome/browser/extensions/api/downloads/downloads_api.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cctype> | 8 #include <cctype> |
| 9 #include <iterator> | 9 #include <iterator> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <string> | 11 #include <string> |
| 12 | 12 |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/callback.h" | 16 #include "base/callback.h" |
| 17 #include "base/file_path.h" | |
| 17 #include "base/json/json_writer.h" | 18 #include "base/json/json_writer.h" |
| 18 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
| 19 #include "base/logging.h" | 20 #include "base/logging.h" |
| 20 #include "base/metrics/histogram.h" | 21 #include "base/metrics/histogram.h" |
| 21 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
| 22 #include "base/string16.h" | 23 #include "base/string16.h" |
| 23 #include "base/string_split.h" | 24 #include "base/string_split.h" |
| 24 #include "base/string_util.h" | 25 #include "base/string_util.h" |
| 25 #include "base/stringprintf.h" | 26 #include "base/stringprintf.h" |
| 27 #include "base/strings/string_number_conversions.h" | |
| 26 #include "base/values.h" | 28 #include "base/values.h" |
| 27 #include "chrome/browser/browser_process.h" | 29 #include "chrome/browser/browser_process.h" |
| 28 #include "chrome/browser/download/download_danger_prompt.h" | 30 #include "chrome/browser/download/download_danger_prompt.h" |
| 29 #include "chrome/browser/download/download_file_icon_extractor.h" | 31 #include "chrome/browser/download/download_file_icon_extractor.h" |
| 30 #include "chrome/browser/download/download_query.h" | 32 #include "chrome/browser/download/download_query.h" |
| 31 #include "chrome/browser/download/download_service.h" | 33 #include "chrome/browser/download/download_service.h" |
| 32 #include "chrome/browser/download/download_service_factory.h" | 34 #include "chrome/browser/download/download_service_factory.h" |
| 33 #include "chrome/browser/download/download_util.h" | 35 #include "chrome/browser/download/download_util.h" |
| 34 #include "chrome/browser/extensions/event_names.h" | 36 #include "chrome/browser/extensions/event_names.h" |
| 35 #include "chrome/browser/extensions/event_router.h" | 37 #include "chrome/browser/extensions/event_router.h" |
| 36 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 38 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
| 39 #include "chrome/browser/extensions/extension_info_map.h" | |
| 40 #include "chrome/browser/extensions/extension_prefs.h" | |
| 41 #include "chrome/browser/extensions/extension_service.h" | |
| 37 #include "chrome/browser/extensions/extension_system.h" | 42 #include "chrome/browser/extensions/extension_system.h" |
| 38 #include "chrome/browser/icon_loader.h" | 43 #include "chrome/browser/icon_loader.h" |
| 39 #include "chrome/browser/icon_manager.h" | 44 #include "chrome/browser/icon_manager.h" |
| 40 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | 45 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
| 41 #include "chrome/browser/ui/browser.h" | 46 #include "chrome/browser/ui/browser.h" |
| 42 #include "chrome/common/cancelable_task_tracker.h" | 47 #include "chrome/common/cancelable_task_tracker.h" |
| 43 #include "chrome/common/chrome_notification_types.h" | 48 #include "chrome/common/chrome_notification_types.h" |
| 44 #include "chrome/common/extensions/api/downloads.h" | 49 #include "chrome/common/extensions/api/downloads.h" |
| 45 #include "content/public/browser/download_interrupt_reasons.h" | 50 #include "content/public/browser/download_interrupt_reasons.h" |
| 46 #include "content/public/browser/download_item.h" | 51 #include "content/public/browser/download_item.h" |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 } | 182 } |
| 178 | 183 |
| 179 DownloadItem::DownloadState StateEnumFromString(const std::string& state) { | 184 DownloadItem::DownloadState StateEnumFromString(const std::string& state) { |
| 180 for (size_t i = 0; i < arraysize(kStateStrings); ++i) { | 185 for (size_t i = 0; i < arraysize(kStateStrings); ++i) { |
| 181 if ((kStateStrings[i] != NULL) && (state == kStateStrings[i])) | 186 if ((kStateStrings[i] != NULL) && (state == kStateStrings[i])) |
| 182 return static_cast<DownloadItem::DownloadState>(i); | 187 return static_cast<DownloadItem::DownloadState>(i); |
| 183 } | 188 } |
| 184 return DownloadItem::MAX_DOWNLOAD_STATE; | 189 return DownloadItem::MAX_DOWNLOAD_STATE; |
| 185 } | 190 } |
| 186 | 191 |
| 187 bool ValidateFilename(const string16& filename) { | 192 bool ValidateFilename(const base::FilePath& filename) { |
| 188 // TODO(benjhayden): More robust validation of filename. | 193 return !filename.empty() && |
|
asanka
2013/02/22 18:55:48
"foo/" shouldn't be considered a valid filename ei
benjhayden
2013/02/22 20:43:23
I believe that the next line handles that case.
asanka
2013/02/22 21:22:29
For "foo/" BaseName() returns "foo".
| |
| 189 if ((filename.find('/') != string16::npos) || | 194 (filename.BaseName().value() != base::FilePath::kCurrentDirectory) && |
| 190 (filename.find('\\') != string16::npos)) | 195 !filename.ReferencesParent() && |
| 191 return false; | 196 !filename.IsAbsolute(); |
| 192 if (filename.size() >= 2u && filename[0] == L'.' && filename[1] == L'.') | |
| 193 return false; | |
| 194 return true; | |
| 195 } | 197 } |
| 196 | 198 |
| 197 std::string TimeToISO8601(const base::Time& t) { | 199 std::string TimeToISO8601(const base::Time& t) { |
| 198 base::Time::Exploded exploded; | 200 base::Time::Exploded exploded; |
| 199 t.UTCExplode(&exploded); | 201 t.UTCExplode(&exploded); |
| 200 return base::StringPrintf( | 202 return base::StringPrintf( |
| 201 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, | 203 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, |
| 202 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, | 204 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, |
| 203 exploded.millisecond); | 205 exploded.millisecond); |
| 204 } | 206 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 }; | 258 }; |
| 257 | 259 |
| 258 bool DownloadFileIconExtractorImpl::ExtractIconURLForPath( | 260 bool DownloadFileIconExtractorImpl::ExtractIconURLForPath( |
| 259 const base::FilePath& path, | 261 const base::FilePath& path, |
| 260 IconLoader::IconSize icon_size, | 262 IconLoader::IconSize icon_size, |
| 261 IconURLCallback callback) { | 263 IconURLCallback callback) { |
| 262 callback_ = callback; | 264 callback_ = callback; |
| 263 IconManager* im = g_browser_process->icon_manager(); | 265 IconManager* im = g_browser_process->icon_manager(); |
| 264 // The contents of the file at |path| may have changed since a previous | 266 // The contents of the file at |path| may have changed since a previous |
| 265 // request, in which case the associated icon may also have changed. | 267 // request, in which case the associated icon may also have changed. |
| 266 // Therefore, for the moment we always call LoadIcon instead of attempting | 268 // Therefore, always call LoadIcon instead of attempting a LookupIcon. |
| 267 // a LookupIcon. | |
| 268 im->LoadIcon(path, | 269 im->LoadIcon(path, |
| 269 icon_size, | 270 icon_size, |
| 270 base::Bind(&DownloadFileIconExtractorImpl::OnIconLoadComplete, | 271 base::Bind(&DownloadFileIconExtractorImpl::OnIconLoadComplete, |
| 271 base::Unretained(this)), | 272 base::Unretained(this)), |
| 272 &cancelable_task_tracker_); | 273 &cancelable_task_tracker_); |
| 273 return true; | 274 return true; |
| 274 } | 275 } |
| 275 | 276 |
| 276 void DownloadFileIconExtractorImpl::OnIconLoadComplete(gfx::Image* icon) { | 277 void DownloadFileIconExtractorImpl::OnIconLoadComplete(gfx::Image* icon) { |
| 277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 404 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
| 404 // comparisons. | 405 // comparisons. |
| 405 static base::LazyInstance<SortTypeMap> sorter_types = | 406 static base::LazyInstance<SortTypeMap> sorter_types = |
| 406 LAZY_INSTANCE_INITIALIZER; | 407 LAZY_INSTANCE_INITIALIZER; |
| 407 if (sorter_types.Get().size() == 0) | 408 if (sorter_types.Get().size() == 0) |
| 408 InitSortTypeMap(sorter_types.Get()); | 409 InitSortTypeMap(sorter_types.Get()); |
| 409 | 410 |
| 410 std::vector<std::string> order_by_strs; | 411 std::vector<std::string> order_by_strs; |
| 411 base::SplitString(order_by_str, ' ', &order_by_strs); | 412 base::SplitString(order_by_str, ' ', &order_by_strs); |
| 412 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); | 413 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); |
| 413 iter != order_by_strs.end(); ++iter) { | 414 iter != order_by_strs.end(); ++iter) { |
| 414 std::string term_str = *iter; | 415 std::string term_str = *iter; |
| 415 if (term_str.empty()) | 416 if (term_str.empty()) |
| 416 continue; | 417 continue; |
| 417 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; | 418 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; |
| 418 if (term_str[0] == '-') { | 419 if (term_str[0] == '-') { |
| 419 direction = DownloadQuery::DESCENDING; | 420 direction = DownloadQuery::DESCENDING; |
| 420 term_str = term_str.substr(1); | 421 term_str = term_str.substr(1); |
| 421 } | 422 } |
| 422 SortTypeMap::const_iterator sorter_type = | 423 SortTypeMap::const_iterator sorter_type = |
| 423 sorter_types.Get().find(term_str); | 424 sorter_types.Get().find(term_str); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 500 all_items.push_back(download_item); | 501 all_items.push_back(download_item); |
| 501 } else { | 502 } else { |
| 502 manager->GetAllDownloads(&all_items); | 503 manager->GetAllDownloads(&all_items); |
| 503 if (incognito_manager) | 504 if (incognito_manager) |
| 504 incognito_manager->GetAllDownloads(&all_items); | 505 incognito_manager->GetAllDownloads(&all_items); |
| 505 } | 506 } |
| 506 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); | 507 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); |
| 507 query_out.Search(all_items.begin(), all_items.end(), results); | 508 query_out.Search(all_items.begin(), all_items.end(), results); |
| 508 } | 509 } |
| 509 | 510 |
| 510 void DispatchEventInternal( | |
| 511 Profile* target_profile, | |
| 512 const char* event_name, | |
| 513 const std::string& json_args, | |
| 514 scoped_ptr<base::ListValue> event_args) { | |
| 515 if (!extensions::ExtensionSystem::Get(target_profile)->event_router()) | |
| 516 return; | |
| 517 scoped_ptr<extensions::Event> event(new extensions::Event( | |
| 518 event_name, event_args.Pass())); | |
| 519 event->restrict_to_profile = target_profile; | |
| 520 extensions::ExtensionSystem::Get(target_profile)->event_router()-> | |
| 521 BroadcastEvent(event.Pass()); | |
| 522 ExtensionDownloadsEventRouter::DownloadsNotificationSource | |
| 523 notification_source; | |
| 524 notification_source.event_name = event_name; | |
| 525 notification_source.profile = target_profile; | |
| 526 content::Source<ExtensionDownloadsEventRouter::DownloadsNotificationSource> | |
| 527 content_source(¬ification_source); | |
| 528 std::string args_copy(json_args); | |
| 529 content::NotificationService::current()->Notify( | |
| 530 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | |
| 531 content_source, | |
| 532 content::Details<std::string>(&args_copy)); | |
| 533 } | |
| 534 | |
| 535 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { | 511 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { |
| 536 public: | 512 public: |
| 537 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { | 513 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { |
| 538 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); | 514 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); |
| 539 return (data == NULL) ? NULL : | 515 return (data == NULL) ? NULL : |
| 540 static_cast<ExtensionDownloadsEventRouterData*>(data); | 516 static_cast<ExtensionDownloadsEventRouterData*>(data); |
| 541 } | 517 } |
| 542 | 518 |
| 543 explicit ExtensionDownloadsEventRouterData( | 519 explicit ExtensionDownloadsEventRouterData( |
| 544 DownloadItem* download_item, | 520 DownloadItem* download_item, |
| 545 scoped_ptr<base::DictionaryValue> json_item) | 521 scoped_ptr<base::DictionaryValue> json_item) |
| 546 : updated_(0), | 522 : updated_(0), |
| 547 changed_fired_(0), | 523 changed_fired_(0), |
| 548 json_(json_item.Pass()) { | 524 json_(json_item.Pass()), |
| 525 determined_overwrite_(false) { | |
| 549 download_item->SetUserData(kKey, this); | 526 download_item->SetUserData(kKey, this); |
| 550 } | 527 } |
| 551 | 528 |
| 552 virtual ~ExtensionDownloadsEventRouterData() { | 529 virtual ~ExtensionDownloadsEventRouterData() { |
| 553 if (updated_ > 0) { | 530 if (updated_ > 0) { |
| 554 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", | 531 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", |
| 555 (changed_fired_ * 100 / updated_)); | 532 (changed_fired_ * 100 / updated_)); |
| 556 } | 533 } |
| 557 } | 534 } |
| 558 | 535 |
| 559 const base::DictionaryValue& json() const { return *json_.get(); } | 536 const base::DictionaryValue& json() const { return *json_.get(); } |
| 560 void set_json(scoped_ptr<base::DictionaryValue> json_item) { | 537 void set_json(scoped_ptr<base::DictionaryValue> json_item) { |
| 561 json_ = json_item.Pass(); | 538 json_ = json_item.Pass(); |
| 562 } | 539 } |
| 563 | 540 |
| 564 void OnItemUpdated() { ++updated_; } | 541 void OnItemUpdated() { ++updated_; } |
| 565 void OnChangedFired() { ++changed_fired_; } | 542 void OnChangedFired() { ++changed_fired_; } |
| 566 | 543 |
| 544 void set_filename_change_callbacks( | |
| 545 const base::Closure& no_change, | |
| 546 const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) { | |
| 547 filename_no_change_ = no_change; | |
| 548 filename_change_ = change; | |
| 549 } | |
| 550 | |
| 551 void ClearPendingDeterminers() { | |
| 552 determiners_.clear(); | |
| 553 determined_filename_.clear(); | |
| 554 determined_overwrite_ = false; | |
| 555 determiner_ = DeterminerInfo(); | |
| 556 filename_no_change_ = base::Closure(); | |
| 557 filename_change_ = ExtensionDownloadsEventRouter::FilenameChangedCallback(); | |
| 558 } | |
| 559 | |
| 560 void ExtensionUnloaded(const std::string& extension_id) { | |
| 561 // Remove this extension from |determiners_|. | |
| 562 for (DeterminerInfoVector::iterator iter = determiners_.begin(); | |
| 563 iter != determiners_.end();) { | |
| 564 if (iter->extension_id == extension_id) { | |
| 565 iter = determiners_.erase(iter); | |
| 566 } else { | |
| 567 ++iter; | |
| 568 } | |
| 569 } | |
| 570 // If we just removed the last unreported determiner, then we need to call a | |
| 571 // callback. | |
| 572 CheckAllDeterminersCalled(); | |
| 573 } | |
| 574 | |
| 575 void DeterminerRemoved(const std::string& extension_id, | |
| 576 int sub_event_id) { | |
| 577 for (DeterminerInfoVector::iterator iter = determiners_.begin(); | |
| 578 iter != determiners_.end();) { | |
| 579 if ((iter->extension_id == extension_id) && | |
| 580 (iter->sub_event_id == sub_event_id)) { | |
| 581 iter = determiners_.erase(iter); | |
| 582 } else { | |
| 583 ++iter; | |
| 584 } | |
| 585 } | |
| 586 // If we just removed the last unreported determiner, then we need to call a | |
| 587 // callback. | |
| 588 CheckAllDeterminersCalled(); | |
| 589 } | |
| 590 | |
| 591 void AddPendingDeterminer(const std::string& extension_id, | |
| 592 int sub_event_id, | |
| 593 const base::Time& installed) { | |
| 594 determiners_.push_back(DeterminerInfo( | |
| 595 extension_id, sub_event_id, installed)); | |
| 596 } | |
| 597 | |
| 598 bool DeterminerCallback( | |
| 599 const std::string& extension_id, | |
| 600 int sub_event_id, | |
| 601 const base::FilePath& filename, | |
| 602 bool overwrite) { | |
| 603 bool filename_valid = ValidateFilename(filename); | |
| 604 bool found_info = false; | |
| 605 for (int index = 0; index < static_cast<int>(determiners_.size()); | |
| 606 ++index) { | |
| 607 if ((determiners_[index].extension_id == extension_id) && | |
| 608 (determiners_[index].sub_event_id == sub_event_id)) { | |
| 609 found_info = true; | |
|
asanka
2013/02/22 18:55:48
Curious: Is it possible for there to be more than
benjhayden
2013/02/22 20:43:23
I hope not. :-)
See AddPendingDeterminer and searc
| |
| 610 DCHECK(!determiners_[index].reported); | |
| 611 determiners_[index].reported = true; | |
| 612 if (!determiner_.extension_id.empty() && | |
| 613 (determiners_[index].extension_id == determiner_.extension_id)) { | |
| 614 DCHECK_NE(determiners_[index].sub_event_id, determiner_.sub_event_id); | |
| 615 } | |
| 616 // Do not use filename if another determiner has already overridden the | |
| 617 // filename and they take precedence. Extensions that were installed | |
| 618 // later take precedence over previous extensions, and listeners that | |
| 619 // were added later take precedence over previous listeners. | |
| 620 if (filename_valid && | |
| 621 (determiner_.extension_id.empty() || | |
| 622 ((determiners_[index].extension_id == determiner_.extension_id) ? | |
| 623 (determiners_[index].sub_event_id > determiner_.sub_event_id) : | |
| 624 (determiners_[index].install_time > determiner_.install_time)))) { | |
| 625 determined_filename_ = filename; | |
| 626 determined_overwrite_ = overwrite; | |
| 627 determiner_ = determiners_[index]; | |
| 628 } | |
| 629 } | |
| 630 } | |
| 631 if (!found_info) | |
| 632 return false; | |
| 633 CheckAllDeterminersCalled(); | |
| 634 return filename.empty() || filename_valid; | |
| 635 } | |
| 636 | |
| 567 private: | 637 private: |
| 638 struct DeterminerInfo { | |
| 639 DeterminerInfo(); | |
| 640 DeterminerInfo(const std::string& e_id, | |
| 641 int sub_id, | |
| 642 const base::Time& installed); | |
| 643 ~DeterminerInfo(); | |
| 644 | |
| 645 std::string extension_id; | |
| 646 int sub_event_id; | |
| 647 base::Time install_time; | |
| 648 bool reported; | |
| 649 }; | |
| 650 typedef std::vector<DeterminerInfo> DeterminerInfoVector; | |
| 651 | |
| 568 static const char kKey[]; | 652 static const char kKey[]; |
| 569 | 653 |
| 654 // This is safe to call even while not waiting for determiners to call back; | |
| 655 // in that case, the callbacks will be null so they won't be Run. | |
| 656 void CheckAllDeterminersCalled() { | |
| 657 for (DeterminerInfoVector::iterator iter = determiners_.begin(); | |
| 658 iter != determiners_.end(); ++iter) { | |
| 659 if (!iter->reported) | |
| 660 return; | |
| 661 } | |
| 662 if (determined_filename_.empty()) { | |
| 663 if (!filename_no_change_.is_null()) | |
| 664 filename_no_change_.Run(); | |
| 665 } else { | |
| 666 if (!filename_change_.is_null()) | |
| 667 filename_change_.Run(determined_filename_, determined_overwrite_); | |
| 668 } | |
| 669 ClearPendingDeterminers(); | |
| 670 } | |
| 671 | |
| 570 int updated_; | 672 int updated_; |
| 571 int changed_fired_; | 673 int changed_fired_; |
| 572 scoped_ptr<base::DictionaryValue> json_; | 674 scoped_ptr<base::DictionaryValue> json_; |
| 573 | 675 |
| 676 base::Closure filename_no_change_; | |
| 677 ExtensionDownloadsEventRouter::FilenameChangedCallback filename_change_; | |
| 678 | |
| 679 DeterminerInfoVector determiners_; | |
| 680 | |
| 681 base::FilePath determined_filename_; | |
| 682 bool determined_overwrite_; | |
| 683 DeterminerInfo determiner_; | |
| 684 | |
| 574 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); | 685 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); |
| 575 }; | 686 }; |
| 576 | 687 |
| 688 ExtensionDownloadsEventRouterData::DeterminerInfo::DeterminerInfo( | |
| 689 const std::string& e_id, | |
| 690 int sub_id, | |
| 691 const base::Time& installed) | |
| 692 : extension_id(e_id), | |
| 693 sub_event_id(sub_id), | |
| 694 install_time(installed), | |
| 695 reported(false) { | |
| 696 } | |
| 697 | |
| 698 ExtensionDownloadsEventRouterData::DeterminerInfo::DeterminerInfo() | |
| 699 : reported(false) { | |
| 700 } | |
| 701 | |
| 702 ExtensionDownloadsEventRouterData::DeterminerInfo::~DeterminerInfo() {} | |
| 703 | |
| 577 const char ExtensionDownloadsEventRouterData::kKey[] = | 704 const char ExtensionDownloadsEventRouterData::kKey[] = |
| 578 "DownloadItem ExtensionDownloadsEventRouterData"; | 705 "DownloadItem ExtensionDownloadsEventRouterData"; |
| 579 | 706 |
| 580 class ManagerDestructionObserver : public DownloadManager::Observer { | 707 class ManagerDestructionObserver : public DownloadManager::Observer { |
| 581 public: | 708 public: |
| 582 static void CheckForHistoryFilesRemoval(DownloadManager* manager) { | 709 static void CheckForHistoryFilesRemoval(DownloadManager* manager) { |
| 583 if (!manager) | 710 if (!manager) |
| 584 return; | 711 return; |
| 585 if (!manager_file_existence_last_checked_) | 712 if (!manager_file_existence_last_checked_) |
| 586 manager_file_existence_last_checked_ = | 713 manager_file_existence_last_checked_ = |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 629 | 756 |
| 630 DISALLOW_COPY_AND_ASSIGN(ManagerDestructionObserver); | 757 DISALLOW_COPY_AND_ASSIGN(ManagerDestructionObserver); |
| 631 }; | 758 }; |
| 632 | 759 |
| 633 std::map<DownloadManager*, ManagerDestructionObserver*>* | 760 std::map<DownloadManager*, ManagerDestructionObserver*>* |
| 634 ManagerDestructionObserver::manager_file_existence_last_checked_ = NULL; | 761 ManagerDestructionObserver::manager_file_existence_last_checked_ = NULL; |
| 635 | 762 |
| 636 } // namespace | 763 } // namespace |
| 637 | 764 |
| 638 DownloadsDownloadFunction::DownloadsDownloadFunction() {} | 765 DownloadsDownloadFunction::DownloadsDownloadFunction() {} |
| 766 | |
| 639 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} | 767 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} |
| 640 | 768 |
| 641 bool DownloadsDownloadFunction::RunImpl() { | 769 bool DownloadsDownloadFunction::RunImpl() { |
| 642 scoped_ptr<extensions::api::downloads::Download::Params> params( | 770 scoped_ptr<extensions::api::downloads::Download::Params> params( |
| 643 extensions::api::downloads::Download::Params::Create(*args_)); | 771 extensions::api::downloads::Download::Params::Create(*args_)); |
| 644 EXTENSION_FUNCTION_VALIDATE(params.get()); | 772 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 645 const extensions::api::downloads::DownloadOptions& options = params->options; | 773 const extensions::api::downloads::DownloadOptions& options = params->options; |
| 646 GURL download_url(options.url); | 774 GURL download_url(options.url); |
| 647 if (!download_url.is_valid() || | 775 if (!download_url.is_valid() || |
| 648 (!download_url.SchemeIs("data") && | 776 (!download_url.SchemeIs("data") && |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 665 | 793 |
| 666 if (options.filename.get()) { | 794 if (options.filename.get()) { |
| 667 // TODO(benjhayden): Make json_schema_compiler generate string16s instead of | 795 // TODO(benjhayden): Make json_schema_compiler generate string16s instead of |
| 668 // std::strings. Can't get filename16 from options.ToValue() because that | 796 // std::strings. Can't get filename16 from options.ToValue() because that |
| 669 // converts it from std::string. | 797 // converts it from std::string. |
| 670 base::DictionaryValue* options_value = NULL; | 798 base::DictionaryValue* options_value = NULL; |
| 671 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); | 799 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); |
| 672 string16 filename16; | 800 string16 filename16; |
| 673 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( | 801 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( |
| 674 kFilenameKey, &filename16)); | 802 kFilenameKey, &filename16)); |
| 675 if (!ValidateFilename(filename16)) { | 803 #if defined(OS_WIN) |
| 804 base::FilePath file_path(filename16); | |
| 805 #elif defined(OS_POSIX) | |
| 806 base::FilePath file_path(*options.filename.get()); | |
| 807 #endif | |
| 808 if (!ValidateFilename(file_path) || | |
| 809 (file_path.DirName().value() != base::FilePath::kCurrentDirectory)) { | |
| 676 error_ = download_extension_errors::kGenericError; | 810 error_ = download_extension_errors::kGenericError; |
| 677 return false; | 811 return false; |
| 678 } | 812 } |
| 679 // TODO(benjhayden) Ensure that this filename is interpreted as a path | 813 // TODO(benjhayden) Ensure that this filename is interpreted as a path |
| 680 // relative to the default downloads directory without allowing '..'. | 814 // relative to the default downloads directory without allowing '..'. |
| 681 download_params->set_suggested_name(filename16); | 815 download_params->set_suggested_name(filename16); |
| 682 } | 816 } |
| 683 | 817 |
| 684 if (options.save_as.get()) | 818 if (options.save_as.get()) |
| 685 download_params->set_prompt(*options.save_as.get()); | 819 download_params->set_prompt(*options.save_as.get()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 DCHECK_EQ(net::OK, error); | 859 DCHECK_EQ(net::OK, error); |
| 726 SetResult(base::Value::CreateIntegerValue(item->GetId())); | 860 SetResult(base::Value::CreateIntegerValue(item->GetId())); |
| 727 } else { | 861 } else { |
| 728 DCHECK_NE(net::OK, error); | 862 DCHECK_NE(net::OK, error); |
| 729 error_ = net::ErrorToString(error); | 863 error_ = net::ErrorToString(error); |
| 730 } | 864 } |
| 731 SendResponse(error_.empty()); | 865 SendResponse(error_.empty()); |
| 732 } | 866 } |
| 733 | 867 |
| 734 DownloadsSearchFunction::DownloadsSearchFunction() {} | 868 DownloadsSearchFunction::DownloadsSearchFunction() {} |
| 869 | |
| 735 DownloadsSearchFunction::~DownloadsSearchFunction() {} | 870 DownloadsSearchFunction::~DownloadsSearchFunction() {} |
| 736 | 871 |
| 737 bool DownloadsSearchFunction::RunImpl() { | 872 bool DownloadsSearchFunction::RunImpl() { |
| 738 scoped_ptr<extensions::api::downloads::Search::Params> params( | 873 scoped_ptr<extensions::api::downloads::Search::Params> params( |
| 739 extensions::api::downloads::Search::Params::Create(*args_)); | 874 extensions::api::downloads::Search::Params::Create(*args_)); |
| 740 EXTENSION_FUNCTION_VALIDATE(params.get()); | 875 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 741 DownloadManager* manager = NULL; | 876 DownloadManager* manager = NULL; |
| 742 DownloadManager* incognito_manager = NULL; | 877 DownloadManager* incognito_manager = NULL; |
| 743 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | 878 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); |
| 744 ManagerDestructionObserver::CheckForHistoryFilesRemoval(manager); | 879 ManagerDestructionObserver::CheckForHistoryFilesRemoval(manager); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 762 scoped_ptr<base::DictionaryValue> json_item(DownloadItemToJSON( | 897 scoped_ptr<base::DictionaryValue> json_item(DownloadItemToJSON( |
| 763 *it, off_record)); | 898 *it, off_record)); |
| 764 json_results->Append(json_item.release()); | 899 json_results->Append(json_item.release()); |
| 765 } | 900 } |
| 766 SetResult(json_results); | 901 SetResult(json_results); |
| 767 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); | 902 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); |
| 768 return true; | 903 return true; |
| 769 } | 904 } |
| 770 | 905 |
| 771 DownloadsPauseFunction::DownloadsPauseFunction() {} | 906 DownloadsPauseFunction::DownloadsPauseFunction() {} |
| 907 | |
| 772 DownloadsPauseFunction::~DownloadsPauseFunction() {} | 908 DownloadsPauseFunction::~DownloadsPauseFunction() {} |
| 773 | 909 |
| 774 bool DownloadsPauseFunction::RunImpl() { | 910 bool DownloadsPauseFunction::RunImpl() { |
| 775 scoped_ptr<extensions::api::downloads::Pause::Params> params( | 911 scoped_ptr<extensions::api::downloads::Pause::Params> params( |
| 776 extensions::api::downloads::Pause::Params::Create(*args_)); | 912 extensions::api::downloads::Pause::Params::Create(*args_)); |
| 777 EXTENSION_FUNCTION_VALIDATE(params.get()); | 913 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 778 DownloadItem* download_item = GetDownloadIfInProgress( | 914 DownloadItem* download_item = GetDownloadIfInProgress( |
| 779 profile(), include_incognito(), params->download_id); | 915 profile(), include_incognito(), params->download_id); |
| 780 if (download_item == NULL) { | 916 if (download_item == NULL) { |
| 781 // This could be due to an invalid download ID, or it could be due to the | 917 // This could be due to an invalid download ID, or it could be due to the |
| 782 // download not being currently active. | 918 // download not being currently active. |
| 783 error_ = download_extension_errors::kInvalidOperationError; | 919 error_ = download_extension_errors::kInvalidOperationError; |
| 784 } else { | 920 } else { |
| 785 // If the item is already paused, this is a no-op and the | 921 // If the item is already paused, this is a no-op and the |
| 786 // operation will silently succeed. | 922 // operation will silently succeed. |
| 787 download_item->Pause(); | 923 download_item->Pause(); |
| 788 } | 924 } |
| 789 if (error_.empty()) | 925 if (error_.empty()) |
| 790 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); | 926 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); |
| 791 return error_.empty(); | 927 return error_.empty(); |
| 792 } | 928 } |
| 793 | 929 |
| 794 DownloadsResumeFunction::DownloadsResumeFunction() {} | 930 DownloadsResumeFunction::DownloadsResumeFunction() {} |
| 931 | |
| 795 DownloadsResumeFunction::~DownloadsResumeFunction() {} | 932 DownloadsResumeFunction::~DownloadsResumeFunction() {} |
| 796 | 933 |
| 797 bool DownloadsResumeFunction::RunImpl() { | 934 bool DownloadsResumeFunction::RunImpl() { |
| 798 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 935 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
| 799 extensions::api::downloads::Resume::Params::Create(*args_)); | 936 extensions::api::downloads::Resume::Params::Create(*args_)); |
| 800 EXTENSION_FUNCTION_VALIDATE(params.get()); | 937 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 801 DownloadItem* download_item = GetDownloadIfInProgress( | 938 DownloadItem* download_item = GetDownloadIfInProgress( |
| 802 profile(), include_incognito(), params->download_id); | 939 profile(), include_incognito(), params->download_id); |
| 803 if (download_item == NULL) { | 940 if (download_item == NULL) { |
| 804 // This could be due to an invalid download ID, or it could be due to the | 941 // This could be due to an invalid download ID, or it could be due to the |
| 805 // download not being currently active. | 942 // download not being currently active. |
| 806 error_ = download_extension_errors::kInvalidOperationError; | 943 error_ = download_extension_errors::kInvalidOperationError; |
| 807 } else { | 944 } else { |
| 808 // Note that if the item isn't paused, this will be a no-op, and | 945 // Note that if the item isn't paused, this will be a no-op, and |
| 809 // we will silently treat the extension call as a success. | 946 // the extension call will seem successful. |
| 810 download_item->Resume(); | 947 download_item->Resume(); |
| 811 } | 948 } |
| 812 if (error_.empty()) | 949 if (error_.empty()) |
| 813 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); | 950 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); |
| 814 return error_.empty(); | 951 return error_.empty(); |
| 815 } | 952 } |
| 816 | 953 |
| 817 DownloadsCancelFunction::DownloadsCancelFunction() {} | 954 DownloadsCancelFunction::DownloadsCancelFunction() {} |
| 955 | |
| 818 DownloadsCancelFunction::~DownloadsCancelFunction() {} | 956 DownloadsCancelFunction::~DownloadsCancelFunction() {} |
| 819 | 957 |
| 820 bool DownloadsCancelFunction::RunImpl() { | 958 bool DownloadsCancelFunction::RunImpl() { |
| 821 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 959 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
| 822 extensions::api::downloads::Resume::Params::Create(*args_)); | 960 extensions::api::downloads::Resume::Params::Create(*args_)); |
| 823 EXTENSION_FUNCTION_VALIDATE(params.get()); | 961 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 824 DownloadItem* download_item = GetDownloadIfInProgress( | 962 DownloadItem* download_item = GetDownloadIfInProgress( |
| 825 profile(), include_incognito(), params->download_id); | 963 profile(), include_incognito(), params->download_id); |
| 826 if (download_item != NULL) | 964 if (download_item != NULL) |
| 827 download_item->Cancel(true); | 965 download_item->Cancel(true); |
| 828 // |download_item| can be NULL if the download ID was invalid or if the | 966 // |download_item| can be NULL if the download ID was invalid or if the |
| 829 // download is not currently active. Either way, we don't consider it a | 967 // download is not currently active. Either way, it's not a failure. |
| 830 // failure. | |
| 831 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); | 968 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); |
| 832 return true; | 969 return true; |
| 833 } | 970 } |
| 834 | 971 |
| 835 DownloadsEraseFunction::DownloadsEraseFunction() {} | 972 DownloadsEraseFunction::DownloadsEraseFunction() {} |
| 973 | |
| 836 DownloadsEraseFunction::~DownloadsEraseFunction() {} | 974 DownloadsEraseFunction::~DownloadsEraseFunction() {} |
| 837 | 975 |
| 838 bool DownloadsEraseFunction::RunImpl() { | 976 bool DownloadsEraseFunction::RunImpl() { |
| 839 scoped_ptr<extensions::api::downloads::Erase::Params> params( | 977 scoped_ptr<extensions::api::downloads::Erase::Params> params( |
| 840 extensions::api::downloads::Erase::Params::Create(*args_)); | 978 extensions::api::downloads::Erase::Params::Create(*args_)); |
| 841 EXTENSION_FUNCTION_VALIDATE(params.get()); | 979 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 842 DownloadManager* manager = NULL; | 980 DownloadManager* manager = NULL; |
| 843 DownloadManager* incognito_manager = NULL; | 981 DownloadManager* incognito_manager = NULL; |
| 844 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | 982 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); |
| 845 DownloadQuery::DownloadVector results; | 983 DownloadQuery::DownloadVector results; |
| 846 RunDownloadQuery(params->query, | 984 RunDownloadQuery(params->query, |
| 847 manager, | 985 manager, |
| 848 incognito_manager, | 986 incognito_manager, |
| 849 &error_, | 987 &error_, |
| 850 &results); | 988 &results); |
| 851 if (!error_.empty()) | 989 if (!error_.empty()) |
| 852 return false; | 990 return false; |
| 853 base::ListValue* json_results = new base::ListValue(); | 991 base::ListValue* json_results = new base::ListValue(); |
| 854 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); | 992 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); |
| 855 it != results.end(); ++it) { | 993 it != results.end(); ++it) { |
| 856 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); | 994 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); |
| 857 (*it)->Remove(); | 995 (*it)->Remove(); |
| 858 } | 996 } |
| 859 SetResult(json_results); | 997 SetResult(json_results); |
| 860 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); | 998 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); |
| 861 return true; | 999 return true; |
| 862 } | 1000 } |
| 863 | 1001 |
| 864 DownloadsSetDestinationFunction::DownloadsSetDestinationFunction() {} | 1002 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} |
| 865 DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {} | |
| 866 | 1003 |
| 867 bool DownloadsSetDestinationFunction::RunImpl() { | |
| 868 scoped_ptr<extensions::api::downloads::SetDestination::Params> params( | |
| 869 extensions::api::downloads::SetDestination::Params::Create(*args_)); | |
| 870 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
| 871 error_ = download_extension_errors::kNotImplementedError; | |
| 872 if (error_.empty()) | |
| 873 RecordApiFunctions(DOWNLOADS_FUNCTION_SET_DESTINATION); | |
| 874 return error_.empty(); | |
| 875 } | |
| 876 | |
| 877 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} | |
| 878 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} | 1004 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} |
| 879 | 1005 |
| 880 bool DownloadsAcceptDangerFunction::RunImpl() { | 1006 bool DownloadsAcceptDangerFunction::RunImpl() { |
| 881 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( | 1007 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( |
| 882 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); | 1008 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); |
| 883 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1009 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 884 DownloadItem* download_item = GetDownloadIfInProgress( | 1010 DownloadItem* download_item = GetDownloadIfInProgress( |
| 885 profile(), include_incognito(), params->download_id); | 1011 profile(), include_incognito(), params->download_id); |
| 886 content::WebContents* web_contents = | 1012 content::WebContents* web_contents = |
| 887 dispatcher()->delegate()->GetAssociatedWebContents(); | 1013 dispatcher()->delegate()->GetAssociatedWebContents(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 911 if (accept) { | 1037 if (accept) { |
| 912 DownloadItem* download_item = GetDownloadIfInProgress( | 1038 DownloadItem* download_item = GetDownloadIfInProgress( |
| 913 profile(), include_incognito(), download_id); | 1039 profile(), include_incognito(), download_id); |
| 914 if (download_item) | 1040 if (download_item) |
| 915 download_item->DangerousDownloadValidated(); | 1041 download_item->DangerousDownloadValidated(); |
| 916 } | 1042 } |
| 917 SendResponse(error_.empty()); | 1043 SendResponse(error_.empty()); |
| 918 } | 1044 } |
| 919 | 1045 |
| 920 DownloadsShowFunction::DownloadsShowFunction() {} | 1046 DownloadsShowFunction::DownloadsShowFunction() {} |
| 1047 | |
| 921 DownloadsShowFunction::~DownloadsShowFunction() {} | 1048 DownloadsShowFunction::~DownloadsShowFunction() {} |
| 922 | 1049 |
| 923 bool DownloadsShowFunction::RunImpl() { | 1050 bool DownloadsShowFunction::RunImpl() { |
| 924 scoped_ptr<extensions::api::downloads::Show::Params> params( | 1051 scoped_ptr<extensions::api::downloads::Show::Params> params( |
| 925 extensions::api::downloads::Show::Params::Create(*args_)); | 1052 extensions::api::downloads::Show::Params::Create(*args_)); |
| 926 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1053 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 927 DownloadItem* download_item = GetDownload( | 1054 DownloadItem* download_item = GetDownload( |
| 928 profile(), include_incognito(), params->download_id); | 1055 profile(), include_incognito(), params->download_id); |
| 929 if (!download_item) { | 1056 if (!download_item) { |
| 930 error_ = download_extension_errors::kInvalidOperationError; | 1057 error_ = download_extension_errors::kInvalidOperationError; |
| 931 return false; | 1058 return false; |
| 932 } | 1059 } |
| 933 download_item->ShowDownloadInShell(); | 1060 download_item->ShowDownloadInShell(); |
| 934 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); | 1061 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); |
| 935 return true; | 1062 return true; |
| 936 } | 1063 } |
| 937 | 1064 |
| 938 DownloadsOpenFunction::DownloadsOpenFunction() {} | 1065 DownloadsOpenFunction::DownloadsOpenFunction() {} |
| 1066 | |
| 939 DownloadsOpenFunction::~DownloadsOpenFunction() {} | 1067 DownloadsOpenFunction::~DownloadsOpenFunction() {} |
| 940 | 1068 |
| 941 bool DownloadsOpenFunction::RunImpl() { | 1069 bool DownloadsOpenFunction::RunImpl() { |
| 942 scoped_ptr<extensions::api::downloads::Open::Params> params( | 1070 scoped_ptr<extensions::api::downloads::Open::Params> params( |
| 943 extensions::api::downloads::Open::Params::Create(*args_)); | 1071 extensions::api::downloads::Open::Params::Create(*args_)); |
| 944 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1072 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 945 DownloadItem* download_item = GetDownload( | 1073 DownloadItem* download_item = GetDownload( |
| 946 profile(), include_incognito(), params->download_id); | 1074 profile(), include_incognito(), params->download_id); |
| 947 if (!download_item || !download_item->IsComplete()) { | 1075 if (!download_item || !download_item->IsComplete()) { |
| 948 error_ = download_extension_errors::kInvalidOperationError; | 1076 error_ = download_extension_errors::kInvalidOperationError; |
| 949 return false; | 1077 return false; |
| 950 } | 1078 } |
| 951 download_item->OpenDownload(); | 1079 download_item->OpenDownload(); |
| 952 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); | 1080 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); |
| 953 return true; | 1081 return true; |
| 954 } | 1082 } |
| 955 | 1083 |
| 956 DownloadsDragFunction::DownloadsDragFunction() {} | 1084 DownloadsDragFunction::DownloadsDragFunction() {} |
| 1085 | |
| 957 DownloadsDragFunction::~DownloadsDragFunction() {} | 1086 DownloadsDragFunction::~DownloadsDragFunction() {} |
| 958 | 1087 |
| 959 bool DownloadsDragFunction::RunImpl() { | 1088 bool DownloadsDragFunction::RunImpl() { |
| 960 scoped_ptr<extensions::api::downloads::Drag::Params> params( | 1089 scoped_ptr<extensions::api::downloads::Drag::Params> params( |
| 961 extensions::api::downloads::Drag::Params::Create(*args_)); | 1090 extensions::api::downloads::Drag::Params::Create(*args_)); |
| 962 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1091 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 963 DownloadItem* download_item = GetDownload( | 1092 DownloadItem* download_item = GetDownload( |
| 964 profile(), include_incognito(), params->download_id); | 1093 profile(), include_incognito(), params->download_id); |
| 965 content::WebContents* web_contents = | 1094 content::WebContents* web_contents = |
| 966 dispatcher()->delegate()->GetAssociatedWebContents(); | 1095 dispatcher()->delegate()->GetAssociatedWebContents(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1001 int icon_size = kDefaultIconSize; | 1130 int icon_size = kDefaultIconSize; |
| 1002 if (options && options->size.get()) | 1131 if (options && options->size.get()) |
| 1003 icon_size = *options->size.get(); | 1132 icon_size = *options->size.get(); |
| 1004 DownloadItem* download_item = GetDownload( | 1133 DownloadItem* download_item = GetDownload( |
| 1005 profile(), include_incognito(), params->download_id); | 1134 profile(), include_incognito(), params->download_id); |
| 1006 if (!download_item || download_item->GetTargetFilePath().empty()) { | 1135 if (!download_item || download_item->GetTargetFilePath().empty()) { |
| 1007 error_ = download_extension_errors::kInvalidOperationError; | 1136 error_ = download_extension_errors::kInvalidOperationError; |
| 1008 return false; | 1137 return false; |
| 1009 } | 1138 } |
| 1010 // In-progress downloads return the intermediate filename for GetFullPath() | 1139 // In-progress downloads return the intermediate filename for GetFullPath() |
| 1011 // which doesn't have the final extension. Therefore we won't be able to | 1140 // which doesn't have the final extension. Therefore a good file icon can't be |
| 1012 // derive a good file icon for it. So we use GetTargetFilePath() instead. | 1141 // found, so use GetTargetFilePath() instead. |
| 1013 DCHECK(icon_extractor_.get()); | 1142 DCHECK(icon_extractor_.get()); |
| 1014 DCHECK(icon_size == 16 || icon_size == 32); | 1143 DCHECK(icon_size == 16 || icon_size == 32); |
| 1015 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( | 1144 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( |
| 1016 download_item->GetTargetFilePath(), | 1145 download_item->GetTargetFilePath(), |
| 1017 IconLoaderSizeFromPixelSize(icon_size), | 1146 IconLoaderSizeFromPixelSize(icon_size), |
| 1018 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); | 1147 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); |
| 1019 return true; | 1148 return true; |
| 1020 } | 1149 } |
| 1021 | 1150 |
| 1022 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { | 1151 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { |
| 1023 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1024 if (url.empty()) { | 1153 if (url.empty()) { |
| 1025 error_ = download_extension_errors::kIconNotFoundError; | 1154 error_ = download_extension_errors::kIconNotFoundError; |
| 1026 } else { | 1155 } else { |
| 1027 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); | 1156 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); |
| 1028 SetResult(base::Value::CreateStringValue(url)); | 1157 SetResult(base::Value::CreateStringValue(url)); |
| 1029 } | 1158 } |
| 1030 SendResponse(error_.empty()); | 1159 SendResponse(error_.empty()); |
| 1031 } | 1160 } |
| 1032 | 1161 |
| 1162 ExtensionDownloadsEventRouter::DeterminerId::DeterminerId( | |
| 1163 const std::string& ext_id, | |
| 1164 int sub_id, | |
| 1165 bool incognito, | |
| 1166 const base::Time& install) | |
| 1167 : extension_id(ext_id), | |
| 1168 sub_event_id(sub_id), | |
| 1169 include_incognito(incognito), | |
| 1170 installed(install) { | |
| 1171 } | |
| 1172 | |
| 1173 ExtensionDownloadsEventRouter::DeterminerId::~DeterminerId() {} | |
| 1174 | |
| 1033 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( | 1175 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( |
| 1034 Profile* profile, | 1176 Profile* profile, |
| 1035 DownloadManager* manager) | 1177 DownloadManager* manager) |
| 1036 : profile_(profile), | 1178 : profile_(profile), |
| 1037 ALLOW_THIS_IN_INITIALIZER_LIST(notifier_(manager, this)) { | 1179 ALLOW_THIS_IN_INITIALIZER_LIST(notifier_(manager, this)) { |
| 1038 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1039 DCHECK(profile_); | 1181 DCHECK(profile_); |
| 1182 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | |
| 1183 content::Source<Profile>(profile_)); | |
| 1040 } | 1184 } |
| 1041 | 1185 |
| 1042 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { | 1186 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { |
| 1043 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1044 } | 1188 } |
| 1045 | 1189 |
| 1190 // The method by which extensions hook into the filename determination process | |
| 1191 // is based on the method by which the webRequest API allows extensions to hook | |
| 1192 // into the resource loading process. Extensions that wish to play a part in | |
| 1193 // the filename determination process call | |
| 1194 // chrome.downloads.onDeterminingFilename.addListener, which secretly (see | |
| 1195 // chrome/renderer/resources/extensions/downloads_custom_bindings.js) calls | |
| 1196 // DownloadsInternalAddFilenameDeterminerFunction (see ../downloads_internal/), | |
| 1197 // which adds the extension's ID to the profile's ExtensionDownloadsEventRouter | |
| 1198 // (EDER). | |
| 1199 // | |
| 1200 // When a download's filename is being determined, | |
| 1201 // ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone (CVRBD) passes | |
| 1202 // 2 callbacks to EDER::OnDeterminingFilename (ODFD), which stores the | |
| 1203 // callbacks in the item's ExtensionDownloadsEventRouterData (EDERD) along with | |
| 1204 // all of the extension IDs that are listening for onDeterminingFilename events. | |
| 1205 // ODFD dispatches chrome.downloads.onDeterminingFilename. | |
| 1206 // | |
| 1207 // When the extension's event handler returns, downloads_custom_bindings.js | |
| 1208 // calls DownloadsInternalDetermineFilenameFunction::RunImpl, which notifies the | |
| 1209 // item's EDERD. | |
| 1210 // | |
| 1211 // When the last extension's event handler returns, EDERD calls one of the two | |
| 1212 // callbacks that CVRBD passed to ODFD, allowing CDMD to complete the filename | |
| 1213 // determination process. If multiple extensions wish to override the filename, | |
| 1214 // then the extension that was last installed wins; if multiple determiners | |
| 1215 // within an extension compete, then the determiner that was last added wins. | |
| 1216 | |
| 1217 bool ExtensionDownloadsEventRouter::AddFilenameDeterminer( | |
| 1218 Profile* profile, | |
| 1219 bool include_incognito, | |
| 1220 const std::string& ext_id, | |
| 1221 int sub_event_id) { | |
| 1222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1223 // Only incognito/regular renderer processes receive onDeterminingFilename | |
| 1224 // events for incognito/regular downloads. Do not automatically add this | |
| 1225 // determiner to the other (incognito/regular) EDER; if the extension wants to | |
| 1226 // listen for onDeterminingFilename in those extension renderer processes, | |
| 1227 // then it will call addListener there, and |profile| will be | |
| 1228 // incognito/regular for those addListener calls, so they will use the | |
| 1229 // incognito/regular EDER. | |
| 1230 ExtensionDownloadsEventRouter* router = | |
| 1231 DownloadServiceFactory::GetForProfile(profile)->GetExtensionEventRouter(); | |
| 1232 if (!router) | |
| 1233 return false; | |
| 1234 for (DeterminerVector::const_iterator iter = router->determiners_.begin(); | |
| 1235 iter != router->determiners_.end(); ++iter) { | |
| 1236 if (iter->extension_id == ext_id) { | |
| 1237 DCHECK_NE(iter->sub_event_id, sub_event_id); | |
| 1238 } | |
| 1239 if ((iter->extension_id == ext_id) && | |
| 1240 (iter->sub_event_id == sub_event_id)) | |
| 1241 return false; | |
| 1242 } | |
| 1243 base::Time installed = extensions::ExtensionSystem::Get( | |
| 1244 profile)->extension_service()->extension_prefs()->GetInstallTime(ext_id); | |
| 1245 router->determiners_.push_back(DeterminerId( | |
| 1246 ext_id, sub_event_id, include_incognito, installed)); | |
| 1247 return true; | |
| 1248 } | |
| 1249 | |
| 1250 bool ExtensionDownloadsEventRouter::RemoveFilenameDeterminer( | |
| 1251 Profile* profile, | |
| 1252 const std::string& ext_id, | |
| 1253 int sub_event_id) { | |
| 1254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1255 ExtensionDownloadsEventRouter* router = | |
| 1256 DownloadServiceFactory::GetForProfile(profile)->GetExtensionEventRouter(); | |
| 1257 for (DeterminerVector::iterator iter = router->determiners_.begin(); | |
| 1258 iter != router->determiners_.end(); ++iter) { | |
| 1259 if (iter->extension_id == ext_id && iter->sub_event_id == sub_event_id) { | |
| 1260 router->determiners_.erase(iter); | |
| 1261 // Notify any items that may be waiting for callbacks from this | |
| 1262 // determiner. | |
| 1263 DownloadManager* manager = router->notifier_.GetManager(); | |
| 1264 if (manager) { | |
| 1265 DownloadManager::DownloadVector items; | |
| 1266 manager->GetAllDownloads(&items); | |
| 1267 for (DownloadManager::DownloadVector::const_iterator iter = | |
| 1268 items.begin(); | |
| 1269 iter != items.end(); ++iter) { | |
| 1270 ExtensionDownloadsEventRouterData* data = | |
| 1271 ExtensionDownloadsEventRouterData::Get(*iter); | |
| 1272 if (data) | |
| 1273 data->DeterminerRemoved(ext_id, sub_event_id); | |
| 1274 } | |
| 1275 } | |
| 1276 return true; | |
| 1277 } | |
| 1278 } | |
| 1279 DCHECK(false) << ext_id << " " << sub_event_id; | |
| 1280 return false; | |
| 1281 } | |
| 1282 | |
| 1283 void ExtensionDownloadsEventRouter::OnDeterminingFilename( | |
| 1284 DownloadItem* item, | |
| 1285 const base::FilePath& suggested_path, | |
| 1286 const base::Closure& no_change, | |
| 1287 const FilenameChangedCallback& change) { | |
| 1288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1289 bool any_determiners = false; | |
| 1290 | |
| 1291 ExtensionDownloadsEventRouterData* data = | |
| 1292 ExtensionDownloadsEventRouterData::Get(item); | |
| 1293 data->ClearPendingDeterminers(); | |
|
asanka
2013/02/22 18:55:48
Is it possible for there to be a pending determine
benjhayden
2013/02/22 20:43:23
Yep, Randy suggested clearing pending determiners
| |
| 1294 data->set_filename_change_callbacks(no_change, change); | |
| 1295 std::set<int> sub_events; | |
| 1296 for (DeterminerVector::const_iterator iter = determiners_.begin(); | |
| 1297 iter != determiners_.end(); ++iter) { | |
| 1298 data->AddPendingDeterminer(iter->extension_id, | |
| 1299 iter->sub_event_id, | |
| 1300 iter->installed); | |
| 1301 sub_events.insert(iter->sub_event_id); | |
| 1302 any_determiners = true; | |
| 1303 } | |
| 1304 | |
| 1305 if (profile_->IsOffTheRecord()) { | |
| 1306 // If this DownloadItem is incognito and there are any | |
| 1307 // incognito-spanning-mode extensions registered in the on-record EDER, then | |
| 1308 // dispatch to them and wait for them as well. | |
| 1309 ExtensionDownloadsEventRouter* router = | |
| 1310 DownloadServiceFactory::GetForProfile( | |
| 1311 profile_->GetOriginalProfile())->GetExtensionEventRouter(); | |
| 1312 for (DeterminerVector::const_iterator iter = router->determiners_.begin(); | |
| 1313 iter != router->determiners_.end(); ++iter) { | |
| 1314 if (iter->include_incognito) { | |
| 1315 data->AddPendingDeterminer(iter->extension_id, | |
| 1316 iter->sub_event_id, | |
| 1317 iter->installed); | |
| 1318 sub_events.insert(iter->sub_event_id); | |
| 1319 any_determiners = true; | |
| 1320 } | |
| 1321 } | |
| 1322 } | |
| 1323 | |
| 1324 std::string event_name( | |
| 1325 extensions::event_names::kOnDownloadDeterminingFilename); | |
| 1326 event_name += "/"; | |
| 1327 for (std::set<int>::const_iterator iter = sub_events.begin(); | |
| 1328 iter != sub_events.end(); ++iter) { | |
| 1329 base::DictionaryValue* json = DownloadItemToJSON( | |
| 1330 item, profile_->IsOffTheRecord()).release(); | |
| 1331 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); | |
| 1332 // If there's a listener in an incognito extension renderer, then it will | |
| 1333 // have registered its own determiner in the incognito EDER, which will be | |
| 1334 // called for incognito downloads. | |
| 1335 DispatchEvent((event_name + base::IntToString(*iter)).c_str(), false, json); | |
| 1336 } | |
| 1337 | |
| 1338 if (!any_determiners) { | |
| 1339 no_change.Run(); | |
| 1340 return; | |
| 1341 } | |
| 1342 } | |
| 1343 | |
| 1344 bool ExtensionDownloadsEventRouter::DetermineFilename( | |
| 1345 Profile* profile, | |
| 1346 bool include_incognito, | |
| 1347 const std::string& ext_id, | |
| 1348 int sub_event_id, | |
| 1349 int download_id, | |
| 1350 const base::FilePath& filename, | |
| 1351 bool overwrite) { | |
| 1352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1353 DownloadItem* item = GetDownloadIfInProgress( | |
| 1354 profile, include_incognito, download_id); | |
| 1355 if (!item) | |
| 1356 return false; | |
| 1357 ExtensionDownloadsEventRouterData* data = | |
| 1358 ExtensionDownloadsEventRouterData::Get(item); | |
| 1359 if (!data) | |
| 1360 return false; | |
| 1361 return data->DeterminerCallback(ext_id, sub_event_id, filename, overwrite); | |
| 1362 } | |
| 1363 | |
| 1364 void ExtensionDownloadsEventRouter::Observe( | |
| 1365 int type, | |
| 1366 const content::NotificationSource& source, | |
| 1367 const content::NotificationDetails& details) { | |
| 1368 switch (type) { | |
| 1369 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | |
| 1370 const extensions::Extension* extension = content::Details< | |
| 1371 extensions::UnloadedExtensionInfo>(details)->extension; | |
| 1372 // Remove this extension from |determiners_|. | |
| 1373 for (DeterminerVector::iterator iter = determiners_.begin(); | |
| 1374 iter != determiners_.end();) { | |
| 1375 if (iter->extension_id == extension->id()) { | |
| 1376 iter = determiners_.erase(iter); | |
| 1377 } else { | |
| 1378 ++iter; | |
| 1379 } | |
| 1380 } | |
| 1381 // Notify any items that may be waiting for callbacks from this extension. | |
| 1382 DownloadManager* manager = notifier_.GetManager(); | |
| 1383 if (manager) { | |
| 1384 DownloadManager::DownloadVector items; | |
| 1385 manager->GetAllDownloads(&items); | |
| 1386 for (DownloadManager::DownloadVector::const_iterator iter = | |
| 1387 items.begin(); | |
| 1388 iter != items.end(); ++iter) { | |
| 1389 ExtensionDownloadsEventRouterData* data = | |
| 1390 ExtensionDownloadsEventRouterData::Get(*iter); | |
| 1391 if (data) | |
| 1392 data->ExtensionUnloaded(extension->id()); | |
| 1393 } | |
| 1394 } | |
| 1395 break; | |
| 1396 } | |
| 1397 default: | |
| 1398 NOTREACHED(); | |
| 1399 break; | |
| 1400 } | |
| 1401 } | |
| 1402 | |
| 1403 // That's all the methods that have to do with filename determination. The rest | |
| 1404 // have to do with the other, less special events. | |
| 1405 | |
| 1046 void ExtensionDownloadsEventRouter::OnDownloadCreated( | 1406 void ExtensionDownloadsEventRouter::OnDownloadCreated( |
| 1047 DownloadManager* manager, DownloadItem* download_item) { | 1407 DownloadManager* manager, DownloadItem* download_item) { |
| 1048 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1049 if (download_item->IsTemporary()) | 1409 if (download_item->IsTemporary()) |
| 1050 return; | 1410 return; |
| 1051 | 1411 |
| 1052 scoped_ptr<base::DictionaryValue> json_item( | 1412 scoped_ptr<base::DictionaryValue> json_item( |
| 1053 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); | 1413 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); |
| 1054 DispatchEvent(extensions::event_names::kOnDownloadCreated, | 1414 DispatchEvent(extensions::event_names::kOnDownloadCreated, |
| 1415 true, | |
| 1055 json_item->DeepCopy()); | 1416 json_item->DeepCopy()); |
| 1056 if (!ExtensionDownloadsEventRouterData::Get(download_item)) | 1417 if (!ExtensionDownloadsEventRouterData::Get(download_item)) |
| 1057 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); | 1418 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); |
| 1058 } | 1419 } |
| 1059 | 1420 |
| 1060 void ExtensionDownloadsEventRouter::OnDownloadUpdated( | 1421 void ExtensionDownloadsEventRouter::OnDownloadUpdated( |
| 1061 DownloadManager* manager, DownloadItem* download_item) { | 1422 DownloadManager* manager, DownloadItem* download_item) { |
| 1062 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1063 if (download_item->IsTemporary()) | 1424 if (download_item->IsTemporary()) |
| 1064 return; | 1425 return; |
| 1065 | 1426 |
| 1066 ExtensionDownloadsEventRouterData* data = | 1427 ExtensionDownloadsEventRouterData* data = |
| 1067 ExtensionDownloadsEventRouterData::Get(download_item); | 1428 ExtensionDownloadsEventRouterData::Get(download_item); |
| 1068 if (!data) { | 1429 if (!data) { |
| 1069 // The download_item probably transitioned from temporary to not temporary. | 1430 // The download_item probably transitioned from temporary to not temporary. |
| 1070 OnDownloadCreated(manager, download_item); | 1431 OnDownloadCreated(manager, download_item); |
| 1071 return; | 1432 return; |
| 1072 } | 1433 } |
| 1073 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( | 1434 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( |
| 1074 download_item, profile_->IsOffTheRecord())); | 1435 download_item, profile_->IsOffTheRecord())); |
| 1075 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); | 1436 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); |
| 1076 delta->SetInteger(kIdKey, download_item->GetId()); | 1437 delta->SetInteger(kIdKey, download_item->GetId()); |
| 1077 std::set<std::string> new_fields; | 1438 std::set<std::string> new_fields; |
| 1078 bool changed = false; | 1439 bool changed = false; |
| 1079 | 1440 |
| 1080 // For each field in the new json representation of the download_item except | 1441 // For each field in the new json representation of the download_item except |
| 1081 // the bytesReceived field, if the field has changed from the previous old | 1442 // the bytesReceived field, if the field has changed from the previous old |
| 1082 // json, set the differences in the |delta| object and remember that something | 1443 // json, set the differences in the |delta| object and remember that something |
| 1083 // significant changed. | 1444 // significant changed. |
| 1084 for (base::DictionaryValue::Iterator iter(*new_json.get()); | 1445 for (base::DictionaryValue::Iterator iter(*new_json.get()); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1104 if (new_fields.find(iter.key()) == new_fields.end()) { | 1465 if (new_fields.find(iter.key()) == new_fields.end()) { |
| 1105 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); | 1466 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); |
| 1106 changed = true; | 1467 changed = true; |
| 1107 } | 1468 } |
| 1108 } | 1469 } |
| 1109 | 1470 |
| 1110 // Update the OnChangedStat and dispatch the event if something significant | 1471 // Update the OnChangedStat and dispatch the event if something significant |
| 1111 // changed. Replace the stored json with the new json. | 1472 // changed. Replace the stored json with the new json. |
| 1112 data->OnItemUpdated(); | 1473 data->OnItemUpdated(); |
| 1113 if (changed) { | 1474 if (changed) { |
| 1114 DispatchEvent(extensions::event_names::kOnDownloadChanged, delta.release()); | 1475 DispatchEvent(extensions::event_names::kOnDownloadChanged, |
| 1476 true, | |
| 1477 delta.release()); | |
| 1115 data->OnChangedFired(); | 1478 data->OnChangedFired(); |
| 1116 } | 1479 } |
| 1117 data->set_json(new_json.Pass()); | 1480 data->set_json(new_json.Pass()); |
| 1118 } | 1481 } |
| 1119 | 1482 |
| 1120 void ExtensionDownloadsEventRouter::OnDownloadRemoved( | 1483 void ExtensionDownloadsEventRouter::OnDownloadRemoved( |
| 1121 DownloadManager* manager, DownloadItem* download_item) { | 1484 DownloadManager* manager, DownloadItem* download_item) { |
| 1122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1123 if (download_item->IsTemporary()) | 1486 if (download_item->IsTemporary()) |
| 1124 return; | 1487 return; |
| 1125 DispatchEvent(extensions::event_names::kOnDownloadErased, | 1488 DispatchEvent(extensions::event_names::kOnDownloadErased, |
| 1489 true, | |
| 1126 base::Value::CreateIntegerValue(download_item->GetId())); | 1490 base::Value::CreateIntegerValue(download_item->GetId())); |
| 1127 } | 1491 } |
| 1128 | 1492 |
| 1129 void ExtensionDownloadsEventRouter::DispatchEvent( | 1493 void ExtensionDownloadsEventRouter::DispatchEvent( |
| 1130 const char* event_name, base::Value* arg) { | 1494 const char* event_name, bool include_incognito, base::Value* arg) { |
| 1131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1495 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1496 if (!extensions::ExtensionSystem::Get(profile_)->event_router()) | |
| 1497 return; | |
| 1132 scoped_ptr<base::ListValue> args(new base::ListValue()); | 1498 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 1133 args->Append(arg); | 1499 args->Append(arg); |
| 1134 std::string json_args; | 1500 std::string json_args; |
| 1135 base::JSONWriter::Write(args.get(), &json_args); | 1501 base::JSONWriter::Write(args.get(), &json_args); |
| 1136 // There is a one EDER for each on-record Profile, and a separate EDER for | 1502 scoped_ptr<extensions::Event> event(new extensions::Event( |
| 1137 // each off-record Profile, so there is exactly one EDER for each | 1503 event_name, args.Pass())); |
| 1138 // DownloadManager. EDER only watches its own DM, so all the items that an | 1504 // "restrict_to_profile" is not smart enough to avoid sharing off-record |
| 1139 // EDER sees are either all on-record or all off-record. However, we want | 1505 // events with on-record extension renderers. |
|
Matt Perry
2013/02/22 01:43:43
This comment is a bit cryptic to me.
The main qui
benjhayden
2013/02/22 20:43:23
Done.
| |
| 1140 // extensions in off-record contexts to see on-record items. So, if this EDER | 1506 event->restrict_to_profile = |
| 1141 // is watching an on-record DM, and there is a corresponding off-record | 1507 (include_incognito && !profile_->IsOffTheRecord()) ? NULL : profile_; |
| 1142 // Profile, then dispatch this event to both the on-record Profile and the | 1508 extensions::ExtensionSystem::Get(profile_)->event_router()-> |
| 1143 // off-record Profile. There may or may not be an off-record Profile, so send | 1509 BroadcastEvent(event.Pass()); |
| 1144 // a *copy* of |args| to the off-record Profile, and Pass() |args| | 1510 ExtensionDownloadsEventRouter::DownloadsNotificationSource |
|
Matt Perry
2013/02/22 01:43:43
nit: you're already in this scope so you can drop
benjhayden
2013/02/22 20:43:23
Done.
| |
| 1145 // to the Profile that we know is there. | 1511 notification_source; |
| 1146 if (profile_->HasOffTheRecordProfile() && | 1512 notification_source.event_name = event_name; |
| 1147 !profile_->IsOffTheRecord()) { | 1513 notification_source.profile = profile_; |
| 1148 DispatchEventInternal( | 1514 content::Source<ExtensionDownloadsEventRouter::DownloadsNotificationSource> |
|
Matt Perry
2013/02/22 01:43:43
same here
benjhayden
2013/02/22 20:43:23
Done.
| |
| 1149 profile_->GetOffTheRecordProfile(), | 1515 content_source(¬ification_source); |
| 1150 event_name, | 1516 content::NotificationService::current()->Notify( |
| 1151 json_args, | 1517 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
| 1152 scoped_ptr<base::ListValue>(args->DeepCopy())); | 1518 content_source, |
| 1153 } | 1519 content::Details<std::string>(&json_args)); |
| 1154 DispatchEventInternal(profile_, event_name, json_args, args.Pass()); | |
| 1155 } | 1520 } |
| OLD | NEW |