notification_processor.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef ASH_COMPONENTS_PHONEHUB_NOTIFICATION_PROCESSOR_H_
  5. #define ASH_COMPONENTS_PHONEHUB_NOTIFICATION_PROCESSOR_H_
  6. #include <google/protobuf/repeated_field.h>
  7. #include "ash/components/phonehub/proto/phonehub_api.pb.h"
  8. #include "base/containers/flat_map.h"
  9. #include "base/containers/flat_set.h"
  10. #include "base/containers/queue.h"
  11. #include "base/memory/weak_ptr.h"
  12. #include "services/data_decoder/public/cpp/data_decoder.h"
  13. #include "services/data_decoder/public/cpp/decode_image.h"
  14. #include "ui/gfx/image/image.h"
  15. namespace ash {
  16. namespace phonehub {
  17. using ::google::protobuf::RepeatedPtrField;
  18. class Notification;
  19. class NotificationManager;
  20. // A helper class that processes inline reply-able notification protos and
  21. // updates the notification manager with such notifications to add or remove.
  22. // Since decoding image(s) included in every notification proto are asynchronous
  23. // calls, this class ensures that additions and removals are scheduled and
  24. // executed synchronously via a queue of requests without unexpected race
  25. // conditions. Note that adding notifications requires using an image utility
  26. // process asynchronously, but removals are carried out synchronously.
  27. class NotificationProcessor {
  28. public:
  29. using DecodeImageCallback = data_decoder::DecodeImageCallback;
  30. explicit NotificationProcessor(NotificationManager* notification_manager);
  31. virtual ~NotificationProcessor();
  32. NotificationProcessor(const NotificationProcessor&) = delete;
  33. NotificationProcessor& operator=(const NotificationProcessor&) = delete;
  34. // Removes all notifications and clears pending unfulfilled requests.
  35. void ClearNotificationsAndPendingUpdates();
  36. // Adds only inline reply-able notifications by extracting metadata from
  37. // their protos and asynchronously decoding their associated images.
  38. virtual void AddNotifications(
  39. const std::vector<proto::Notification>& notification_protos);
  40. // Removes notifications with |notifications_ids|.
  41. virtual void RemoveNotifications(
  42. const base::flat_set<int64_t>& notification_ids);
  43. private:
  44. friend class FakeNotificationProcessor;
  45. friend class NotificationProcessorTest;
  46. // Used to track which image type is being processed.
  47. enum class NotificationImageField {
  48. kIcon = 0,
  49. kSharedImage = 1,
  50. kContactImage = 2,
  51. };
  52. // Each notification proto will be associated with one of these structs.
  53. // |icon| will always be populated, but |shared_image| and |contact_image| may
  54. // be empty.
  55. struct NotificationImages {
  56. gfx::Image icon;
  57. gfx::Image shared_image;
  58. gfx::Image contact_image;
  59. };
  60. // Each image to decode will be associated with one of these structs. Each
  61. // request in |pending_notification_requests_| may be associated to multiple
  62. // DecodeImageRequestMetadata with more than one |notification_id|.
  63. struct DecodeImageRequestMetadata {
  64. DecodeImageRequestMetadata(int64_t notification_id,
  65. NotificationImageField image_field,
  66. const std::string& data);
  67. int64_t notification_id;
  68. NotificationImageField image_field;
  69. std::string data;
  70. };
  71. // A delegate class that is faked out for testing purposes.
  72. class ImageDecoderDelegate {
  73. public:
  74. ImageDecoderDelegate() = default;
  75. virtual ~ImageDecoderDelegate() = default;
  76. virtual void PerformImageDecode(
  77. const std::string& data,
  78. DecodeImageCallback single_image_decoded_closure);
  79. private:
  80. // The instance of the Data Decoder used by this ImageDecoderDelegate to
  81. // perform any image decoding operations. The underlying service instance is
  82. // started lazily when needed and torn down when not in use.
  83. data_decoder::DataDecoder data_decoder_;
  84. };
  85. NotificationProcessor(NotificationManager* notification_manager,
  86. std::unique_ptr<ImageDecoderDelegate> delegate);
  87. void StartDecodingImages(
  88. const std::vector<DecodeImageRequestMetadata>& decode_image_requests,
  89. base::RepeatingClosure done_closure);
  90. void OnDecodedBitmapReady(const DecodeImageRequestMetadata& request,
  91. base::OnceClosure done_closure,
  92. const SkBitmap& decoded_bitmap);
  93. void OnAllImagesDecoded(
  94. std::vector<proto::Notification> inline_replyable_notifications);
  95. void ProcessRequestQueue();
  96. void CompleteRequest();
  97. void AddNotificationsAndProcessNextRequest(
  98. const base::flat_set<Notification>& notifications);
  99. void RemoveNotificationsAndProcessNextRequest(
  100. base::flat_set<int64_t> removed_notification_ids);
  101. NotificationManager* notification_manager_;
  102. base::queue<base::OnceClosure> pending_notification_requests_;
  103. base::flat_map<int64_t, NotificationImages> id_to_images_map_;
  104. std::unique_ptr<ImageDecoderDelegate> delegate_;
  105. base::WeakPtrFactory<NotificationProcessor> weak_ptr_factory_{this};
  106. };
  107. } // namespace phonehub
  108. } // namespace ash
  109. #endif // ASH_COMPONENTS_PHONEHUB_NOTIFICATION_PROCESSOR_H_