Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/notifications/notification_platform_bridge_linux.h" | 5 #include "chrome/browser/notifications/notification_platform_bridge_linux.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | |
| 9 #include <set> | |
| 10 #include <unordered_map> | |
| 11 #include <utility> | |
| 12 #include <vector> | |
|
Tom (Use chromium acct)
2017/05/03 21:42:56
out of curiosity, did you do this by hand?
Lei Zhang
2017/05/03 21:45:24
"git cl lint" checks for these.
| |
| 8 | 13 |
| 9 #include "base/barrier_closure.h" | 14 #include "base/barrier_closure.h" |
| 10 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 11 #include "base/strings/nullable_string16.h" | 16 #include "base/strings/nullable_string16.h" |
| 12 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/task_scheduler/post_task.h" | 20 #include "base/task_scheduler/post_task.h" |
| 16 #include "chrome/browser/browser_process.h" | 21 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/chrome_notification_types.h" | 22 #include "chrome/browser/chrome_notification_types.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 void ProfileLoadedCallback(NotificationCommon::Operation operation, | 70 void ProfileLoadedCallback(NotificationCommon::Operation operation, |
| 66 NotificationCommon::Type notification_type, | 71 NotificationCommon::Type notification_type, |
| 67 const std::string& origin, | 72 const std::string& origin, |
| 68 const std::string& notification_id, | 73 const std::string& notification_id, |
| 69 int action_index, | 74 int action_index, |
| 70 const base::NullableString16& reply, | 75 const base::NullableString16& reply, |
| 71 Profile* profile) { | 76 Profile* profile) { |
| 72 if (!profile) | 77 if (!profile) |
| 73 return; | 78 return; |
| 74 | 79 |
| 75 NotificationDisplayService* display_service = | 80 auto* display_service = static_cast<NativeNotificationDisplayService*>( |
| 76 NotificationDisplayServiceFactory::GetForProfile(profile); | 81 NotificationDisplayServiceFactory::GetForProfile(profile)); |
| 77 | 82 display_service->ProcessNotificationOperation(operation, notification_type, |
| 78 static_cast<NativeNotificationDisplayService*>(display_service) | 83 origin, notification_id, |
| 79 ->ProcessNotificationOperation(operation, notification_type, origin, | 84 action_index, reply); |
| 80 notification_id, action_index, reply); | |
| 81 } | 85 } |
| 82 | 86 |
| 83 void ForwardNotificationOperationOnUiThread( | 87 void ForwardNotificationOperationOnUiThread( |
| 84 NotificationCommon::Operation operation, | 88 NotificationCommon::Operation operation, |
| 85 NotificationCommon::Type notification_type, | 89 NotificationCommon::Type notification_type, |
| 86 const std::string& origin, | 90 const std::string& origin, |
| 87 const std::string& notification_id, | 91 const std::string& notification_id, |
| 88 int action_index, | 92 int action_index, |
| 89 const std::string& profile_id, | 93 const std::string& profile_id, |
| 90 bool is_incognito) { | 94 bool is_incognito) { |
| 91 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 95 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 92 ProfileManager* profile_manager = g_browser_process->profile_manager(); | 96 g_browser_process->profile_manager()->LoadProfile( |
| 93 | |
| 94 profile_manager->LoadProfile( | |
| 95 profile_id, is_incognito, | 97 profile_id, is_incognito, |
| 96 base::Bind(&ProfileLoadedCallback, operation, notification_type, origin, | 98 base::Bind(&ProfileLoadedCallback, operation, notification_type, origin, |
| 97 notification_id, action_index, base::NullableString16())); | 99 notification_id, action_index, base::NullableString16())); |
| 98 } | 100 } |
| 99 | 101 |
| 100 // Writes |data| to a new temporary file and returns its path. | 102 class ResourceFile { |
| 101 // Returns base::FilePath() on failure. | 103 public: |
| 102 base::FilePath WriteDataToTmpFile( | 104 explicit ResourceFile(const base::FilePath& file_path) |
| 105 : file_path_(file_path) { | |
| 106 DCHECK(!file_path.empty()); | |
| 107 } | |
| 108 ~ResourceFile() { base::DeleteFile(file_path_, false); } | |
| 109 | |
| 110 const base::FilePath& file_path() const { return file_path_; } | |
| 111 | |
| 112 private: | |
| 113 const base::FilePath file_path_; | |
| 114 | |
| 115 DISALLOW_COPY_AND_ASSIGN(ResourceFile); | |
| 116 }; | |
| 117 | |
| 118 // Writes |data| to a new temporary file and returns the ResourceFile | |
| 119 // that holds it. | |
| 120 std::unique_ptr<ResourceFile> WriteDataToTmpFile( | |
| 103 const scoped_refptr<base::RefCountedMemory>& data) { | 121 const scoped_refptr<base::RefCountedMemory>& data) { |
| 104 int data_len = data->size(); | 122 int data_len = data->size(); |
| 105 if (data_len == 0) | 123 if (data_len == 0) |
| 106 return base::FilePath(); | 124 return nullptr; |
| 107 base::FilePath file_path; | 125 base::FilePath file_path; |
| 108 if (!base::CreateTemporaryFile(&file_path)) | 126 if (!base::CreateTemporaryFile(&file_path)) |
| 109 return base::FilePath(); | 127 return nullptr; |
| 128 | |
| 129 auto resource_file = base::MakeUnique<ResourceFile>(file_path); | |
| 110 if (base::WriteFile(file_path, data->front_as<char>(), data_len) != | 130 if (base::WriteFile(file_path, data->front_as<char>(), data_len) != |
| 111 data_len) { | 131 data_len) { |
| 112 base::DeleteFile(file_path, false); | 132 resource_file.reset(); |
| 113 return base::FilePath(); | |
| 114 } | 133 } |
| 115 return file_path; | 134 return resource_file; |
| 116 } | 135 } |
| 117 | 136 |
| 118 } // namespace | 137 } // namespace |
| 119 | 138 |
| 120 // static | 139 // static |
| 121 NotificationPlatformBridge* NotificationPlatformBridge::Create() { | 140 NotificationPlatformBridge* NotificationPlatformBridge::Create() { |
| 122 return new NotificationPlatformBridgeLinux(); | 141 return new NotificationPlatformBridgeLinux(); |
| 123 } | 142 } |
| 124 | 143 |
| 125 class NotificationPlatformBridgeLinuxImpl | 144 class NotificationPlatformBridgeLinuxImpl |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 | 220 |
| 202 void CleanUp() { | 221 void CleanUp() { |
| 203 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 222 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 204 PostTaskToTaskRunnerThread(base::BindOnce( | 223 PostTaskToTaskRunnerThread(base::BindOnce( |
| 205 &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this)); | 224 &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this)); |
| 206 } | 225 } |
| 207 | 226 |
| 208 private: | 227 private: |
| 209 friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>; | 228 friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>; |
| 210 | 229 |
| 211 struct ResourceFile { | |
| 212 explicit ResourceFile(const base::FilePath& file_path) | |
| 213 : file_path(file_path) {} | |
| 214 ~ResourceFile() { base::DeleteFile(file_path, false); } | |
| 215 const base::FilePath file_path; | |
| 216 }; | |
| 217 | |
| 218 struct NotificationData { | 230 struct NotificationData { |
| 219 NotificationData(NotificationCommon::Type notification_type, | 231 NotificationData(NotificationCommon::Type notification_type, |
| 220 const std::string& notification_id, | 232 const std::string& notification_id, |
| 221 const std::string& profile_id, | 233 const std::string& profile_id, |
| 222 bool is_incognito, | 234 bool is_incognito, |
| 223 const GURL& origin_url) | 235 const GURL& origin_url) |
| 224 : notification_type(notification_type), | 236 : notification_type(notification_type), |
| 225 notification_id(notification_id), | 237 notification_id(notification_id), |
| 226 profile_id(profile_id), | 238 profile_id(profile_id), |
| 227 is_incognito(is_incognito), | 239 is_incognito(is_incognito), |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 const char kDesktopFileSuffix[] = ".desktop"; | 417 const char kDesktopFileSuffix[] = ".desktop"; |
| 406 DCHECK(base::EndsWith(desktop_file.value(), kDesktopFileSuffix, | 418 DCHECK(base::EndsWith(desktop_file.value(), kDesktopFileSuffix, |
| 407 base::CompareCase::SENSITIVE)); | 419 base::CompareCase::SENSITIVE)); |
| 408 desktop_file = desktop_file.RemoveFinalExtension(); | 420 desktop_file = desktop_file.RemoveFinalExtension(); |
| 409 dbus::MessageWriter desktop_entry_writer(nullptr); | 421 dbus::MessageWriter desktop_entry_writer(nullptr); |
| 410 hints_writer.OpenDictEntry(&desktop_entry_writer); | 422 hints_writer.OpenDictEntry(&desktop_entry_writer); |
| 411 desktop_entry_writer.AppendString("desktop-entry"); | 423 desktop_entry_writer.AppendString("desktop-entry"); |
| 412 desktop_entry_writer.AppendVariantOfString(desktop_file.value()); | 424 desktop_entry_writer.AppendVariantOfString(desktop_file.value()); |
| 413 hints_writer.CloseContainer(&desktop_entry_writer); | 425 hints_writer.CloseContainer(&desktop_entry_writer); |
| 414 | 426 |
| 415 base::FilePath icon_file = | 427 std::unique_ptr<ResourceFile> icon_file = |
| 416 WriteDataToTmpFile(notification->icon().As1xPNGBytes()); | 428 WriteDataToTmpFile(notification->icon().As1xPNGBytes()); |
| 417 if (!icon_file.empty()) { | 429 if (icon_file) { |
| 418 dbus::MessageWriter image_path_writer(nullptr); | 430 dbus::MessageWriter image_path_writer(nullptr); |
| 419 hints_writer.OpenDictEntry(&image_path_writer); | 431 hints_writer.OpenDictEntry(&image_path_writer); |
| 420 image_path_writer.AppendString("image-path"); | 432 image_path_writer.AppendString("image-path"); |
| 421 image_path_writer.AppendVariantOfString(icon_file.value()); | 433 image_path_writer.AppendVariantOfString(icon_file->file_path().value()); |
| 422 hints_writer.CloseContainer(&image_path_writer); | 434 hints_writer.CloseContainer(&image_path_writer); |
| 423 data->resource_files.push_back(base::MakeUnique<ResourceFile>(icon_file)); | 435 data->resource_files.push_back(std::move(icon_file)); |
| 424 } | 436 } |
| 425 | 437 |
| 426 writer.CloseContainer(&hints_writer); | 438 writer.CloseContainer(&hints_writer); |
| 427 | 439 |
| 428 const int32_t kExpireTimeoutDefault = -1; | 440 const int32_t kExpireTimeoutDefault = -1; |
| 429 writer.AppendInt32(kExpireTimeoutDefault); | 441 writer.AppendInt32(kExpireTimeoutDefault); |
| 430 | 442 |
| 431 std::unique_ptr<dbus::Response> response = | 443 std::unique_ptr<dbus::Response> response = |
| 432 notification_proxy_->CallMethodAndBlock( | 444 notification_proxy_->CallMethodAndBlock( |
| 433 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); | 445 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 449 for (const auto& pair : notifications_) { | 461 for (const auto& pair : notifications_) { |
| 450 NotificationData* data = pair.first; | 462 NotificationData* data = pair.first; |
| 451 if (data->notification_id == notification_id && | 463 if (data->notification_id == notification_id && |
| 452 data->profile_id == profile_id) { | 464 data->profile_id == profile_id) { |
| 453 dbus::MethodCall method_call(kFreedesktopNotificationsName, | 465 dbus::MethodCall method_call(kFreedesktopNotificationsName, |
| 454 "CloseNotification"); | 466 "CloseNotification"); |
| 455 dbus::MessageWriter writer(&method_call); | 467 dbus::MessageWriter writer(&method_call); |
| 456 writer.AppendUint32(data->dbus_id); | 468 writer.AppendUint32(data->dbus_id); |
| 457 notification_proxy_->CallMethodAndBlock( | 469 notification_proxy_->CallMethodAndBlock( |
| 458 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); | 470 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); |
| 471 to_erase.push_back(data); | |
| 459 } | 472 } |
| 460 } | 473 } |
| 461 for (NotificationData* data : to_erase) | 474 for (NotificationData* data : to_erase) |
| 462 notifications_.erase(data); | 475 notifications_.erase(data); |
| 463 } | 476 } |
| 464 | 477 |
| 465 void GetDisplayedOnTaskRunner( | 478 void GetDisplayedOnTaskRunner( |
| 466 const std::string& profile_id, | 479 const std::string& profile_id, |
| 467 bool incognito, | 480 bool incognito, |
| 468 const GetDisplayedNotificationsCallback& callback) const { | 481 const GetDisplayedNotificationsCallback& callback) const { |
| 469 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 482 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 470 auto displayed = base::MakeUnique<std::set<std::string>>(); | 483 auto displayed = base::MakeUnique<std::set<std::string>>(); |
| 471 for (const auto& notification : notifications_) { | 484 for (const auto& pair : notifications_) { |
| 472 if (notification.first->profile_id == profile_id && | 485 NotificationData* data = pair.first; |
| 473 notification.first->is_incognito == incognito) { | 486 if (data->profile_id == profile_id && data->is_incognito == incognito) |
| 474 displayed->insert(notification.first->notification_id); | 487 displayed->insert(data->notification_id); |
| 475 } | |
| 476 } | 488 } |
| 477 PostTaskToUiThread(base::BindOnce(callback, std::move(displayed), true)); | 489 PostTaskToUiThread(base::BindOnce(callback, std::move(displayed), true)); |
| 478 } | 490 } |
| 479 | 491 |
| 480 NotificationData* FindNotificationData(const std::string& notification_id, | 492 NotificationData* FindNotificationData(const std::string& notification_id, |
| 481 const std::string& profile_id, | 493 const std::string& profile_id, |
| 482 bool is_incognito) { | 494 bool is_incognito) { |
| 483 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 495 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 484 for (const auto& pair : notifications_) { | 496 for (const auto& pair : notifications_) { |
| 485 NotificationData* data = pair.first; | 497 NotificationData* data = pair.first; |
| 486 if (data->notification_id == notification_id && | 498 if (data->notification_id == notification_id && |
| 487 data->profile_id == profile_id && | 499 data->profile_id == profile_id && |
| 488 data->is_incognito == is_incognito) { | 500 data->is_incognito == is_incognito) { |
| 489 return data; | 501 return data; |
| 490 } | 502 } |
| 491 } | 503 } |
| 492 | 504 |
| 493 return nullptr; | 505 return nullptr; |
| 494 } | 506 } |
| 495 | 507 |
| 496 NotificationData* FindNotificationData(uint32_t dbus_id) { | 508 NotificationData* FindNotificationDataWithDBusId(uint32_t dbus_id) { |
| 497 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 509 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 510 DCHECK(dbus_id); | |
| 498 for (const auto& pair : notifications_) { | 511 for (const auto& pair : notifications_) { |
| 499 NotificationData* data = pair.first; | 512 NotificationData* data = pair.first; |
| 500 if (data->dbus_id == dbus_id) | 513 if (data->dbus_id == dbus_id) |
| 501 return data; | 514 return data; |
| 502 } | 515 } |
| 503 | 516 |
| 504 return nullptr; | 517 return nullptr; |
| 505 } | 518 } |
| 506 | 519 |
| 507 void ForwardNotificationOperation(NotificationData* data, | 520 void ForwardNotificationOperation(NotificationData* data, |
| 508 NotificationCommon::Operation operation, | 521 NotificationCommon::Operation operation, |
| 509 int action_index) { | 522 int action_index) { |
| 510 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 523 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 511 PostTaskToUiThread(base::BindOnce( | 524 PostTaskToUiThread(base::BindOnce( |
| 512 ForwardNotificationOperationOnUiThread, operation, | 525 ForwardNotificationOperationOnUiThread, operation, |
| 513 data->notification_type, data->origin_url.spec(), data->notification_id, | 526 data->notification_type, data->origin_url.spec(), data->notification_id, |
| 514 action_index, data->profile_id, data->is_incognito)); | 527 action_index, data->profile_id, data->is_incognito)); |
| 515 } | 528 } |
| 516 | 529 |
| 517 void OnActionInvoked(dbus::Signal* signal) { | 530 void OnActionInvoked(dbus::Signal* signal) { |
| 518 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 531 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 519 dbus::MessageReader reader(signal); | 532 dbus::MessageReader reader(signal); |
| 520 uint32_t dbus_id; | 533 uint32_t dbus_id; |
| 521 if (!reader.PopUint32(&dbus_id)) | 534 if (!reader.PopUint32(&dbus_id) || !dbus_id) |
| 522 return; | 535 return; |
| 523 std::string action; | 536 std::string action; |
| 524 if (!reader.PopString(&action)) | 537 if (!reader.PopString(&action)) |
| 525 return; | 538 return; |
| 526 | 539 |
| 527 NotificationData* data = FindNotificationData(dbus_id); | 540 NotificationData* data = FindNotificationDataWithDBusId(dbus_id); |
| 528 if (!data) | 541 if (!data) |
| 529 return; | 542 return; |
| 530 | 543 |
| 531 if (action == kDefaultButtonId) { | 544 if (action == kDefaultButtonId) { |
| 532 ForwardNotificationOperation(data, NotificationCommon::CLICK, -1); | 545 ForwardNotificationOperation(data, NotificationCommon::CLICK, -1); |
| 533 } else if (action == kSettingsButtonId) { | 546 } else if (action == kSettingsButtonId) { |
| 534 ForwardNotificationOperation(data, NotificationCommon::SETTINGS, -1); | 547 ForwardNotificationOperation(data, NotificationCommon::SETTINGS, -1); |
| 535 } else { | 548 } else { |
| 536 size_t id; | 549 size_t id; |
| 537 if (!base::StringToSizeT(action, &id)) | 550 if (!base::StringToSizeT(action, &id)) |
| 538 return; | 551 return; |
| 539 size_t n_buttons = data->action_end - data->action_start; | 552 size_t n_buttons = data->action_end - data->action_start; |
| 540 size_t id_zero_based = id - data->action_start; | 553 size_t id_zero_based = id - data->action_start; |
| 541 if (id_zero_based >= n_buttons) | 554 if (id_zero_based >= n_buttons) |
| 542 return; | 555 return; |
| 543 ForwardNotificationOperation(data, NotificationCommon::CLICK, | 556 ForwardNotificationOperation(data, NotificationCommon::CLICK, |
| 544 id_zero_based); | 557 id_zero_based); |
| 545 } | 558 } |
| 546 } | 559 } |
| 547 | 560 |
| 548 void OnNotificationClosed(dbus::Signal* signal) { | 561 void OnNotificationClosed(dbus::Signal* signal) { |
| 549 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 562 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 550 dbus::MessageReader reader(signal); | 563 dbus::MessageReader reader(signal); |
| 551 uint32_t dbus_id; | 564 uint32_t dbus_id; |
| 552 if (!reader.PopUint32(&dbus_id)) | 565 if (!reader.PopUint32(&dbus_id) || !dbus_id) |
| 553 return; | 566 return; |
| 554 | 567 |
| 555 NotificationData* data = FindNotificationData(dbus_id); | 568 NotificationData* data = FindNotificationDataWithDBusId(dbus_id); |
| 556 if (!data) | 569 if (!data) |
| 557 return; | 570 return; |
| 558 | 571 |
| 559 ForwardNotificationOperation(data, NotificationCommon::CLOSE, -1); | 572 ForwardNotificationOperation(data, NotificationCommon::CLOSE, -1); |
| 560 notifications_.erase(data); | 573 notifications_.erase(data); |
| 561 } | 574 } |
| 562 | 575 |
| 563 // Called once the connection has been set up (or not). |success| | 576 // Called once the connection has been set up (or not). |success| |
| 564 // indicates the connection is ready to use. | 577 // indicates the connection is ready to use. |
| 565 void OnConnectionInitializationFinishedOnUiThread(bool success) { | 578 void OnConnectionInitializationFinishedOnUiThread(bool success) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 658 } | 671 } |
| 659 | 672 |
| 660 void NotificationPlatformBridgeLinux::SetReadyCallback( | 673 void NotificationPlatformBridgeLinux::SetReadyCallback( |
| 661 NotificationBridgeReadyCallback callback) { | 674 NotificationBridgeReadyCallback callback) { |
| 662 impl_->SetReadyCallback(std::move(callback)); | 675 impl_->SetReadyCallback(std::move(callback)); |
| 663 } | 676 } |
| 664 | 677 |
| 665 void NotificationPlatformBridgeLinux::CleanUp() { | 678 void NotificationPlatformBridgeLinux::CleanUp() { |
| 666 impl_->CleanUp(); | 679 impl_->CleanUp(); |
| 667 } | 680 } |
| OLD | NEW |