1 // Copyright 2019 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 
5 #ifndef CHROME_BROWSER_CHROMEOS_ANDROID_SMS_FCM_CONNECTION_ESTABLISHER_H_
6 #define CHROME_BROWSER_CHROMEOS_ANDROID_SMS_FCM_CONNECTION_ESTABLISHER_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/memory/weak_ptr.h"
12 #include "base/timer/timer.h"
13 #include "chrome/browser/chromeos/android_sms/connection_establisher.h"
14 
15 namespace chromeos {
16 
17 namespace android_sms {
18 
19 // ConnectionEstablisher implementation that initiates an FCM web push
20 // suscription frin the Android Messages for Web service worker and the
21 // Tachyon server by dispatching a known message string to it.
22 class FcmConnectionEstablisher : public ConnectionEstablisher {
23  public:
24   explicit FcmConnectionEstablisher(
25       std::unique_ptr<base::OneShotTimer> retry_timer);
26   ~FcmConnectionEstablisher() override;
27 
28   // ConnectionEstablisher:
29   void EstablishConnection(
30       const GURL& url,
31       ConnectionMode connection_mode,
32       content::ServiceWorkerContext* service_worker_context) override;
33 
34   void TearDownConnection(
35       const GURL& url,
36       content::ServiceWorkerContext* service_worker_context) override;
37 
38  private:
39   // This enum is used for logging metrics. It should be kept in sync with
40   // AndroidSmsFcmMessageType in enums.xml
41   enum class MessageType {
42     kStart = 0,
43     kResume = 1,
44     kStop = 2,
45     kMaxValue = kStop,
46   };
47   friend std::ostream& operator<<(std::ostream& stream,
48                                   const MessageType& message_type);
49 
50   struct PendingServiceWorkerMessage {
51     PendingServiceWorkerMessage(
52         GURL service_worker_scope,
53         MessageType message_type,
54         content::ServiceWorkerContext* service_worker_context);
55     GURL service_worker_scope;
56     MessageType message_type;
57     content::ServiceWorkerContext* service_worker_context;
58   };
59 
60   struct InFlightMessage {
61     explicit InFlightMessage(PendingServiceWorkerMessage message);
62     PendingServiceWorkerMessage message;
63     size_t retry_count = 0u;
64   };
65 
66   FRIEND_TEST_ALL_PREFIXES(FcmConnectionEstablisherTest,
67                            TestEstablishConnection);
68   FRIEND_TEST_ALL_PREFIXES(FcmConnectionEstablisherTest,
69                            TestTearDownConnection);
70 
71   static MessageType GetMessageTypeForConnectionMode(
72       ConnectionMode connection_mode);
73 
74   static std::string GetMessageStringForType(MessageType message_type);
75 
76   void SendMessageToServiceWorkerWithRetries(
77       const GURL& url,
78       MessageType message_type,
79       content::ServiceWorkerContext* service_worker_context);
80 
81   void ProcessMessageQueue();
82 
83   void SendInFlightMessage();
84 
85   void OnMessageDispatchResult(bool status);
86 
87   std::unique_ptr<base::OneShotTimer> retry_timer_;
88   base::Optional<InFlightMessage> in_flight_message_;
89 
90   // A queue of messages to be dispatched. Messages are dispatched and retried
91   // one at a time from this queue.
92   base::queue<PendingServiceWorkerMessage> message_queue_;
93 
94   static const char kStartFcmMessage[];
95   static const char kResumeFcmMessage[];
96   static const char kStopFcmMessage[];
97   static const int kMaxRetryCount;
98   static const base::TimeDelta kRetryDelay;
99 
100   base::WeakPtrFactory<FcmConnectionEstablisher> weak_ptr_factory_{this};
101 
102   DISALLOW_COPY_AND_ASSIGN(FcmConnectionEstablisher);
103 };
104 
105 }  // namespace android_sms
106 
107 }  // namespace chromeos
108 
109 #endif  // CHROME_BROWSER_CHROMEOS_ANDROID_SMS_FCM_CONNECTION_ESTABLISHER_H_
110