| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | |
| 10 #include <set> | 9 #include <set> |
| 11 #include <string> | 10 #include <string> |
| 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
| 15 #include "base/callback.h" | 15 #include "base/callback.h" |
| 16 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
| 17 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
| 18 #include "base/json/json_writer.h" | 18 #include "base/json/json_writer.h" |
| 19 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
| 20 #include "base/location.h" | 20 #include "base/location.h" |
| 21 #include "base/logging.h" | 21 #include "base/logging.h" |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 return; | 533 return; |
| 534 } | 534 } |
| 535 query_out.AddFilter(danger_type); | 535 query_out.AddFilter(danger_type); |
| 536 } | 536 } |
| 537 if (query_in.order_by.get()) { | 537 if (query_in.order_by.get()) { |
| 538 CompileDownloadQueryOrderBy(*query_in.order_by.get(), error, &query_out); | 538 CompileDownloadQueryOrderBy(*query_in.order_by.get(), error, &query_out); |
| 539 if (!error->empty()) | 539 if (!error->empty()) |
| 540 return; | 540 return; |
| 541 } | 541 } |
| 542 | 542 |
| 543 scoped_ptr<base::DictionaryValue> query_in_value(query_in.ToValue().Pass()); | 543 scoped_ptr<base::DictionaryValue> query_in_value(query_in.ToValue()); |
| 544 for (base::DictionaryValue::Iterator query_json_field(*query_in_value.get()); | 544 for (base::DictionaryValue::Iterator query_json_field(*query_in_value.get()); |
| 545 !query_json_field.IsAtEnd(); query_json_field.Advance()) { | 545 !query_json_field.IsAtEnd(); query_json_field.Advance()) { |
| 546 FilterTypeMap::const_iterator filter_type = | 546 FilterTypeMap::const_iterator filter_type = |
| 547 filter_types.Get().find(query_json_field.key()); | 547 filter_types.Get().find(query_json_field.key()); |
| 548 if (filter_type != filter_types.Get().end()) { | 548 if (filter_type != filter_types.Get().end()) { |
| 549 if (!query_out.AddFilter(filter_type->second, query_json_field.value())) { | 549 if (!query_out.AddFilter(filter_type->second, query_json_field.value())) { |
| 550 *error = errors::kInvalidFilter; | 550 *error = errors::kInvalidFilter; |
| 551 return; | 551 return; |
| 552 } | 552 } |
| 553 } | 553 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 | 594 |
| 595 static void Remove(DownloadItem* download_item) { | 595 static void Remove(DownloadItem* download_item) { |
| 596 download_item->RemoveUserData(kKey); | 596 download_item->RemoveUserData(kKey); |
| 597 } | 597 } |
| 598 | 598 |
| 599 explicit ExtensionDownloadsEventRouterData( | 599 explicit ExtensionDownloadsEventRouterData( |
| 600 DownloadItem* download_item, | 600 DownloadItem* download_item, |
| 601 scoped_ptr<base::DictionaryValue> json_item) | 601 scoped_ptr<base::DictionaryValue> json_item) |
| 602 : updated_(0), | 602 : updated_(0), |
| 603 changed_fired_(0), | 603 changed_fired_(0), |
| 604 json_(json_item.Pass()), | 604 json_(std::move(json_item)), |
| 605 creator_conflict_action_( | 605 creator_conflict_action_(downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY), |
| 606 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY), | |
| 607 determined_conflict_action_( | 606 determined_conflict_action_( |
| 608 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { | 607 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { |
| 609 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 608 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 610 download_item->SetUserData(kKey, this); | 609 download_item->SetUserData(kKey, this); |
| 611 } | 610 } |
| 612 | 611 |
| 613 ~ExtensionDownloadsEventRouterData() override { | 612 ~ExtensionDownloadsEventRouterData() override { |
| 614 if (updated_ > 0) { | 613 if (updated_ > 0) { |
| 615 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", | 614 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", |
| 616 (changed_fired_ * 100 / updated_)); | 615 (changed_fired_ * 100 / updated_)); |
| 617 } | 616 } |
| 618 } | 617 } |
| 619 | 618 |
| 620 const base::DictionaryValue& json() const { return *json_.get(); } | 619 const base::DictionaryValue& json() const { return *json_.get(); } |
| 621 void set_json(scoped_ptr<base::DictionaryValue> json_item) { | 620 void set_json(scoped_ptr<base::DictionaryValue> json_item) { |
| 622 json_ = json_item.Pass(); | 621 json_ = std::move(json_item); |
| 623 } | 622 } |
| 624 | 623 |
| 625 void OnItemUpdated() { ++updated_; } | 624 void OnItemUpdated() { ++updated_; } |
| 626 void OnChangedFired() { ++changed_fired_; } | 625 void OnChangedFired() { ++changed_fired_; } |
| 627 | 626 |
| 628 static void SetDetermineFilenameTimeoutSecondsForTesting(int s) { | 627 static void SetDetermineFilenameTimeoutSecondsForTesting(int s) { |
| 629 determine_filename_timeout_s_ = s; | 628 determine_filename_timeout_s_ = s; |
| 630 } | 629 } |
| 631 | 630 |
| 632 void BeginFilenameDetermination( | 631 void BeginFilenameDetermination( |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 if (options.body.get()) | 1017 if (options.body.get()) |
| 1019 download_params->set_post_body(*options.body.get()); | 1018 download_params->set_post_body(*options.body.get()); |
| 1020 download_params->set_callback(base::Bind( | 1019 download_params->set_callback(base::Bind( |
| 1021 &DownloadsDownloadFunction::OnStarted, this, | 1020 &DownloadsDownloadFunction::OnStarted, this, |
| 1022 creator_suggested_filename, options.conflict_action)); | 1021 creator_suggested_filename, options.conflict_action)); |
| 1023 // Prevent login prompts for 401/407 responses. | 1022 // Prevent login prompts for 401/407 responses. |
| 1024 download_params->set_do_not_prompt_for_login(true); | 1023 download_params->set_do_not_prompt_for_login(true); |
| 1025 | 1024 |
| 1026 DownloadManager* manager = BrowserContext::GetDownloadManager( | 1025 DownloadManager* manager = BrowserContext::GetDownloadManager( |
| 1027 current_profile); | 1026 current_profile); |
| 1028 manager->DownloadUrl(download_params.Pass()); | 1027 manager->DownloadUrl(std::move(download_params)); |
| 1029 RecordDownloadSource(DOWNLOAD_INITIATED_BY_EXTENSION); | 1028 RecordDownloadSource(DOWNLOAD_INITIATED_BY_EXTENSION); |
| 1030 RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD); | 1029 RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD); |
| 1031 return true; | 1030 return true; |
| 1032 } | 1031 } |
| 1033 | 1032 |
| 1034 void DownloadsDownloadFunction::OnStarted( | 1033 void DownloadsDownloadFunction::OnStarted( |
| 1035 const base::FilePath& creator_suggested_filename, | 1034 const base::FilePath& creator_suggested_filename, |
| 1036 downloads::FilenameConflictAction creator_conflict_action, | 1035 downloads::FilenameConflictAction creator_conflict_action, |
| 1037 DownloadItem* item, | 1036 DownloadItem* item, |
| 1038 content::DownloadInterruptReason interrupt_reason) { | 1037 content::DownloadInterruptReason interrupt_reason) { |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1761 return; | 1760 return; |
| 1762 } | 1761 } |
| 1763 scoped_ptr<base::DictionaryValue> json_item( | 1762 scoped_ptr<base::DictionaryValue> json_item( |
| 1764 DownloadItemToJSON(download_item, profile_)); | 1763 DownloadItemToJSON(download_item, profile_)); |
| 1765 DispatchEvent(events::DOWNLOADS_ON_CREATED, downloads::OnCreated::kEventName, | 1764 DispatchEvent(events::DOWNLOADS_ON_CREATED, downloads::OnCreated::kEventName, |
| 1766 true, Event::WillDispatchCallback(), json_item->DeepCopy()); | 1765 true, Event::WillDispatchCallback(), json_item->DeepCopy()); |
| 1767 if (!ExtensionDownloadsEventRouterData::Get(download_item) && | 1766 if (!ExtensionDownloadsEventRouterData::Get(download_item) && |
| 1768 (router->HasEventListener(downloads::OnChanged::kEventName) || | 1767 (router->HasEventListener(downloads::OnChanged::kEventName) || |
| 1769 router->HasEventListener( | 1768 router->HasEventListener( |
| 1770 downloads::OnDeterminingFilename::kEventName))) { | 1769 downloads::OnDeterminingFilename::kEventName))) { |
| 1771 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); | 1770 new ExtensionDownloadsEventRouterData(download_item, std::move(json_item)); |
| 1772 } | 1771 } |
| 1773 } | 1772 } |
| 1774 | 1773 |
| 1775 void ExtensionDownloadsEventRouter::OnDownloadUpdated( | 1774 void ExtensionDownloadsEventRouter::OnDownloadUpdated( |
| 1776 DownloadManager* manager, DownloadItem* download_item) { | 1775 DownloadManager* manager, DownloadItem* download_item) { |
| 1777 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1776 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1778 EventRouter* router = EventRouter::Get(profile_); | 1777 EventRouter* router = EventRouter::Get(profile_); |
| 1779 ExtensionDownloadsEventRouterData* data = | 1778 ExtensionDownloadsEventRouterData* data = |
| 1780 ExtensionDownloadsEventRouterData::Get(download_item); | 1779 ExtensionDownloadsEventRouterData::Get(download_item); |
| 1781 if (download_item->IsTemporary() || | 1780 if (download_item->IsTemporary() || |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1830 | 1829 |
| 1831 // Update the OnChangedStat and dispatch the event if something significant | 1830 // Update the OnChangedStat and dispatch the event if something significant |
| 1832 // changed. Replace the stored json with the new json. | 1831 // changed. Replace the stored json with the new json. |
| 1833 data->OnItemUpdated(); | 1832 data->OnItemUpdated(); |
| 1834 if (changed) { | 1833 if (changed) { |
| 1835 DispatchEvent(events::DOWNLOADS_ON_CHANGED, | 1834 DispatchEvent(events::DOWNLOADS_ON_CHANGED, |
| 1836 downloads::OnChanged::kEventName, true, | 1835 downloads::OnChanged::kEventName, true, |
| 1837 Event::WillDispatchCallback(), delta.release()); | 1836 Event::WillDispatchCallback(), delta.release()); |
| 1838 data->OnChangedFired(); | 1837 data->OnChangedFired(); |
| 1839 } | 1838 } |
| 1840 data->set_json(new_json.Pass()); | 1839 data->set_json(std::move(new_json)); |
| 1841 } | 1840 } |
| 1842 | 1841 |
| 1843 void ExtensionDownloadsEventRouter::OnDownloadRemoved( | 1842 void ExtensionDownloadsEventRouter::OnDownloadRemoved( |
| 1844 DownloadManager* manager, DownloadItem* download_item) { | 1843 DownloadManager* manager, DownloadItem* download_item) { |
| 1845 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1844 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1846 if (download_item->IsTemporary()) | 1845 if (download_item->IsTemporary()) |
| 1847 return; | 1846 return; |
| 1848 DispatchEvent( | 1847 DispatchEvent( |
| 1849 events::DOWNLOADS_ON_ERASED, downloads::OnErased::kEventName, true, | 1848 events::DOWNLOADS_ON_ERASED, downloads::OnErased::kEventName, true, |
| 1850 Event::WillDispatchCallback(), | 1849 Event::WillDispatchCallback(), |
| 1851 new base::FundamentalValue(static_cast<int>(download_item->GetId()))); | 1850 new base::FundamentalValue(static_cast<int>(download_item->GetId()))); |
| 1852 } | 1851 } |
| 1853 | 1852 |
| 1854 void ExtensionDownloadsEventRouter::DispatchEvent( | 1853 void ExtensionDownloadsEventRouter::DispatchEvent( |
| 1855 events::HistogramValue histogram_value, | 1854 events::HistogramValue histogram_value, |
| 1856 const std::string& event_name, | 1855 const std::string& event_name, |
| 1857 bool include_incognito, | 1856 bool include_incognito, |
| 1858 const Event::WillDispatchCallback& will_dispatch_callback, | 1857 const Event::WillDispatchCallback& will_dispatch_callback, |
| 1859 base::Value* arg) { | 1858 base::Value* arg) { |
| 1860 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1859 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1861 if (!EventRouter::Get(profile_)) | 1860 if (!EventRouter::Get(profile_)) |
| 1862 return; | 1861 return; |
| 1863 scoped_ptr<base::ListValue> args(new base::ListValue()); | 1862 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 1864 args->Append(arg); | 1863 args->Append(arg); |
| 1865 std::string json_args; | 1864 std::string json_args; |
| 1866 base::JSONWriter::Write(*args, &json_args); | 1865 base::JSONWriter::Write(*args, &json_args); |
| 1867 scoped_ptr<Event> event(new Event(histogram_value, event_name, args.Pass())); | 1866 scoped_ptr<Event> event( |
| 1867 new Event(histogram_value, event_name, std::move(args))); |
| 1868 // The downloads system wants to share on-record events with off-record | 1868 // The downloads system wants to share on-record events with off-record |
| 1869 // extension renderers even in incognito_split_mode because that's how | 1869 // extension renderers even in incognito_split_mode because that's how |
| 1870 // chrome://downloads works. The "restrict_to_profile" mechanism does not | 1870 // chrome://downloads works. The "restrict_to_profile" mechanism does not |
| 1871 // anticipate this, so it does not automatically prevent sharing off-record | 1871 // anticipate this, so it does not automatically prevent sharing off-record |
| 1872 // events with on-record extension renderers. | 1872 // events with on-record extension renderers. |
| 1873 event->restrict_to_browser_context = | 1873 event->restrict_to_browser_context = |
| 1874 (include_incognito && !profile_->IsOffTheRecord()) ? NULL : profile_; | 1874 (include_incognito && !profile_->IsOffTheRecord()) ? NULL : profile_; |
| 1875 event->will_dispatch_callback = will_dispatch_callback; | 1875 event->will_dispatch_callback = will_dispatch_callback; |
| 1876 EventRouter::Get(profile_)->BroadcastEvent(event.Pass()); | 1876 EventRouter::Get(profile_)->BroadcastEvent(std::move(event)); |
| 1877 DownloadsNotificationSource notification_source; | 1877 DownloadsNotificationSource notification_source; |
| 1878 notification_source.event_name = event_name; | 1878 notification_source.event_name = event_name; |
| 1879 notification_source.profile = profile_; | 1879 notification_source.profile = profile_; |
| 1880 content::Source<DownloadsNotificationSource> content_source( | 1880 content::Source<DownloadsNotificationSource> content_source( |
| 1881 ¬ification_source); | 1881 ¬ification_source); |
| 1882 content::NotificationService::current()->Notify( | 1882 content::NotificationService::current()->Notify( |
| 1883 extensions::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | 1883 extensions::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
| 1884 content_source, | 1884 content_source, |
| 1885 content::Details<std::string>(&json_args)); | 1885 content::Details<std::string>(&json_args)); |
| 1886 } | 1886 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1903 return; | 1903 return; |
| 1904 base::Time now(base::Time::Now()); | 1904 base::Time now(base::Time::Now()); |
| 1905 int delta = now.ToTimeT() - last_checked_removal_.ToTimeT(); | 1905 int delta = now.ToTimeT() - last_checked_removal_.ToTimeT(); |
| 1906 if (delta <= kFileExistenceRateLimitSeconds) | 1906 if (delta <= kFileExistenceRateLimitSeconds) |
| 1907 return; | 1907 return; |
| 1908 last_checked_removal_ = now; | 1908 last_checked_removal_ = now; |
| 1909 manager->CheckForHistoryFilesRemoval(); | 1909 manager->CheckForHistoryFilesRemoval(); |
| 1910 } | 1910 } |
| 1911 | 1911 |
| 1912 } // namespace extensions | 1912 } // namespace extensions |
| OLD | NEW |