1 // Copyright (c) 2010 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.
5 #include "remoting/client/plugin/chromoting_scriptable_object.h"
7 #include "base/logging.h"
8 #include "ppapi/cpp/var.h"
9 #include "remoting/client/client_config.h"
10 #include "remoting/client/plugin/chromoting_instance.h"
16 const char kConnectionInfoUpdate
[] = "connectionInfoUpdate";
17 const char kDebugInfoUpdate
[] = "debugInfoUpdate";
18 const char kDebugInfoAttribute
[] = "debugInfo";
19 const char kDesktopHeight
[] = "desktopHeight";
20 const char kDesktopWidth
[] = "desktopWidth";
21 const char kLoginChallenge
[] = "loginChallenge";
22 const char kQualityAttribute
[] = "quality";
23 const char kStatusAttribute
[] = "status";
25 ChromotingScriptableObject::ChromotingScriptableObject(
26 ChromotingInstance
* instance
)
27 : instance_(instance
) {
30 ChromotingScriptableObject::~ChromotingScriptableObject() {
33 void ChromotingScriptableObject::Init() {
34 // Property addition order should match the interface description at the
35 // top of chromoting_scriptable_object.h.
38 AddAttribute(kStatusAttribute
, Var(STATUS_UNKNOWN
));
40 // Connection status values.
41 AddAttribute("STATUS_UNKNOWN", Var(STATUS_UNKNOWN
));
42 AddAttribute("STATUS_CONNECTING", Var(STATUS_CONNECTING
));
43 AddAttribute("STATUS_INITIALIZING", Var(STATUS_INITIALIZING
));
44 AddAttribute("STATUS_CONNECTED", Var(STATUS_CONNECTED
));
45 AddAttribute("STATUS_CLOSED", Var(STATUS_CLOSED
));
46 AddAttribute("STATUS_FAILED", Var(STATUS_FAILED
));
48 // Connection quality.
49 AddAttribute(kQualityAttribute
, Var(QUALITY_UNKNOWN
));
51 // Connection quality values.
52 AddAttribute("QUALITY_UNKNOWN", Var(QUALITY_UNKNOWN
));
53 AddAttribute("QUALITY_GOOD", Var(QUALITY_GOOD
));
54 AddAttribute("QUALITY_BAD", Var(QUALITY_BAD
));
56 // Debug info to display.
57 AddAttribute(kDebugInfoAttribute
, Var());
59 AddAttribute(kConnectionInfoUpdate
, Var());
60 AddAttribute(kDebugInfoUpdate
, Var());
61 AddAttribute(kLoginChallenge
, Var());
62 AddAttribute(kDesktopWidth
, Var(0));
63 AddAttribute(kDesktopHeight
, Var(0));
65 AddMethod("connect", &ChromotingScriptableObject::DoConnect
);
66 AddMethod("disconnect", &ChromotingScriptableObject::DoDisconnect
);
67 AddMethod("submitLoginInfo", &ChromotingScriptableObject::DoSubmitLogin
);
70 bool ChromotingScriptableObject::HasProperty(const Var
& name
, Var
* exception
) {
71 // TODO(ajwong): Check if all these name.is_string() sentinels are required.
72 if (!name
.is_string()) {
73 *exception
= Var("HasProperty expects a string for the name.");
77 PropertyNameMap::const_iterator iter
= property_names_
.find(name
.AsString());
78 if (iter
== property_names_
.end()) {
82 // TODO(ajwong): Investigate why ARM build breaks if you do:
83 // properties_[iter->second].method == NULL;
84 // Somehow the ARM compiler is thinking that the above is using NULL as an
85 // arithmetic expression.
86 return properties_
[iter
->second
].method
== 0;
89 bool ChromotingScriptableObject::HasMethod(const Var
& name
, Var
* exception
) {
90 // TODO(ajwong): Check if all these name.is_string() sentinels are required.
91 if (!name
.is_string()) {
92 *exception
= Var("HasMethod expects a string for the name.");
96 PropertyNameMap::const_iterator iter
= property_names_
.find(name
.AsString());
97 if (iter
== property_names_
.end()) {
101 // See comment from HasProperty about why to use 0 instead of NULL here.
102 return properties_
[iter
->second
].method
!= 0;
105 Var
ChromotingScriptableObject::GetProperty(const Var
& name
, Var
* exception
) {
106 // TODO(ajwong): Check if all these name.is_string() sentinels are required.
107 if (!name
.is_string()) {
108 *exception
= Var("GetProperty expects a string for the name.");
112 PropertyNameMap::const_iterator iter
= property_names_
.find(name
.AsString());
114 // No property found.
115 if (iter
== property_names_
.end()) {
116 return ScriptableObject::GetProperty(name
, exception
);
119 // TODO(ajwong): This incorrectly return a null object if a function
120 // property is requested.
121 return properties_
[iter
->second
].attribute
;
124 void ChromotingScriptableObject::GetAllPropertyNames(
125 std::vector
<Var
>* properties
,
127 for (size_t i
= 0; i
< properties_
.size(); i
++) {
128 properties
->push_back(Var(properties_
[i
].name
));
132 void ChromotingScriptableObject::SetProperty(const Var
& name
,
135 // TODO(ajwong): Check if all these name.is_string() sentinels are required.
136 if (!name
.is_string()) {
137 *exception
= Var("SetProperty expects a string for the name.");
141 // Allow writing to connectionInfoUpdate or loginChallenge. See top of
142 // chromoting_scriptable_object.h for the object interface definition.
143 std::string property_name
= name
.AsString();
144 if (property_name
!= kConnectionInfoUpdate
&&
145 property_name
!= kDebugInfoUpdate
&&
146 property_name
!= kLoginChallenge
&&
147 property_name
!= kDesktopWidth
&&
148 property_name
!= kDesktopHeight
) {
150 Var("Cannot set property " + property_name
+ " on this object.");
154 // Since we're whitelisting the propertie that are settable above, we can
155 // assume that the property exists in the map.
156 properties_
[property_names_
[property_name
]].attribute
= value
;
159 Var
ChromotingScriptableObject::Call(const Var
& method_name
,
160 const std::vector
<Var
>& args
,
162 PropertyNameMap::const_iterator iter
=
163 property_names_
.find(method_name
.AsString());
164 if (iter
== property_names_
.end()) {
165 return pp::deprecated::ScriptableObject::Call(method_name
, args
, exception
);
168 return (this->*(properties_
[iter
->second
].method
))(args
, exception
);
171 void ChromotingScriptableObject::SetConnectionInfo(ConnectionStatus status
,
172 ConnectionQuality quality
) {
173 int status_index
= property_names_
[kStatusAttribute
];
174 int quality_index
= property_names_
[kQualityAttribute
];
176 if (properties_
[status_index
].attribute
.AsInt() != status
||
177 properties_
[quality_index
].attribute
.AsInt() != quality
) {
178 // Update the connection state properties..
179 properties_
[status_index
].attribute
= Var(status
);
180 properties_
[quality_index
].attribute
= Var(quality
);
182 // Signal the Chromoting Tab UI to get the update connection state values.
183 SignalConnectionInfoChange();
187 void ChromotingScriptableObject::LogDebugInfo(const std::string
& info
) {
188 int debug_info_index
= property_names_
[kDebugInfoAttribute
];
190 // Update the debug info string.
191 // Note that this only stores the most recent debug string.
192 properties_
[debug_info_index
].attribute
= Var(info
);
194 // Signal the client UI to get the updated debug info.
195 SignalDebugInfoChange();
198 void ChromotingScriptableObject::SetDesktopSize(int width
, int height
) {
199 int width_index
= property_names_
[kDesktopWidth
];
200 int height_index
= property_names_
[kDesktopHeight
];
202 if (properties_
[width_index
].attribute
.AsInt() != width
||
203 properties_
[height_index
].attribute
.AsInt() != height
) {
204 properties_
[width_index
].attribute
= Var(width
);
205 properties_
[height_index
].attribute
= Var(height
);
209 void ChromotingScriptableObject::AddAttribute(const std::string
& name
,
211 property_names_
[name
] = properties_
.size();
212 properties_
.push_back(PropertyDescriptor(name
, attribute
));
215 void ChromotingScriptableObject::AddMethod(const std::string
& name
,
216 MethodHandler handler
) {
217 property_names_
[name
] = properties_
.size();
218 properties_
.push_back(PropertyDescriptor(name
, handler
));
221 void ChromotingScriptableObject::SignalConnectionInfoChange() {
224 // The JavaScript callback function is the 'callback' property on the
225 // 'connectionInfoUpdate' object.
226 Var cb
= GetProperty(Var(kConnectionInfoUpdate
), &exception
);
228 // Var() means call the object directly as a function rather than calling
229 // a method in the object.
230 cb
.Call(Var(), 0, NULL
, &exception
);
232 if (!exception
.is_undefined()) {
233 LOG(WARNING
) << "Exception when invoking connectionInfoUpdate JS callback"
234 << exception
.AsString();
238 void ChromotingScriptableObject::SignalDebugInfoChange() {
241 // The JavaScript callback function is the 'callback' property on the
242 // 'debugInfoUpdate' object.
243 Var cb
= GetProperty(Var(kDebugInfoUpdate
), &exception
);
245 // Var() means call the object directly as a function rather than calling
246 // a method in the object.
247 cb
.Call(Var(), 0, NULL
, &exception
);
249 if (!exception
.is_undefined()) {
250 LOG(WARNING
) << "Exception when invoking debugInfoUpdate JS callback"
251 << exception
.AsString();
255 void ChromotingScriptableObject::SignalLoginChallenge() {
258 // The JavaScript callback function is the 'callback' property on the
259 // 'loginChallenge' object.
260 Var cb
= GetProperty(Var(kLoginChallenge
), &exception
);
262 // Var() means call the object directly as a function rather than calling
263 // a method in the object.
264 cb
.Call(Var(), 0, NULL
, &exception
);
266 if (!exception
.is_undefined()) {
267 LOG(WARNING
) << "Exception when invoking loginChallenge JS callback"
268 << exception
.AsString();
272 Var
ChromotingScriptableObject::DoConnect(const std::vector
<Var
>& args
,
274 if (args
.size() != 3) {
275 *exception
= Var("Usage: connect(username, host_jid, auth_token)");
281 if (!args
[0].is_string()) {
282 *exception
= Var("The username must be a string.");
285 config
.username
= args
[0].AsString();
287 if (!args
[1].is_string()) {
288 *exception
= Var("The host_jid must be a string.");
291 config
.host_jid
= args
[1].AsString();
293 if (!args
[2].is_string()) {
294 *exception
= Var("The auth_token must be a string.");
297 config
.auth_token
= args
[2].AsString();
299 instance_
->Connect(config
);
304 Var
ChromotingScriptableObject::DoDisconnect(const std::vector
<Var
>& args
,
306 instance_
->Disconnect();
310 Var
ChromotingScriptableObject::DoSubmitLogin(const std::vector
<Var
>& args
,
312 if (args
.size() != 2) {
313 *exception
= Var("Usage: login(username, password)");
317 if (!args
[0].is_string()) {
318 *exception
= Var("Username must be a string.");
321 std::string username
= args
[0].AsString();
323 if (!args
[1].is_string()) {
324 *exception
= Var("Password must be a string.");
327 std::string password
= args
[1].AsString();
329 instance_
->SubmitLoginInfo(username
, password
);
333 } // namespace remoting