File: notification_processor.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (142 lines) | stat: -rw-r--r-- 5,473 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_ASH_COMPONENTS_PHONEHUB_NOTIFICATION_PROCESSOR_H_
#define CHROMEOS_ASH_COMPONENTS_PHONEHUB_NOTIFICATION_PROCESSOR_H_

#include <google/protobuf/repeated_field.h>

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/queue.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/ash/components/phonehub/proto/phonehub_api.pb.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "services/data_decoder/public/cpp/decode_image.h"
#include "ui/gfx/image/image.h"

namespace ash::phonehub {

using ::google::protobuf::RepeatedPtrField;

class Notification;
class NotificationManager;

// A helper class that processes inline reply-able notification protos and
// updates the notification manager with such notifications to add or remove.
// Since decoding image(s) included in every notification proto are asynchronous
// calls, this class ensures that additions and removals are scheduled and
// executed synchronously via a queue of requests without unexpected race
// conditions. Note that adding notifications requires using an image utility
// process asynchronously, but removals are carried out synchronously.
class NotificationProcessor {
 public:
  using DecodeImageCallback = data_decoder::DecodeImageCallback;

  explicit NotificationProcessor(NotificationManager* notification_manager);
  virtual ~NotificationProcessor();

  NotificationProcessor(const NotificationProcessor&) = delete;
  NotificationProcessor& operator=(const NotificationProcessor&) = delete;

  // Removes all notifications and clears pending unfulfilled requests.
  void ClearNotificationsAndPendingUpdates();

  // Adds only inline reply-able notifications by extracting metadata from
  // their protos and asynchronously decoding their associated images.
  virtual void AddNotifications(
      const std::vector<proto::Notification>& notification_protos);

  // Removes notifications with |notifications_ids|.
  virtual void RemoveNotifications(
      const base::flat_set<int64_t>& notification_ids);

 private:
  friend class FakeNotificationProcessor;
  friend class NotificationProcessorTest;

  // Used to track which image type is being processed.
  enum class NotificationImageField {
    kColorIcon = 0,
    kMonochromeIcon = 1,
    kSharedImage = 2,
    kContactImage = 3,
  };

  // Each notification proto will be associated with one of these structs.
  // |color_icon| will always be populated, but |monochrome_icon|,
  // |shared_image|, and |contact_image| may be empty.
  struct NotificationImages {
    NotificationImages();
    ~NotificationImages();
    NotificationImages(const NotificationImages& other);
    NotificationImages& operator=(const NotificationImages& other);

    gfx::Image color_icon;
    gfx::Image monochrome_icon_mask;
    gfx::Image shared_image;
    gfx::Image contact_image;
  };

  // Each image to decode will be associated with one of these structs. Each
  // request in |pending_notification_requests_| may be associated to multiple
  // DecodeImageRequestMetadata with more than one |notification_id|.
  struct DecodeImageRequestMetadata {
    DecodeImageRequestMetadata(int64_t notification_id,
                               NotificationImageField image_field,
                               const std::string& data);

    int64_t notification_id;
    NotificationImageField image_field;
    std::string data;
  };

  // A delegate class that is faked out for testing purposes.
  class ImageDecoderDelegate {
   public:
    ImageDecoderDelegate() = default;
    virtual ~ImageDecoderDelegate() = default;

    virtual void PerformImageDecode(
        const std::string& data,
        DecodeImageCallback single_image_decoded_closure);

   private:
    // The instance of the Data Decoder used by this ImageDecoderDelegate to
    // perform any image decoding operations. The underlying service instance is
    // started lazily when needed and torn down when not in use.
    data_decoder::DataDecoder data_decoder_;
  };

  NotificationProcessor(NotificationManager* notification_manager,
                        std::unique_ptr<ImageDecoderDelegate> delegate);

  void StartDecodingImages(
      const std::vector<DecodeImageRequestMetadata>& decode_image_requests,
      base::RepeatingClosure done_closure);
  void OnDecodedBitmapReady(const DecodeImageRequestMetadata& request,
                            base::OnceClosure done_closure,
                            const SkBitmap& decoded_bitmap);
  void OnAllImagesDecoded(
      std::vector<proto::Notification> inline_replyable_notifications);

  void ProcessRequestQueue();
  void CompleteRequest();
  void AddNotificationsAndProcessNextRequest(
      const base::flat_set<Notification>& notifications);
  void RemoveNotificationsAndProcessNextRequest(
      base::flat_set<int64_t> removed_notification_ids);

  raw_ptr<NotificationManager> notification_manager_;
  base::queue<base::OnceClosure> pending_notification_requests_;
  base::flat_map<int64_t, NotificationImages> id_to_images_map_;
  std::unique_ptr<ImageDecoderDelegate> delegate_;

  base::WeakPtrFactory<NotificationProcessor> weak_ptr_factory_{this};
};

}  // namespace ash::phonehub

#endif  // CHROMEOS_ASH_COMPONENTS_PHONEHUB_NOTIFICATION_PROCESSOR_H_