Home | History | Annotate | Download | only in renderer
      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
     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 
     44 DomAutomationController::DomAutomationController(RenderFrame* render_frame)
     45     : RenderFrameObserver(render_frame), automation_id_(MSG_ROUTING_NONE) {}
     46 
     47 DomAutomationController::~DomAutomationController() {}
     48 
     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 
     59 void DomAutomationController::OnDestruct() {}
     60 
     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 
     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 
    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 
    118 bool DomAutomationController::SetAutomationId(int automation_id) {
    119   automation_id_ = automation_id;
    120   return true;
    121 }
    122 
    123 }  // namespace content
    124