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 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
516 } | 516 } |
517 | 517 |
518 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { | 518 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { |
519 public: | 519 public: |
520 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { | 520 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { |
521 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); | 521 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); |
522 return (data == NULL) ? NULL : | 522 return (data == NULL) ? NULL : |
523 static_cast<ExtensionDownloadsEventRouterData*>(data); | 523 static_cast<ExtensionDownloadsEventRouterData*>(data); |
524 } | 524 } |
525 | 525 |
526 static void Remove(DownloadItem* download_item) { | |
527 download_item->RemoveUserData(kKey); | |
528 } | |
529 | |
526 explicit ExtensionDownloadsEventRouterData( | 530 explicit ExtensionDownloadsEventRouterData( |
527 DownloadItem* download_item, | 531 DownloadItem* download_item, |
528 scoped_ptr<base::DictionaryValue> json_item) | 532 scoped_ptr<base::DictionaryValue> json_item) |
529 : updated_(0), | 533 : updated_(0), |
530 changed_fired_(0), | 534 changed_fired_(0), |
531 json_(json_item.Pass()), | 535 json_(json_item.Pass()), |
532 determined_conflict_action_( | 536 determined_conflict_action_( |
533 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { | 537 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { |
534 download_item->SetUserData(kKey, this); | 538 download_item->SetUserData(kKey, this); |
535 } | 539 } |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1239 // then the extension that was last installed wins. | 1243 // then the extension that was last installed wins. |
1240 | 1244 |
1241 void ExtensionDownloadsEventRouter::OnDeterminingFilename( | 1245 void ExtensionDownloadsEventRouter::OnDeterminingFilename( |
1242 DownloadItem* item, | 1246 DownloadItem* item, |
1243 const base::FilePath& suggested_path, | 1247 const base::FilePath& suggested_path, |
1244 const base::Closure& no_change, | 1248 const base::Closure& no_change, |
1245 const FilenameChangedCallback& change) { | 1249 const FilenameChangedCallback& change) { |
1246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1247 ExtensionDownloadsEventRouterData* data = | 1251 ExtensionDownloadsEventRouterData* data = |
1248 ExtensionDownloadsEventRouterData::Get(item); | 1252 ExtensionDownloadsEventRouterData::Get(item); |
1253 if (!data) { | |
1254 no_change.Run(); | |
1255 return; | |
1256 } | |
1249 data->ClearPendingDeterminers(); | 1257 data->ClearPendingDeterminers(); |
1250 data->set_filename_change_callbacks(no_change, change); | 1258 data->set_filename_change_callbacks(no_change, change); |
1251 bool any_determiners = false; | 1259 bool any_determiners = false; |
1252 base::DictionaryValue* json = DownloadItemToJSON( | 1260 base::DictionaryValue* json = DownloadItemToJSON( |
1253 item, profile_->IsOffTheRecord()).release(); | 1261 item, profile_->IsOffTheRecord()).release(); |
1254 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); | 1262 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); |
1255 DispatchEvent(extensions::event_names::kOnDownloadDeterminingFilename, | 1263 DispatchEvent(extensions::event_names::kOnDownloadDeterminingFilename, |
1256 false, | 1264 false, |
1257 base::Bind(&OnDeterminingFilenameWillDispatchCallback, | 1265 base::Bind(&OnDeterminingFilenameWillDispatchCallback, |
1258 &any_determiners, | 1266 &any_determiners, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1306 // forever waiting for this ext_id to report. | 1314 // forever waiting for this ext_id to report. |
1307 *error = download_extension_errors::kInvalidFilenameError; | 1315 *error = download_extension_errors::kInvalidFilenameError; |
1308 return false; | 1316 return false; |
1309 } | 1317 } |
1310 return true; | 1318 return true; |
1311 } | 1319 } |
1312 | 1320 |
1313 void ExtensionDownloadsEventRouter::OnListenerRemoved( | 1321 void ExtensionDownloadsEventRouter::OnListenerRemoved( |
1314 const extensions::EventListenerInfo& details) { | 1322 const extensions::EventListenerInfo& details) { |
1315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1316 if (details.event_name != | |
1317 extensions::event_names::kOnDownloadDeterminingFilename) | |
1318 return; | |
1319 DownloadManager* manager = notifier_.GetManager(); | 1324 DownloadManager* manager = notifier_.GetManager(); |
1320 if (!manager) | 1325 if (!manager) |
1321 return; | 1326 return; |
1327 bool determiner_removed = ( | |
1328 details.event_name == | |
1329 extensions::event_names::kOnDownloadDeterminingFilename); | |
Matt Perry
2013/04/17 02:01:28
nit: might help to put
namespace events = extens
benjhayden
2013/04/18 18:17:55
Done.
| |
1330 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> | |
1331 event_router(); | |
Matt Perry
2013/04/17 02:01:28
Use 4 space indent when wrapping a line like this.
benjhayden
2013/04/18 18:17:55
Done.
| |
1332 bool any_listeners = | |
1333 router->HasEventListener(extensions::event_names::kOnDownloadChanged) || | |
1334 router->HasEventListener( | |
1335 extensions::event_names::kOnDownloadDeterminingFilename); | |
1336 if (!determiner_removed && any_listeners) | |
1337 return; | |
1322 DownloadManager::DownloadVector items; | 1338 DownloadManager::DownloadVector items; |
1323 manager->GetAllDownloads(&items); | 1339 manager->GetAllDownloads(&items); |
1324 // Notify any items that may be waiting for callbacks from this | |
1325 // extension/determiner. | |
1326 for (DownloadManager::DownloadVector::const_iterator iter = | 1340 for (DownloadManager::DownloadVector::const_iterator iter = |
1327 items.begin(); | 1341 items.begin(); |
1328 iter != items.end(); ++iter) { | 1342 iter != items.end(); ++iter) { |
1329 ExtensionDownloadsEventRouterData* data = | 1343 ExtensionDownloadsEventRouterData* data = |
1330 ExtensionDownloadsEventRouterData::Get(*iter); | 1344 ExtensionDownloadsEventRouterData::Get(*iter); |
1331 // This will almost always be a no-op, however, it is possible for an | 1345 if (!data) |
1332 // extension renderer to be unloaded while a download item is waiting | 1346 continue; |
1333 // for a determiner. In that case, the download item should proceed. | 1347 if (determiner_removed) { |
1334 if (data) | 1348 // Notify any items that may be waiting for callbacks from this |
1349 // extension/determiner. This will almost always be a no-op, however, it | |
1350 // is possible for an extension renderer to be unloaded while a download | |
1351 // item is waiting for a determiner. In that case, the download item | |
1352 // should proceed. | |
1335 data->DeterminerRemoved(details.extension_id); | 1353 data->DeterminerRemoved(details.extension_id); |
1354 } | |
1355 if (!any_listeners) { | |
1356 ExtensionDownloadsEventRouterData::Remove(*iter); | |
1357 } | |
1336 } | 1358 } |
1337 } | 1359 } |
1338 | 1360 |
1339 // That's all the methods that have to do with filename determination. The rest | 1361 // That's all the methods that have to do with filename determination. The rest |
1340 // have to do with the other, less special events. | 1362 // have to do with the other, less special events. |
1341 | 1363 |
1342 void ExtensionDownloadsEventRouter::OnDownloadCreated( | 1364 void ExtensionDownloadsEventRouter::OnDownloadCreated( |
1343 DownloadManager* manager, DownloadItem* download_item) { | 1365 DownloadManager* manager, DownloadItem* download_item) { |
1344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1345 if (download_item->IsTemporary()) | 1367 if (download_item->IsTemporary()) |
1346 return; | 1368 return; |
1347 | 1369 |
1370 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> | |
1371 event_router(); | |
1372 // Avoid allocating a bunch of memory in DownloadItemToJSON if it isn't going | |
1373 // to be used. | |
1374 if (!router || | |
1375 (!router->HasEventListener(extensions::event_names::kOnDownloadCreated) && | |
1376 !router->HasEventListener(extensions::event_names::kOnDownloadChanged) && | |
1377 !router->HasEventListener( | |
1378 extensions::event_names::kOnDownloadDeterminingFilename))) { | |
1379 return; | |
1380 } | |
1348 scoped_ptr<base::DictionaryValue> json_item( | 1381 scoped_ptr<base::DictionaryValue> json_item( |
1349 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); | 1382 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); |
1350 DispatchEvent(extensions::event_names::kOnDownloadCreated, | 1383 DispatchEvent(extensions::event_names::kOnDownloadCreated, |
1351 true, | 1384 true, |
1352 extensions::Event::WillDispatchCallback(), | 1385 extensions::Event::WillDispatchCallback(), |
1353 json_item->DeepCopy()); | 1386 json_item->DeepCopy()); |
1354 if (!ExtensionDownloadsEventRouterData::Get(download_item)) | 1387 if (!ExtensionDownloadsEventRouterData::Get(download_item) && |
1388 (router->HasEventListener(extensions::event_names::kOnDownloadChanged) || | |
1389 router->HasEventListener( | |
1390 extensions::event_names::kOnDownloadDeterminingFilename))) { | |
1355 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); | 1391 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); |
1392 } | |
1356 } | 1393 } |
1357 | 1394 |
1358 void ExtensionDownloadsEventRouter::OnDownloadUpdated( | 1395 void ExtensionDownloadsEventRouter::OnDownloadUpdated( |
1359 DownloadManager* manager, DownloadItem* download_item) { | 1396 DownloadManager* manager, DownloadItem* download_item) { |
1360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1361 if (download_item->IsTemporary()) | 1398 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> |
1362 return; | 1399 event_router(); |
1363 | |
1364 ExtensionDownloadsEventRouterData* data = | 1400 ExtensionDownloadsEventRouterData* data = |
1365 ExtensionDownloadsEventRouterData::Get(download_item); | 1401 ExtensionDownloadsEventRouterData::Get(download_item); |
1402 if (download_item->IsTemporary() || | |
1403 !router->HasEventListener(extensions::event_names::kOnDownloadChanged)) { | |
1404 return; | |
1405 } | |
1366 if (!data) { | 1406 if (!data) { |
1367 // The download_item probably transitioned from temporary to not temporary. | 1407 // The download_item probably transitioned from temporary to not temporary, |
1368 OnDownloadCreated(manager, download_item); | 1408 // or else an event listener was added. |
1369 return; | 1409 data = new ExtensionDownloadsEventRouterData( |
1410 download_item, | |
1411 scoped_ptr<base::DictionaryValue>(new base::DictionaryValue())); | |
1370 } | 1412 } |
1371 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( | 1413 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( |
1372 download_item, profile_->IsOffTheRecord())); | 1414 download_item, profile_->IsOffTheRecord())); |
1373 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); | 1415 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); |
1374 delta->SetInteger(kIdKey, download_item->GetId()); | 1416 delta->SetInteger(kIdKey, download_item->GetId()); |
1375 std::set<std::string> new_fields; | 1417 std::set<std::string> new_fields; |
1376 bool changed = false; | 1418 bool changed = false; |
1377 | 1419 |
1378 // For each field in the new json representation of the download_item except | 1420 // For each field in the new json representation of the download_item except |
1379 // the bytesReceived field, if the field has changed from the previous old | 1421 // the bytesReceived field, if the field has changed from the previous old |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1456 DownloadsNotificationSource notification_source; | 1498 DownloadsNotificationSource notification_source; |
1457 notification_source.event_name = event_name; | 1499 notification_source.event_name = event_name; |
1458 notification_source.profile = profile_; | 1500 notification_source.profile = profile_; |
1459 content::Source<DownloadsNotificationSource> content_source( | 1501 content::Source<DownloadsNotificationSource> content_source( |
1460 ¬ification_source); | 1502 ¬ification_source); |
1461 content::NotificationService::current()->Notify( | 1503 content::NotificationService::current()->Notify( |
1462 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | 1504 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
1463 content_source, | 1505 content_source, |
1464 content::Details<std::string>(&json_args)); | 1506 content::Details<std::string>(&json_args)); |
1465 } | 1507 } |
OLD | NEW |