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> |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 bool ValidateFilename(const string16& filename) { | 179 bool ValidateFilename(const string16& filename) { |
180 // TODO(benjhayden): More robust validation of filename. | 180 // TODO(benjhayden): More robust validation of filename. |
181 if ((filename.find('/') != string16::npos) || | 181 if ((filename.find('/') != string16::npos) || |
182 (filename.find('\\') != string16::npos)) | 182 (filename.find('\\') != string16::npos)) |
183 return false; | 183 return false; |
184 if (filename.size() >= 2u && filename[0] == L'.' && filename[1] == L'.') | 184 if (filename.size() >= 2u && filename[0] == L'.' && filename[1] == L'.') |
185 return false; | 185 return false; |
186 return true; | 186 return true; |
187 } | 187 } |
188 | 188 |
189 scoped_ptr<base::DictionaryValue> DownloadItemToJSON(DownloadItem* item) { | 189 scoped_ptr<base::DictionaryValue> DownloadItemToJSON( |
190 DownloadItem* item, | |
191 bool incognito) { | |
190 base::DictionaryValue* json = new base::DictionaryValue(); | 192 base::DictionaryValue* json = new base::DictionaryValue(); |
191 json->SetInteger(kIdKey, item->GetId()); | 193 json->SetInteger(kIdKey, item->GetId()); |
192 json->SetString(kUrlKey, item->GetOriginalUrl().spec()); | 194 json->SetString(kUrlKey, item->GetOriginalUrl().spec()); |
193 json->SetString(kFilenameKey, item->GetFullPath().LossyDisplayName()); | 195 json->SetString(kFilenameKey, item->GetFullPath().LossyDisplayName()); |
194 json->SetString(kDangerKey, DangerString(item->GetDangerType())); | 196 json->SetString(kDangerKey, DangerString(item->GetDangerType())); |
195 if (item->GetDangerType() != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) | 197 if (item->GetDangerType() != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) |
196 json->SetBoolean(kDangerAcceptedKey, | 198 json->SetBoolean(kDangerAcceptedKey, |
197 item->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED); | 199 item->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED); |
198 json->SetString(kStateKey, StateString(item->GetState())); | 200 json->SetString(kStateKey, StateString(item->GetState())); |
199 json->SetBoolean(kPausedKey, item->IsPaused()); | 201 json->SetBoolean(kPausedKey, item->IsPaused()); |
200 json->SetString(kMimeKey, item->GetMimeType()); | 202 json->SetString(kMimeKey, item->GetMimeType()); |
201 json->SetInteger(kStartTimeKey, | 203 json->SetInteger(kStartTimeKey, |
202 (item->GetStartTime() - base::Time::UnixEpoch()).InMilliseconds()); | 204 (item->GetStartTime() - base::Time::UnixEpoch()).InMilliseconds()); |
203 json->SetInteger(kBytesReceivedKey, item->GetReceivedBytes()); | 205 json->SetInteger(kBytesReceivedKey, item->GetReceivedBytes()); |
204 json->SetInteger(kTotalBytesKey, item->GetTotalBytes()); | 206 json->SetInteger(kTotalBytesKey, item->GetTotalBytes()); |
205 json->SetBoolean(kIncognito, item->IsOtr()); | 207 json->SetBoolean(kIncognito, incognito); |
206 if (item->GetState() == DownloadItem::INTERRUPTED) { | 208 if (item->GetState() == DownloadItem::INTERRUPTED) { |
207 json->SetInteger(kErrorKey, static_cast<int>(item->GetLastReason())); | 209 json->SetInteger(kErrorKey, static_cast<int>(item->GetLastReason())); |
208 } else if (item->GetState() == DownloadItem::CANCELLED) { | 210 } else if (item->GetState() == DownloadItem::CANCELLED) { |
209 json->SetInteger(kErrorKey, static_cast<int>( | 211 json->SetInteger(kErrorKey, static_cast<int>( |
210 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED)); | 212 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED)); |
211 } | 213 } |
212 // TODO(benjhayden): Implement endTime and fileSize. | 214 // TODO(benjhayden): Implement endTime and fileSize. |
213 // json->SetInteger(kEndTimeKey, -1); | 215 // json->SetInteger(kEndTimeKey, -1); |
214 json->SetInteger(kFileSizeKey, item->GetTotalBytes()); | 216 json->SetInteger(kFileSizeKey, item->GetTotalBytes()); |
215 return scoped_ptr<base::DictionaryValue>(json); | 217 return scoped_ptr<base::DictionaryValue>(json); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 sorter_types[kUrlKey] = DownloadQuery::SORT_URL; | 312 sorter_types[kUrlKey] = DownloadQuery::SORT_URL; |
311 } | 313 } |
312 | 314 |
313 bool IsNotTemporaryDownloadFilter(const DownloadItem& item) { | 315 bool IsNotTemporaryDownloadFilter(const DownloadItem& item) { |
314 return !item.IsTemporary(); | 316 return !item.IsTemporary(); |
315 } | 317 } |
316 | 318 |
317 void GetManagers( | 319 void GetManagers( |
318 Profile* profile, | 320 Profile* profile, |
319 bool include_incognito, | 321 bool include_incognito, |
320 DownloadManager** manager, DownloadManager** incognito_manager) { | 322 DownloadManager** manager, |
323 DownloadManager** incognito_manager) { | |
321 *manager = BrowserContext::GetDownloadManager(profile); | 324 *manager = BrowserContext::GetDownloadManager(profile); |
322 *incognito_manager = NULL; | 325 *incognito_manager = NULL; |
323 if (include_incognito && profile->HasOffTheRecordProfile()) { | 326 if (include_incognito && profile->HasOffTheRecordProfile()) { |
324 *incognito_manager = BrowserContext::GetDownloadManager( | 327 *incognito_manager = BrowserContext::GetDownloadManager( |
325 profile->GetOffTheRecordProfile()); | 328 profile->GetOffTheRecordProfile()); |
326 } | 329 } |
327 } | 330 } |
328 | 331 |
329 DownloadItem* GetActiveItem(Profile* profile, bool include_incognito, int id) { | 332 DownloadItem* GetActiveItem(Profile* profile, bool include_incognito, int id) { |
330 DownloadManager* manager = NULL; | 333 DownloadManager* manager = NULL; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 if (sorter_type == sorter_types.Get().end()) { | 388 if (sorter_type == sorter_types.Get().end()) { |
386 *error = download_extension_errors::kInvalidOrderByError; | 389 *error = download_extension_errors::kInvalidOrderByError; |
387 return; | 390 return; |
388 } | 391 } |
389 query->AddSorter(sorter_type->second, direction); | 392 query->AddSorter(sorter_type->second, direction); |
390 } | 393 } |
391 } | 394 } |
392 | 395 |
393 void RunDownloadQuery( | 396 void RunDownloadQuery( |
394 const extensions::api::downloads::DownloadQuery& query_in, | 397 const extensions::api::downloads::DownloadQuery& query_in, |
395 Profile* profile, | 398 DownloadManager* manager, |
396 bool include_incognito, | 399 DownloadManager* incognito_manager, |
397 std::string* error, | 400 std::string* error, |
398 DownloadQuery::DownloadVector* results) { | 401 DownloadQuery::DownloadVector* results) { |
399 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 402 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
400 // comparisons. | 403 // comparisons. |
401 static base::LazyInstance<FilterTypeMap> filter_types = | 404 static base::LazyInstance<FilterTypeMap> filter_types = |
402 LAZY_INSTANCE_INITIALIZER; | 405 LAZY_INSTANCE_INITIALIZER; |
403 if (filter_types.Get().size() == 0) | 406 if (filter_types.Get().size() == 0) |
404 InitFilterTypeMap(filter_types.Get()); | 407 InitFilterTypeMap(filter_types.Get()); |
405 | 408 |
406 DownloadQuery query_out; | 409 DownloadQuery query_out; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 FilterTypeMap::const_iterator filter_type = | 445 FilterTypeMap::const_iterator filter_type = |
443 filter_types.Get().find(query_json_field.key()); | 446 filter_types.Get().find(query_json_field.key()); |
444 if (filter_type != filter_types.Get().end()) { | 447 if (filter_type != filter_types.Get().end()) { |
445 if (!query_out.AddFilter(filter_type->second, query_json_field.value())) { | 448 if (!query_out.AddFilter(filter_type->second, query_json_field.value())) { |
446 *error = download_extension_errors::kInvalidFilterError; | 449 *error = download_extension_errors::kInvalidFilterError; |
447 return; | 450 return; |
448 } | 451 } |
449 } | 452 } |
450 } | 453 } |
451 | 454 |
452 DownloadManager* manager = NULL; | |
453 DownloadManager* incognito_manager = NULL; | |
454 GetManagers(profile, include_incognito, &manager, &incognito_manager); | |
455 DownloadQuery::DownloadVector all_items; | 455 DownloadQuery::DownloadVector all_items; |
456 if (query_in.id.get()) { | 456 if (query_in.id.get()) { |
457 DownloadItem* item = manager->GetDownloadItem(*query_in.id.get()); | 457 DownloadItem* item = manager->GetDownloadItem(*query_in.id.get()); |
458 if (!item && incognito_manager) | 458 if (!item && incognito_manager) |
459 item = incognito_manager->GetDownloadItem(*query_in.id.get()); | 459 item = incognito_manager->GetDownloadItem(*query_in.id.get()); |
460 if (item) | 460 if (item) |
461 all_items.push_back(item); | 461 all_items.push_back(item); |
462 } else { | 462 } else { |
463 manager->GetAllDownloads(FilePath(FILE_PATH_LITERAL("")), &all_items); | 463 manager->GetAllDownloads(FilePath(FILE_PATH_LITERAL("")), &all_items); |
464 if (incognito_manager) | 464 if (incognito_manager) |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
563 SendResponse(error_.empty()); | 563 SendResponse(error_.empty()); |
564 } | 564 } |
565 | 565 |
566 DownloadsSearchFunction::DownloadsSearchFunction() {} | 566 DownloadsSearchFunction::DownloadsSearchFunction() {} |
567 DownloadsSearchFunction::~DownloadsSearchFunction() {} | 567 DownloadsSearchFunction::~DownloadsSearchFunction() {} |
568 | 568 |
569 bool DownloadsSearchFunction::RunImpl() { | 569 bool DownloadsSearchFunction::RunImpl() { |
570 scoped_ptr<extensions::api::downloads::Search::Params> params( | 570 scoped_ptr<extensions::api::downloads::Search::Params> params( |
571 extensions::api::downloads::Search::Params::Create(*args_)); | 571 extensions::api::downloads::Search::Params::Create(*args_)); |
572 EXTENSION_FUNCTION_VALIDATE(params.get()); | 572 EXTENSION_FUNCTION_VALIDATE(params.get()); |
573 DownloadManager* manager = NULL; | |
574 DownloadManager* incognito_manager = NULL; | |
575 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | |
573 DownloadQuery::DownloadVector results; | 576 DownloadQuery::DownloadVector results; |
574 RunDownloadQuery(params->query, profile(), include_incognito(), | 577 RunDownloadQuery(params->query, |
575 &error_, &results); | 578 manager, |
579 incognito_manager, | |
580 &error_, | |
581 &results); | |
576 if (!error_.empty()) | 582 if (!error_.empty()) |
577 return false; | 583 return false; |
584 | |
578 base::ListValue* json_results = new base::ListValue(); | 585 base::ListValue* json_results = new base::ListValue(); |
579 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); | 586 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); |
580 it != results.end(); ++it) { | 587 it != results.end(); ++it) { |
581 scoped_ptr<base::DictionaryValue> item(DownloadItemToJSON(*it)); | 588 DownloadItem* item = *it; |
582 json_results->Append(item.release()); | 589 int32 download_id = item->GetId(); |
590 bool on_record = manager && manager->GetDownload(download_id); | |
591 bool off_record = (incognito_manager && | |
592 incognito_manager->GetDownload(download_id)); | |
593 DCHECK(on_record ^ off_record); | |
Randy Smith (Not in Mondays)
2012/07/23 18:19:26
Just noting that this is subtly scary. I went on
benjhayden
2012/07/25 20:59:58
Done.
| |
594 scoped_ptr<base::DictionaryValue> json_item(DownloadItemToJSON( | |
595 *it, off_record)); | |
596 json_results->Append(json_item.release()); | |
583 } | 597 } |
584 SetResult(json_results); | 598 SetResult(json_results); |
585 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); | 599 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); |
586 return true; | 600 return true; |
587 } | 601 } |
588 | 602 |
589 DownloadsPauseFunction::DownloadsPauseFunction() {} | 603 DownloadsPauseFunction::DownloadsPauseFunction() {} |
590 DownloadsPauseFunction::~DownloadsPauseFunction() {} | 604 DownloadsPauseFunction::~DownloadsPauseFunction() {} |
591 | 605 |
592 bool DownloadsPauseFunction::RunImpl() { | 606 bool DownloadsPauseFunction::RunImpl() { |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
783 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); | 797 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); |
784 SetResult(base::Value::CreateStringValue(url)); | 798 SetResult(base::Value::CreateStringValue(url)); |
785 } | 799 } |
786 SendResponse(error_.empty()); | 800 SendResponse(error_.empty()); |
787 } | 801 } |
788 | 802 |
789 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( | 803 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( |
790 Profile* profile, | 804 Profile* profile, |
791 DownloadManager* manager) | 805 DownloadManager* manager) |
792 : profile_(profile), | 806 : profile_(profile), |
793 manager_(manager) { | 807 manager_(manager), |
808 incognito_(profile_->HasOffTheRecordProfile() && | |
809 (profile_ == profile_->GetOffTheRecordProfile())) { | |
794 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 810 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
795 DCHECK(profile_); | |
796 DCHECK(manager_); | |
797 manager_->AddObserver(this); | 811 manager_->AddObserver(this); |
798 } | 812 } |
799 | 813 |
800 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { | 814 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { |
801 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 815 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
802 if (manager_ != NULL) | 816 if (manager_ != NULL) |
803 manager_->RemoveObserver(this); | 817 manager_->RemoveObserver(this); |
804 for (ItemMap::const_iterator iter = downloads_.begin(); | 818 for (ItemMap::const_iterator iter = downloads_.begin(); |
805 iter != downloads_.end(); ++iter) { | 819 iter != downloads_.end(); ++iter) { |
806 if (iter->second != NULL) | 820 if (iter->second != NULL) |
(...skipping 26 matching lines...) Expand all Loading... | |
833 DispatchEvent(extension_event_names::kOnDownloadErased, | 847 DispatchEvent(extension_event_names::kOnDownloadErased, |
834 base::Value::CreateIntegerValue(download_id)); | 848 base::Value::CreateIntegerValue(download_id)); |
835 delete item_jsons_[download_id]; | 849 delete item_jsons_[download_id]; |
836 item_jsons_.erase(download_id); | 850 item_jsons_.erase(download_id); |
837 delete on_changed_stats_[download_id]; | 851 delete on_changed_stats_[download_id]; |
838 on_changed_stats_.erase(download_id); | 852 on_changed_stats_.erase(download_id); |
839 return; | 853 return; |
840 } | 854 } |
841 | 855 |
842 base::DictionaryValue* old_json = item_jsons_[download_id]; | 856 base::DictionaryValue* old_json = item_jsons_[download_id]; |
843 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON(item)); | 857 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( |
858 item, incognito_)); | |
844 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); | 859 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); |
845 delta->SetInteger(kIdKey, download_id); | 860 delta->SetInteger(kIdKey, download_id); |
846 std::set<std::string> new_fields; | 861 std::set<std::string> new_fields; |
847 bool changed = false; | 862 bool changed = false; |
848 | 863 |
849 // For each field in the new json representation of the item except the | 864 // For each field in the new json representation of the item except the |
850 // bytesReceived field, if the field has changed from the previous old json, | 865 // bytesReceived field, if the field has changed from the previous old json, |
851 // set the differences in the |delta| object and remember that something | 866 // set the differences in the |delta| object and remember that something |
852 // significant changed. | 867 // significant changed. |
853 for (base::DictionaryValue::Iterator iter(*new_json.get()); | 868 for (base::DictionaryValue::Iterator iter(*new_json.get()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
923 std::insert_iterator<DownloadIdSet>( | 938 std::insert_iterator<DownloadIdSet>( |
924 new_set, new_set.begin())); | 939 new_set, new_set.begin())); |
925 | 940 |
926 // For each download that was not in the old set of downloads but is in the | 941 // For each download that was not in the old set of downloads but is in the |
927 // new set of downloads, fire an onCreated event, register as an Observer of | 942 // new set of downloads, fire an onCreated event, register as an Observer of |
928 // the item, store a json representation of the item so that we can easily | 943 // the item, store a json representation of the item so that we can easily |
929 // find changes in that json representation, and make an OnChangedStat. | 944 // find changes in that json representation, and make an OnChangedStat. |
930 for (DownloadIdSet::const_iterator iter = new_set.begin(); | 945 for (DownloadIdSet::const_iterator iter = new_set.begin(); |
931 iter != new_set.end(); ++iter) { | 946 iter != new_set.end(); ++iter) { |
932 scoped_ptr<base::DictionaryValue> item( | 947 scoped_ptr<base::DictionaryValue> item( |
933 DownloadItemToJSON(current_map[*iter])); | 948 DownloadItemToJSON(current_map[*iter], incognito_)); |
934 DispatchEvent(extension_event_names::kOnDownloadCreated, item->DeepCopy()); | 949 DispatchEvent(extension_event_names::kOnDownloadCreated, item->DeepCopy()); |
935 DCHECK(item_jsons_.find(*iter) == item_jsons_.end()); | 950 DCHECK(item_jsons_.find(*iter) == item_jsons_.end()); |
936 on_changed_stats_[*iter] = new OnChangedStat(); | 951 on_changed_stats_[*iter] = new OnChangedStat(); |
937 current_map[*iter]->AddObserver(this); | 952 current_map[*iter]->AddObserver(this); |
938 item_jsons_[*iter] = item.release(); | 953 item_jsons_[*iter] = item.release(); |
939 } | 954 } |
940 downloads_.swap(current_map); | 955 downloads_.swap(current_map); |
941 | 956 |
942 // Dispatching onErased is handled in OnDownloadUpdated when an item | 957 // Dispatching onErased is handled in OnDownloadUpdated when an item |
943 // transitions to the REMOVING state. | 958 // transitions to the REMOVING state. |
(...skipping 21 matching lines...) Expand all Loading... | |
965 extensions::EventFilteringInfo()); | 980 extensions::EventFilteringInfo()); |
966 | 981 |
967 DownloadsNotificationSource notification_source; | 982 DownloadsNotificationSource notification_source; |
968 notification_source.event_name = event_name; | 983 notification_source.event_name = event_name; |
969 notification_source.profile = profile_; | 984 notification_source.profile = profile_; |
970 content::NotificationService::current()->Notify( | 985 content::NotificationService::current()->Notify( |
971 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | 986 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
972 content::Source<DownloadsNotificationSource>(¬ification_source), | 987 content::Source<DownloadsNotificationSource>(¬ification_source), |
973 content::Details<std::string>(&json_args)); | 988 content::Details<std::string>(&json_args)); |
974 } | 989 } |
OLD | NEW |