Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / dom_automation_controller.cc
blobb002b6c136beab2ce301047f0d0c5eb724fc1d6f
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.
5 #include "content/renderer/dom_automation_controller.h"
7 #include "base/json/json_string_value_serializer.h"
8 #include "base/strings/string_util.h"
9 #include "content/child/v8_value_converter_impl.h"
10 #include "content/common/child_process_messages.h"
11 #include "content/common/frame_messages.h"
12 #include "content/renderer/render_view_impl.h"
13 #include "gin/handle.h"
14 #include "gin/object_template_builder.h"
15 #include "third_party/WebKit/public/web/WebFrame.h"
16 #include "third_party/WebKit/public/web/WebKit.h"
18 namespace content {
20 gin::WrapperInfo DomAutomationController::kWrapperInfo = {
21 gin::kEmbedderNativeGin};
23 // static
24 void DomAutomationController::Install(RenderFrame* render_frame,
25 blink::WebFrame* frame) {
26 v8::Isolate* isolate = blink::mainThreadIsolate();
27 v8::HandleScope handle_scope(isolate);
28 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
29 if (context.IsEmpty())
30 return;
32 v8::Context::Scope context_scope(context);
34 gin::Handle<DomAutomationController> controller =
35 gin::CreateHandle(isolate, new DomAutomationController(render_frame));
36 if (controller.IsEmpty())
37 return;
39 v8::Handle<v8::Object> global = context->Global();
40 global->Set(gin::StringToV8(isolate, "domAutomationController"),
41 controller.ToV8());
44 DomAutomationController::DomAutomationController(RenderFrame* render_frame)
45 : RenderFrameObserver(render_frame), automation_id_(MSG_ROUTING_NONE) {}
47 DomAutomationController::~DomAutomationController() {}
49 gin::ObjectTemplateBuilder DomAutomationController::GetObjectTemplateBuilder(
50 v8::Isolate* isolate) {
51 return gin::Wrappable<DomAutomationController>::GetObjectTemplateBuilder(
52 isolate)
53 .SetMethod("send", &DomAutomationController::SendMsg)
54 .SetMethod("setAutomationId", &DomAutomationController::SetAutomationId)
55 .SetMethod("sendJSON", &DomAutomationController::SendJSON)
56 .SetMethod("sendWithId", &DomAutomationController::SendWithId);
59 void DomAutomationController::OnDestruct() {}
61 bool DomAutomationController::SendMsg(const gin::Arguments& args) {
62 if (!render_frame())
63 return false;
65 if (automation_id_ == MSG_ROUTING_NONE)
66 return false;
68 std::string json;
69 JSONStringValueSerializer serializer(&json);
70 scoped_ptr<base::Value> value;
72 // Warning: note that JSON officially requires the root-level object to be
73 // an object (e.g. {foo:3}) or an array, while here we're serializing
74 // strings, bools, etc. to "JSON". This only works because (a) the JSON
75 // writer is lenient, and (b) on the receiving side we wrap the JSON string
76 // in square brackets, converting it to an array, then parsing it and
77 // grabbing the 0th element to get the value out.
78 if (args.PeekNext()->IsString() || args.PeekNext()->IsBoolean() ||
79 args.PeekNext()->IsNumber()) {
80 V8ValueConverterImpl conv;
81 value.reset(
82 conv.FromV8Value(args.PeekNext(), args.isolate()->GetCurrentContext()));
83 } else {
84 return false;
87 if (!serializer.Serialize(*value))
88 return false;
90 bool succeeded = Send(new FrameHostMsg_DomOperationResponse(
91 routing_id(), json, automation_id_));
93 automation_id_ = MSG_ROUTING_NONE;
94 return succeeded;
97 bool DomAutomationController::SendJSON(const std::string& json) {
98 if (!render_frame())
99 return false;
101 if (automation_id_ == MSG_ROUTING_NONE)
102 return false;
103 bool result = Send(new FrameHostMsg_DomOperationResponse(
104 routing_id(), json, automation_id_));
106 automation_id_ = MSG_ROUTING_NONE;
107 return result;
110 bool DomAutomationController::SendWithId(int automation_id,
111 const std::string& str) {
112 if (!render_frame())
113 return false;
114 return Send(
115 new FrameHostMsg_DomOperationResponse(routing_id(), str, automation_id));
118 bool DomAutomationController::SetAutomationId(int automation_id) {
119 automation_id_ = automation_id;
120 return true;
123 } // namespace content