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> |
| (...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 |