Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: chrome/browser/notifications/notification_platform_bridge_linux.cc

Issue 2859483003: Linux native notifications: Delete notification after sending CloseNotification. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698