Index: headless/lib/web_frame_impl.cc |
diff --git a/headless/lib/web_frame_impl.cc b/headless/lib/web_frame_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..48f38891b8bb01b1d1766569b71bb3ee2c2e467f |
--- /dev/null |
+++ b/headless/lib/web_frame_impl.cc |
@@ -0,0 +1,134 @@ |
+// Copyright 2015 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 "headless/lib/web_frame_impl.h" |
+ |
+#include "headless/public/web_document.h" |
+#include "third_party/WebKit/public/web/WebDocument.h" |
+#include "third_party/WebKit/public/web/WebFrame.h" |
+#include "third_party/WebKit/public/web/WebLocalFrame.h" |
+#include "third_party/WebKit/public/web/WebScriptSource.h" |
+#include "third_party/WebKit/public/web/WebScriptExecutionCallback.h" |
+#include "base/values.h" |
+#include "v8/include/v8.h" |
+ |
+namespace headless { |
+ |
+WebFrameImpl::WebFrameImpl(blink::WebLocalFrame* web_frame) |
+ : web_frame_(web_frame) {} |
+ |
+WebFrameImpl::~WebFrameImpl() {} |
+ |
+WebDocument WebFrameImpl::document() { |
+ return WebDocument(web_frame_->document()); |
+} |
+ |
+namespace { |
+ |
+blink::WebScriptSource StringToWebScript(const std::string& code) { |
+ return blink::WebScriptSource( |
+ blink::WebString::fromUTF8(code.c_str(), code.size())); |
+} |
+ |
+} |
+ |
+class WebFrameImpl::JavaScriptExecutionCallback : |
+ public blink::WebScriptExecutionCallback |
+{ |
+ public: |
+ JavaScriptExecutionCallback( |
+ WebFrameImpl* web_frame, |
+ const WebFrame::ScriptExecutionCallback callback) |
+ : web_frame_(web_frame) |
+ , callback_(callback) {} |
+ ~JavaScriptExecutionCallback() override {}; |
+ |
+ void completed(const blink::WebVector<v8::Local<v8::Value>>& values) { |
+ std::vector<scoped_ptr<base::Value>> converted_values; |
+ for (const auto& value : values) { |
+ converted_values.push_back(web_frame_->ConvertV8ValueToBase(value)); |
+ } |
+ callback_.Run(converted_values); |
+ } |
+ private: |
+ WebFrameImpl* web_frame_; |
+ ScriptExecutionCallback callback_; |
+}; |
+ |
+namespace { |
+ |
+std::string ConvertV8StringToStd(v8::Local<v8::String> string) |
+{ |
+ std::vector<char> buffer; |
+ buffer.resize(string->Utf8Length()); |
+ string->WriteUtf8(buffer.data(), buffer.size()); |
+ return std::string(buffer.data(), buffer.size()); |
+} |
+ |
+} |
+ |
+scoped_ptr<base::Value> WebFrameImpl::ConvertV8ValueToBase( |
+ const v8::Local<v8::Value>& value) { |
+ v8::Local<v8::Context> context = web_frame_->mainWorldScriptContext(); |
+ if (value->IsBoolean()) { |
+ v8::Local<v8::Boolean> boolean = value->ToBoolean(context).ToLocalChecked(); |
+ return make_scoped_ptr(new base::FundamentalValue(boolean->Value())); |
+ } else if (value->IsNumber()) { |
+ v8::Local<v8::Number> number = value->ToNumber(context).ToLocalChecked(); |
+ return make_scoped_ptr(new base::FundamentalValue(number->Value())); |
+ } else if (value->IsString()) { |
+ v8::Local<v8::String> string = value->ToString(context).ToLocalChecked(); |
+ return make_scoped_ptr(new base::StringValue(ConvertV8StringToStd(string))); |
+ } else if (value->IsArray()) { |
+ v8::Local<v8::Object> array = value->ToObject(context).ToLocalChecked(); |
+ scoped_ptr<base::ListValue> list = make_scoped_ptr( |
+ new base::ListValue()); |
+ size_t index = 0; |
+ |
+ // TODO(altimin): Handle exceptions properly. |
+ while (array->Has(context, index).FromJust()) { |
+ list->Append(ConvertV8ValueToBase(array->Get(context, index).ToLocalChecked())); |
+ ++index; |
+ } |
+ return scoped_ptr<base::Value>(std::move(list)); |
+ } else if (value->IsObject()) { |
+ v8::Local<v8::Object> object = value->ToObject(context).ToLocalChecked(); |
+ v8::Local<v8::Array> property_names = |
+ object->GetPropertyNames(context).ToLocalChecked();; |
+ scoped_ptr<base::DictionaryValue> dictionary = make_scoped_ptr( |
+ new base::DictionaryValue()); |
+ |
+ for (size_t i = 0; i < property_names->Length(); ++i) { |
+ v8::Local<v8::Value> property_name = |
+ property_names->Get(context, i).ToLocalChecked(); |
+ if (!property_name->IsString()) { |
+ continue; |
+ } |
+ v8::Local<v8::String> property_name_as_string = |
+ property_name->ToString(context).ToLocalChecked(); |
+ dictionary->Set(ConvertV8StringToStd(property_name_as_string), |
+ ConvertV8ValueToBase(object->Get(property_name))); |
+ } |
+ |
+ return scoped_ptr<base::Value>(std::move(dictionary)); |
+ } |
+ return nullptr; |
+} |
+ |
+ |
+void WebFrameImpl::ExecuteScript( |
+ const std::string& source_code) { |
+ web_frame_->executeScript(StringToWebScript(source_code)); |
+} |
+ |
+void WebFrameImpl::ExecuteScriptAndReturnValue( |
+ const std::string& source_code, |
+ const ScriptExecutionCallback& callback) { |
+ web_frame_->requestExecuteScriptAndReturnValue( |
+ StringToWebScript(source_code), |
+ /* user_gesture */ false, |
+ new JavaScriptExecutionCallback(this, callback)); |
+} |
+ |
+} // namespace headless |