// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/renderer/dom_automation_controller.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/json/json_string_value_serializer.h" #include "base/metrics/histogram.h" #include "base/metrics/statistics_recorder.h" #include "base/strings/string_util.h" #include "content/common/child_process_messages.h" #include "content/common/view_messages.h" using webkit_glue::CppArgumentList; using webkit_glue::CppVariant; namespace content { DomAutomationController::DomAutomationController() : sender_(NULL), routing_id_(MSG_ROUTING_NONE), automation_id_(MSG_ROUTING_NONE) { BindCallback("send", base::Bind(&DomAutomationController::Send, base::Unretained(this))); BindCallback("setAutomationId", base::Bind(&DomAutomationController::SetAutomationId, base::Unretained(this))); BindCallback("sendJSON", base::Bind(&DomAutomationController::SendJSON, base::Unretained(this))); BindCallback("sendWithId", base::Bind(&DomAutomationController::SendWithId, base::Unretained(this))); } void DomAutomationController::Send(const CppArgumentList& args, CppVariant* result) { if (args.size() != 1) { result->SetNull(); return; } if (automation_id_ == MSG_ROUTING_NONE) { result->SetNull(); return; } if (!sender_) { NOTREACHED(); result->SetNull(); return; } std::string json; JSONStringValueSerializer serializer(&json); scoped_ptr value; // Warning: note that JSON officially requires the root-level object to be // an object (e.g. {foo:3}) or an array, while here we're serializing // strings, bools, etc. to "JSON". This only works because (a) the JSON // writer is lenient, and (b) on the receiving side we wrap the JSON string // in square brackets, converting it to an array, then parsing it and // grabbing the 0th element to get the value out. switch (args[0].type) { case NPVariantType_String: { value.reset(new base::StringValue(args[0].ToString())); break; } case NPVariantType_Bool: { value.reset(new base::FundamentalValue(args[0].ToBoolean())); break; } case NPVariantType_Int32: { value.reset(new base::FundamentalValue(args[0].ToInt32())); break; } case NPVariantType_Double: { // The value that is sent back is an integer while it is treated // as a double in this binding. The reason being that KJS treats // any number value as a double. Refer for more details, // chrome/third_party/webkit/src/JavaScriptCore/bindings/c/c_utility.cpp value.reset(new base::FundamentalValue(args[0].ToInt32())); break; } default: { result->SetNull(); return; } } if (!serializer.Serialize(*value)) { result->SetNull(); return; } bool succeeded = sender_->Send( new ViewHostMsg_DomOperationResponse(routing_id_, json, automation_id_)); result->Set(succeeded); automation_id_ = MSG_ROUTING_NONE; } void DomAutomationController::SendJSON(const CppArgumentList& args, CppVariant* result) { if (args.size() != 1) { result->SetNull(); return; } if (automation_id_ == MSG_ROUTING_NONE) { result->SetNull(); return; } if (!sender_) { NOTREACHED(); result->SetNull(); return; } if (args[0].type != NPVariantType_String) { result->SetNull(); return; } std::string json = args[0].ToString(); result->Set(sender_->Send( new ViewHostMsg_DomOperationResponse(routing_id_, json, automation_id_))); automation_id_ = MSG_ROUTING_NONE; } void DomAutomationController::SendWithId(const CppArgumentList& args, CppVariant* result) { if (args.size() != 2) { result->SetNull(); return; } if (!sender_) { NOTREACHED(); result->SetNull(); return; } if (!args[0].isNumber() || args[1].type != NPVariantType_String) { result->SetNull(); return; } result->Set(sender_->Send( new ViewHostMsg_DomOperationResponse(routing_id_, args[1].ToString(), args[0].ToInt32()))); } void DomAutomationController::SetAutomationId( const CppArgumentList& args, CppVariant* result) { if (args.size() != 1) { result->SetNull(); return; } // The check here is for NumberType and not Int32 as // KJS::JSType only defines a NumberType (no Int32) if (!args[0].isNumber()) { result->SetNull(); return; } automation_id_ = args[0].ToInt32(); result->Set(true); } } // namespace content