- add sources.
[platform/framework/web/crosswalk.git] / src / content / renderer / dom_automation_controller.cc
1 // Copyright (c) 2012 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 #include "content/renderer/dom_automation_controller.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/json/json_string_value_serializer.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/statistics_recorder.h"
12 #include "base/strings/string_util.h"
13 #include "content/common/child_process_messages.h"
14 #include "content/common/view_messages.h"
15
16 using webkit_glue::CppArgumentList;
17 using webkit_glue::CppVariant;
18
19 namespace content {
20
21 DomAutomationController::DomAutomationController()
22     : sender_(NULL),
23       routing_id_(MSG_ROUTING_NONE),
24       automation_id_(MSG_ROUTING_NONE) {
25   BindCallback("send", base::Bind(&DomAutomationController::Send,
26                                   base::Unretained(this)));
27   BindCallback("setAutomationId",
28                base::Bind(&DomAutomationController::SetAutomationId,
29                           base::Unretained(this)));
30   BindCallback("sendJSON", base::Bind(&DomAutomationController::SendJSON,
31                                       base::Unretained(this)));
32   BindCallback("sendWithId", base::Bind(&DomAutomationController::SendWithId,
33                                         base::Unretained(this)));
34 }
35
36 void DomAutomationController::Send(const CppArgumentList& args,
37                                    CppVariant* result) {
38   if (args.size() != 1) {
39     result->SetNull();
40     return;
41   }
42
43   if (automation_id_ == MSG_ROUTING_NONE) {
44     result->SetNull();
45     return;
46   }
47
48   if (!sender_) {
49     NOTREACHED();
50     result->SetNull();
51     return;
52   }
53
54   std::string json;
55   JSONStringValueSerializer serializer(&json);
56   scoped_ptr<base::Value> value;
57
58   // Warning: note that JSON officially requires the root-level object to be
59   // an object (e.g. {foo:3}) or an array, while here we're serializing
60   // strings, bools, etc. to "JSON".  This only works because (a) the JSON
61   // writer is lenient, and (b) on the receiving side we wrap the JSON string
62   // in square brackets, converting it to an array, then parsing it and
63   // grabbing the 0th element to get the value out.
64   switch (args[0].type) {
65     case NPVariantType_String: {
66       value.reset(new base::StringValue(args[0].ToString()));
67       break;
68     }
69     case NPVariantType_Bool: {
70       value.reset(new base::FundamentalValue(args[0].ToBoolean()));
71       break;
72     }
73     case NPVariantType_Int32: {
74       value.reset(new base::FundamentalValue(args[0].ToInt32()));
75       break;
76     }
77     case NPVariantType_Double: {
78       // The value that is sent back is an integer while it is treated
79       // as a double in this binding. The reason being that KJS treats
80       // any number value as a double. Refer for more details,
81       // chrome/third_party/webkit/src/JavaScriptCore/bindings/c/c_utility.cpp
82       value.reset(new base::FundamentalValue(args[0].ToInt32()));
83       break;
84     }
85     default: {
86       result->SetNull();
87       return;
88     }
89   }
90
91   if (!serializer.Serialize(*value)) {
92     result->SetNull();
93     return;
94   }
95
96   bool succeeded = sender_->Send(
97       new ViewHostMsg_DomOperationResponse(routing_id_, json, automation_id_));
98   result->Set(succeeded);
99
100   automation_id_ = MSG_ROUTING_NONE;
101 }
102
103 void DomAutomationController::SendJSON(const CppArgumentList& args,
104                                        CppVariant* result) {
105   if (args.size() != 1) {
106     result->SetNull();
107     return;
108   }
109
110   if (automation_id_ == MSG_ROUTING_NONE) {
111     result->SetNull();
112     return;
113   }
114
115   if (!sender_) {
116     NOTREACHED();
117     result->SetNull();
118     return;
119   }
120
121   if (args[0].type != NPVariantType_String) {
122     result->SetNull();
123     return;
124   }
125
126   std::string json = args[0].ToString();
127   result->Set(sender_->Send(
128       new ViewHostMsg_DomOperationResponse(routing_id_, json, automation_id_)));
129
130   automation_id_ = MSG_ROUTING_NONE;
131 }
132
133 void DomAutomationController::SendWithId(const CppArgumentList& args,
134                                          CppVariant* result) {
135   if (args.size() != 2) {
136     result->SetNull();
137     return;
138   }
139
140   if (!sender_) {
141     NOTREACHED();
142     result->SetNull();
143     return;
144   }
145
146   if (!args[0].isNumber() || args[1].type != NPVariantType_String) {
147     result->SetNull();
148     return;
149   }
150
151   result->Set(sender_->Send(
152       new ViewHostMsg_DomOperationResponse(routing_id_, args[1].ToString(),
153                                            args[0].ToInt32())));
154 }
155
156 void DomAutomationController::SetAutomationId(
157     const CppArgumentList& args, CppVariant* result) {
158   if (args.size() != 1) {
159     result->SetNull();
160     return;
161   }
162
163   // The check here is for NumberType and not Int32 as
164   // KJS::JSType only defines a NumberType (no Int32)
165   if (!args[0].isNumber()) {
166     result->SetNull();
167     return;
168   }
169
170   automation_id_ = args[0].ToInt32();
171   result->Set(true);
172 }
173
174 }  // namespace content