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 |