summaryrefslogtreecommitdiffstats
path: root/remoting/client/plugin/chromoting_scriptable_object.h
blob: e34f2e139d4eea072059ec93b55dfb8930b36cc4 (plain)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This implements the JavaScript class entrypoint for the plugin instance.
// The Javascript API is defined as follows.
//
// interface ChromotingScriptableObject {
//
//   // Chromoting session API version (for this plugin).
//   // This is compared with the javascript API version to verify that they are
//   // compatible.
//   readonly attribute unsigned short apiVersion;
//
//   // The oldest API version that we support.
//   // This will differ from |apiVersion| if we decide to maintain backward
//   // compatibility with older API versions.
//   readonly attribute unsigned short apiMinVersion;
//
//   // Connection status.
//   readonly attribute unsigned short status;
//
//   // Constants for connection status.
//   const unsigned short STATUS_UNKNOWN = 0;
//   const unsigned short STATUS_CONNECTING = 1;
//   const unsigned short STATUS_INITIALIZING = 2;
//   const unsigned short STATUS_CONNECTED = 3;
//   const unsigned short STATUS_CLOSED = 4;
//   const unsigned short STATUS_FAILED = 5;
//
//   // Connection quality.
//   readonly attribute unsigned short quality;
//
//   // Constants for connection quality
//   const unsigned short QUALITY_UNKNOWN = 0;
//   const unsigned short QUALITY_GOOD = 1;
//   const unsigned short QUALITY_BAD = 2;
//
//   // JS callback function so we can signal the JS UI when the connection
//   // status has been updated.
//   attribute Function connectionInfoUpdate;
//
//   // JS callback function to call when there is new debug info to display
//   // in the client UI.
//   attribute Function debugInfo;
//
//   attribute Function desktopSizeUpdate;
//
//   // This function is called when login information for the host machine is
//   // needed.
//   //
//   // User of this object should respond with calling submitLoginInfo() when
//   // username and password is available.
//   //
//   // This function will be called multiple times until login was successful
//   // or the maximum number of login attempts has been reached. In the
//   // later case |connection_status| is changed to STATUS_FAILED.
//   attribute Function loginChallenge;
//
//   // JS callback function to send an XMPP IQ stanza for performing the
//   // signaling in a jingle connection.  The callback function should be
//   // of type void(string request_xml).
//   attribute Function sendIq;
//
//   // Dimension of the desktop area.
//   readonly attribute int desktopWidth;
//   readonly attribute int desktopHeight;
//
//   // Statistics.
//   // Video Bandwidth in bytes per second.
//   readonly attribute float videoBandwidth;
//   // Latency for capturing in milliseconds.
//   readonly attribute int videoCaptureLatency;
//   // Latency for video encoding in milliseconds.
//   readonly attribute int videoEncodeLatency;
//   // Latency for video decoding in milliseconds.
//   readonly attribute int videoDecodeLatency;
//   // Latency for rendering in milliseconds.
//   readonly attribute int videoRenderLatency;
//   // Latency between an event is sent and a corresponding video packet is
//   // received.
//   readonly attribute int roundTripLatency;
//
//   // Methods for establishing a Chromoting connection.
//   //
//   // sendIq must be set and responses to calls on sendIq must
//   // be piped back into onIq().
//   //
//   // Note that auth_token_with_service should be specified as
//   // "auth_service:auth_token". For example, "oauth2:5/aBd123".
//   void connect(string host_jid, string auth_token_with_service,
//                optional string access_code);
//
//   // Terminating a Chromoting connection.
//   void disconnect();
//
//   // Method for submitting login information.
//   void submitLoginInfo(string username, string password);
//
//   // Method for setting scale-to-fit.
//   void setScaleToFit(bool scale_to_fit);
//
//   // Method for receiving an XMPP IQ stanza in response to a previous
//   // sendIq() invocation. Other packets will be silently dropped.
//   void onIq(string response_xml);
//
//   // Method for releasing all keys to ensure a consistent host state.
//   void releaseAllKeys();
// }

#ifndef REMOTING_CLIENT_PLUGIN_CHROMOTING_SCRIPTABLE_OBJECT_H_
#define REMOTING_CLIENT_PLUGIN_CHROMOTING_SCRIPTABLE_OBJECT_H_

#include <map>
#include <string>
#include <vector>

#include "base/task.h"
#include "base/memory/weak_ptr.h"
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
#include "ppapi/cpp/var.h"

namespace base {
class MessageLoopProxy;
};  // namespace base

namespace remoting {

class ChromotingInstance;
class PepperXmppProxy;

enum ConnectionStatus {
  STATUS_UNKNOWN = 0,
  STATUS_CONNECTING,
  STATUS_INITIALIZING,
  STATUS_CONNECTED,
  STATUS_CLOSED,
  STATUS_FAILED,
};

enum ConnectionQuality {
  QUALITY_UNKNOWN = 0,
  QUALITY_GOOD,
  QUALITY_BAD,
};

class ChromotingScriptableObject
    : public pp::deprecated::ScriptableObject,
      public base::SupportsWeakPtr<ChromotingScriptableObject> {
 public:
  ChromotingScriptableObject(
      ChromotingInstance* instance,
      base::MessageLoopProxy* plugin_message_loop);
  virtual ~ChromotingScriptableObject();

  virtual void Init();

  // Override the ScriptableObject functions.
  virtual bool HasProperty(const pp::Var& name, pp::Var* exception);
  virtual bool HasMethod(const pp::Var& name, pp::Var* exception);
  virtual pp::Var GetProperty(const pp::Var& name, pp::Var* exception);
  virtual void GetAllPropertyNames(std::vector<pp::Var>* properties,
                                   pp::Var* exception);
  virtual void SetProperty(const pp::Var& name,
                           const pp::Var& value,
                           pp::Var* exception);
  virtual pp::Var Call(const pp::Var& method_name,
                       const std::vector<pp::Var>& args,
                       pp::Var* exception);

  void SetConnectionInfo(ConnectionStatus status, ConnectionQuality quality);
  void LogDebugInfo(const std::string& info);
  void SetDesktopSize(int width, int height);

  // This should be called to signal JS code to provide login information.
  void SignalLoginChallenge();

  // Attaches the XmppProxy used for issuing and receivng IQ stanzas for
  // initializing a jingle connection from within the sandbox.
  void AttachXmppProxy(PepperXmppProxy* xmpp_proxy);

  // Sends an IQ stanza, serialized as an xml string, into Javascript for
  // handling.
  void SendIq(const std::string& request_xml);

 private:
  typedef std::map<std::string, int> PropertyNameMap;
  typedef pp::Var (ChromotingScriptableObject::*MethodHandler)(
      const std::vector<pp::Var>& args, pp::Var* exception);
  struct PropertyDescriptor {
    PropertyDescriptor(const std::string& n, pp::Var a)
        : type(NONE), name(n), attribute(a), method(NULL) {
    }

    PropertyDescriptor(const std::string& n, MethodHandler m)
        : type(NONE), name(n), method(m) {
    }

    enum Type {
      NONE,
      ATTRIBUTE,
      METHOD,
    } type;

    std::string name;
    pp::Var attribute;
    MethodHandler method;
  };

  // Routines to add new attribute, method properties.
  void AddAttribute(const std::string& name, pp::Var attribute);
  void AddMethod(const std::string& name, MethodHandler handler);

  void SignalConnectionInfoChange();
  void SignalDesktopSizeChange();

  // Calls to these methods are posted to the plugin thread from
  // corresponding Signal*() methods. They actually call JavaScript
  // code. This is necessary becase JavaScript needs to be called with
  // clean stack - JavaScript event handlers may destroy the plugin.
  void DoSignalConnectionInfoChange();
  void DoSignalDesktopSizeChange();
  void DoSignalLoginChallenge();

  pp::Var DoConnect(const std::vector<pp::Var>& args, pp::Var* exception);
  pp::Var DoDisconnect(const std::vector<pp::Var>& args, pp::Var* exception);

  // This method is called by JS to provide login information.
  pp::Var DoSubmitLogin(const std::vector<pp::Var>& args, pp::Var* exception);

  // This method is called by JS to set scale-to-fit.
  pp::Var DoSetScaleToFit(const std::vector<pp::Var>& args, pp::Var* exception);

  // This method is called by Javascript to provide responses to sendIq()
  // requests.
  pp::Var DoOnIq(const std::vector<pp::Var>& args, pp::Var* exception);

  // This method is called by Javascript when the plugin loses input focus to
  // release all pressed keys.
  pp::Var DoReleaseAllKeys(const std::vector<pp::Var>& args,
                           pp::Var* exception);

  PropertyNameMap property_names_;
  std::vector<PropertyDescriptor> properties_;
  scoped_refptr<PepperXmppProxy> xmpp_proxy_;

  ChromotingInstance* instance_;

  scoped_refptr<base::MessageLoopProxy> plugin_message_loop_;
  ScopedRunnableMethodFactory<ChromotingScriptableObject> task_factory_;

  DISALLOW_COPY_AND_ASSIGN(ChromotingScriptableObject);
};

}  // namespace remoting

#endif  // REMOTING_CLIENT_PLUGIN_CHROMOTING_SCRIPTABLE_OBJECT_H_