Add debug logging to Chromoting client UI.
[chromium-blink-merge.git] / remoting / client / plugin / chromoting_scriptable_object.cc
blob978055d659279ecc025d0942428d0cdaad478947
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"
12 using pp::Var;
14 namespace remoting {
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.
37 // Connection status.
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.");
74 return false;
77 PropertyNameMap::const_iterator iter = property_names_.find(name.AsString());
78 if (iter == property_names_.end()) {
79 return false;
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.");
93 return false;
96 PropertyNameMap::const_iterator iter = property_names_.find(name.AsString());
97 if (iter == property_names_.end()) {
98 return false;
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.");
109 return Var();
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,
126 Var* exception) {
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,
133 const Var& value,
134 Var* exception) {
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.");
138 return;
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) {
149 *exception =
150 Var("Cannot set property " + property_name + " on this object.");
151 return;
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,
161 Var* exception) {
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,
210 Var attribute) {
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() {
222 Var exception;
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() {
239 Var exception;
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() {
256 Var exception;
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,
273 Var* exception) {
274 if (args.size() != 3) {
275 *exception = Var("Usage: connect(username, host_jid, auth_token)");
276 return Var();
279 ClientConfig config;
281 if (!args[0].is_string()) {
282 *exception = Var("The username must be a string.");
283 return Var();
285 config.username = args[0].AsString();
287 if (!args[1].is_string()) {
288 *exception = Var("The host_jid must be a string.");
289 return Var();
291 config.host_jid = args[1].AsString();
293 if (!args[2].is_string()) {
294 *exception = Var("The auth_token must be a string.");
295 return Var();
297 config.auth_token = args[2].AsString();
299 instance_->Connect(config);
301 return Var();
304 Var ChromotingScriptableObject::DoDisconnect(const std::vector<Var>& args,
305 Var* exception) {
306 instance_->Disconnect();
307 return Var();
310 Var ChromotingScriptableObject::DoSubmitLogin(const std::vector<Var>& args,
311 Var* exception) {
312 if (args.size() != 2) {
313 *exception = Var("Usage: login(username, password)");
314 return Var();
317 if (!args[0].is_string()) {
318 *exception = Var("Username must be a string.");
319 return Var();
321 std::string username = args[0].AsString();
323 if (!args[1].is_string()) {
324 *exception = Var("Password must be a string.");
325 return Var();
327 std::string password = args[1].AsString();
329 instance_->SubmitLoginInfo(username, password);
330 return Var();
333 } // namespace remoting