1 // Copyright 2020 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 COMPONENTS_CAST_API_BINDINGS_SCOPED_API_BINDING_H_
6 #define COMPONENTS_CAST_API_BINDINGS_SCOPED_API_BINDING_H_
7 
8 #include <memory>
9 
10 #include "base/callback_forward.h"
11 #include "base/check.h"
12 #include "base/optional.h"
13 #include "base/strings/string_piece.h"
14 #include "components/cast/cast_component_export.h"
15 #include "components/cast/message_port/message_port.h"
16 
17 namespace cast_api_bindings {
18 
19 class Manager;
20 
21 // Manages the registration of bindings Javascript and establishment of
22 // communication channels, as well as unregistration on object teardown, using
23 // RAII semantics.
24 class CAST_COMPONENT_EXPORT ScopedApiBinding
25     : public cast_api_bindings::MessagePort::Receiver {
26  public:
27   // Methods for handling message I/O with bindings scripts.
28   class Delegate {
29    public:
30     virtual ~Delegate() = default;
31 
32     // Expresses the name for which MessagePort connection requests should be
33     // routed to the Delegate implementation.
34     virtual base::StringPiece GetPortName() const = 0;
35 
36     // Invoked when |message_port_| is connected. This allows the Delegate to do
37     // work when the client first connects, e.g. sending it a message conveying
38     // some initial state.
OnConnected()39     virtual void OnConnected() {}
40 
41     // Invoked for messages received over |message_port_|.
42     virtual bool OnMessage(base::StringPiece message) = 0;
43 
44     // Invoked when |message_port_| is disconnected.
45     // Allows the delegate to cleanup if the client unexpectedly disconnects.
OnDisconnected()46     virtual void OnDisconnected() {}
47   };
48 
49   // |bindings_manager|: Specifies the Manager to which the binding will be
50   //     published.
51   // |delegate|: If set, provides the necessary identifier and
52   //     method implementations for connecting script message I/O with the
53   //     bindings backend.
54   //     Must outlive |this|.
55   //     Can be nullptr if the bindings do not require communication.
56   // |js_bindings_id|: Id used for management of the |js_bindings| script.
57   //     Must be unique.
58   // |js_bindings|: script to inject.
59   ScopedApiBinding(Manager* bindings_manager,
60                    Delegate* delegate,
61                    base::StringPiece js_bindings_id,
62                    base::StringPiece js_bindings);
63   ~ScopedApiBinding() final;
64 
65   ScopedApiBinding(const ScopedApiBinding&) = delete;
66   ScopedApiBinding& operator=(const ScopedApiBinding&) = delete;
67 
68   // Sends a |message| to |message_port_|.
69   // Returns true if the message was sent.
70   bool SendMessage(base::StringPiece message);
71 
72  private:
73   // Called when a port is received from the page.
74   void OnPortConnected(std::unique_ptr<cast_api_bindings::MessagePort> port);
75 
76   // cast_api_bindings::MessagePort::Receiver implementation:
77   bool OnMessage(
78       base::StringPiece message,
79       std::vector<std::unique_ptr<cast_api_bindings::MessagePort>> ports) final;
80   void OnPipeError() final;
81 
82   Manager* const bindings_manager_;
83   Delegate* const delegate_;
84   const std::string js_bindings_id_;
85 
86   // The MessagePort used to receive messages from the receiver JS.
87   std::unique_ptr<cast_api_bindings::MessagePort> message_port_;
88 };
89 
90 }  // namespace cast_api_bindings
91 
92 #endif  // COMPONENTS_CAST_API_BINDINGS_SCOPED_API_BINDING_H_
93