• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/json/json_string_value_serializer.h"
8 #include "base/strings/string_util.h"
9 #include "content/common/child_process_messages.h"
10 #include "content/common/frame_messages.h"
11 #include "content/renderer/render_view_impl.h"
12 #include "content/renderer/v8_value_converter_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"
17 
18 namespace content {
19 
20 gin::WrapperInfo DomAutomationController::kWrapperInfo = {
21     gin::kEmbedderNativeGin};
22 
23 // static
Install(RenderFrame * render_frame,blink::WebFrame * frame)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;
31 
32   v8::Context::Scope context_scope(context);
33 
34   gin::Handle<DomAutomationController> controller =
35       gin::CreateHandle(isolate, new DomAutomationController(render_frame));
36   if (controller.IsEmpty())
37     return;
38 
39   v8::Handle<v8::Object> global = context->Global();
40   global->Set(gin::StringToV8(isolate, "domAutomationController"),
41               controller.ToV8());
42 }
43 
DomAutomationController(RenderFrame * render_frame)44 DomAutomationController::DomAutomationController(RenderFrame* render_frame)
45     : RenderFrameObserver(render_frame), automation_id_(MSG_ROUTING_NONE) {}
46 
~DomAutomationController()47 DomAutomationController::~DomAutomationController() {}
48 
GetObjectTemplateBuilder(v8::Isolate * isolate)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);
57 }
58 
OnDestruct()59 void DomAutomationController::OnDestruct() {}
60 
SendMsg(const gin::Arguments & args)61 bool DomAutomationController::SendMsg(const gin::Arguments& args) {
62   if (!render_frame())
63     return false;
64 
65   if (automation_id_ == MSG_ROUTING_NONE)
66     return false;
67 
68   std::string json;
69   JSONStringValueSerializer serializer(&json);
70   scoped_ptr<base::Value> value;
71 
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;
85   }
86 
87   if (!serializer.Serialize(*value))
88     return false;
89 
90   bool succeeded = Send(new FrameHostMsg_DomOperationResponse(
91       routing_id(), json, automation_id_));
92 
93   automation_id_ = MSG_ROUTING_NONE;
94   return succeeded;
95 }
96 
SendJSON(const std::string & json)97 bool DomAutomationController::SendJSON(const std::string& json) {
98   if (!render_frame())
99     return false;
100 
101   if (automation_id_ == MSG_ROUTING_NONE)
102     return false;
103   bool result = Send(new FrameHostMsg_DomOperationResponse(
104       routing_id(), json, automation_id_));
105 
106   automation_id_ = MSG_ROUTING_NONE;
107   return result;
108 }
109 
SendWithId(int automation_id,const std::string & str)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));
116 }
117 
SetAutomationId(int automation_id)118 bool DomAutomationController::SetAutomationId(int automation_id) {
119   automation_id_ = automation_id;
120   return true;
121 }
122 
123 }  // namespace content
124