15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/dom_automation_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/child_process_messages.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/common/frame_messages.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/render_view_impl.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/v8_value_converter_impl.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/handle.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/object_template_builder.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebKit.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::WrapperInfo DomAutomationController::kWrapperInfo = {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gin::kEmbedderNativeGin};
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void DomAutomationController::Install(RenderFrame* render_frame,
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      blink::WebFrame* frame) {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Isolate* isolate = blink::mainThreadIsolate();
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::HandleScope handle_scope(isolate);
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (context.IsEmpty())
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gin::Handle<DomAutomationController> controller =
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      gin::CreateHandle(isolate, new DomAutomationController(render_frame));
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (controller.IsEmpty())
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Handle<v8::Object> global = context->Global();
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  global->Set(gin::StringToV8(isolate, "domAutomationController"),
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              controller.ToV8());
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)DomAutomationController::DomAutomationController(RenderFrame* render_frame)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : RenderFrameObserver(render_frame), automation_id_(MSG_ROUTING_NONE) {}
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DomAutomationController::~DomAutomationController() {}
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::ObjectTemplateBuilder DomAutomationController::GetObjectTemplateBuilder(
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Isolate* isolate) {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return gin::Wrappable<DomAutomationController>::GetObjectTemplateBuilder(
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             isolate)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("send", &DomAutomationController::SendMsg)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("setAutomationId", &DomAutomationController::SetAutomationId)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("sendJSON", &DomAutomationController::SendJSON)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("sendWithId", &DomAutomationController::SendWithId);
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomAutomationController::OnDestruct() {}
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DomAutomationController::SendMsg(const gin::Arguments& args) {
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!render_frame())
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (automation_id_ == MSG_ROUTING_NONE)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string json;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JSONStringValueSerializer serializer(&json);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> value;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Warning: note that JSON officially requires the root-level object to be
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an object (e.g. {foo:3}) or an array, while here we're serializing
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // strings, bools, etc. to "JSON".  This only works because (a) the JSON
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // writer is lenient, and (b) on the receiving side we wrap the JSON string
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in square brackets, converting it to an array, then parsing it and
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // grabbing the 0th element to get the value out.
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (args.PeekNext()->IsString() || args.PeekNext()->IsBoolean() ||
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      args.PeekNext()->IsNumber()) {
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    V8ValueConverterImpl conv;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    value.reset(
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        conv.FromV8Value(args.PeekNext(), args.isolate()->GetCurrentContext()));
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!serializer.Serialize(*value))
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool succeeded = Send(new FrameHostMsg_DomOperationResponse(
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      routing_id(), json, automation_id_));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  automation_id_ = MSG_ROUTING_NONE;
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return succeeded;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DomAutomationController::SendJSON(const std::string& json) {
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!render_frame())
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (automation_id_ == MSG_ROUTING_NONE)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool result = Send(new FrameHostMsg_DomOperationResponse(
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      routing_id(), json, automation_id_));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  automation_id_ = MSG_ROUTING_NONE;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DomAutomationController::SendWithId(int automation_id,
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         const std::string& str) {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!render_frame())
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return Send(
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new FrameHostMsg_DomOperationResponse(routing_id(), str, automation_id));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DomAutomationController::SetAutomationId(int automation_id) {
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  automation_id_ = automation_id;
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
124