Index: Source/bindings/v8/V8BlinkInJavaScript.cpp |
diff --git a/Source/bindings/v8/V8BlinkInJavaScript.cpp b/Source/bindings/v8/V8BlinkInJavaScript.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..988a0eb98396e1614301529b7910d5defda890ab |
--- /dev/null |
+++ b/Source/bindings/v8/V8BlinkInJavaScript.cpp |
@@ -0,0 +1,161 @@ |
+/* |
+ * Copyright (C) 2014 Google Inc. All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are |
+ * met: |
+ * |
+ * * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following disclaimer |
+ * in the documentation and/or other materials provided with the |
+ * distribution. |
+ * * Neither the name of Google Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived from |
+ * this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ */ |
+ |
+#include "config.h" |
+#include "bindings/v8/V8BlinkInJavaScript.h" |
+ |
+#include "BlinkInJavaScript.h" |
+#include "V8Window.h" |
+#include "bindings/v8/DOMWrapperWorld.h" |
+#include "bindings/v8/ScriptController.h" |
+#include "bindings/v8/V8Binding.h" |
+#include "bindings/v8/V8PerIsolateData.h" |
+#include "bindings/v8/V8ScriptRunner.h" |
+#include "bindings/v8/V8WindowShell.h" |
+#include "core/dom/Document.h" |
+#include "core/frame/Frame.h" |
+ |
+namespace WebCore { |
+ |
+static v8::Handle<v8::Value> compileBlinkInJavaScript(String className, v8::Isolate* isolate) |
+{ |
+ size_t index; |
+ // |kBlinkInJavaScriptSources| is defined in BlinkInJavaScript.h, which is auto-generated |
+ // by make_blink_in_javascript.py. |
+ for (index = 0; index < WTF_ARRAY_LENGTH(kBlinkInJavaScriptSources); index++) { |
+ if (className == kBlinkInJavaScriptSources[index].name) |
+ break; |
+ } |
+ RELEASE_ASSERT(index != WTF_ARRAY_LENGTH(kBlinkInJavaScriptSources)); |
+ |
+ String source(reinterpret_cast<const char*>(kBlinkInJavaScriptSources[index].source), kBlinkInJavaScriptSources[index].size); |
+ return V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, source), isolate); |
+} |
+ |
+static v8::Handle<v8::Value> convertWrapperForThisWorld(v8::Handle<v8::Value> wrapper, v8::Isolate* isolate) |
+{ |
+ // We don't need to convert primitive values. |
+ if (wrapper.IsEmpty() || !wrapper->IsObject()) |
+ return wrapper; |
+ |
+ // FIXME: We need to support conversion for Objects, Functions, Arrays etc. |
+ |
+ // FIXME: This implementation is a temporary hack just for window wrappers. |
+ // What we really need here is something like the following code: |
+ // |
+ // if (WrapperTypeInfo* typeInfo = WrapperTypeInfo::wrapperTypeInfo(wrapper)) { |
+ // return typeInfo->toV8(typeInfo->toNative(), v8::Handle<v8::Object>(), isolate); |
+ // } |
+ // |
+ // To make the above code workable, we need to store toNative() and toV8() to WrapperTypeInfo. |
+ // We also need to implement wrapperTypeInfo() which returns WrapperTypeInfo |
+ // only when |wrapper| is a valid DOM wrapper. |
+ if (V8Window::hasInstanceInAnyWorld(wrapper, isolate)) { |
+ v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(wrapper); |
+ DOMWindow* imp = V8Window::toNative(object); |
+ return toV8(imp, v8::Handle<v8::Object>(), isolate); |
+ } |
+ RELEASE_ASSERT(0); |
+} |
+ |
+v8::Handle<v8::Value> V8BlinkInJavaScript::runBlinkInJavaScript(String className, String functionName, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> argv[], v8::Isolate* isolate) |
+{ |
+ Document* document = currentDocument(); |
+ if (!document || !document->frame()) |
+ return v8::Handle<v8::Value>(); |
+ |
+ // Blink-in-JavaScript runs in the same security level as content scripts of Chrome extensions. |
+ // Specifically, Blink-in-JavaScript runs in a dedicated isolated world. |
+ RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(BlinkInJavaScriptIsolatedWorldId, DOMWrapperWorld::blinkInJavaScriptWorldExtensionGroup); |
+ V8WindowShell* isolatedWorldShell = document->frame()->script().windowShell(world.get()); |
+ if (!isolatedWorldShell->isContextInitialized()) |
+ return v8::Handle<v8::Value>(); |
+ |
+ v8::Handle<v8::Context> context = isolatedWorldShell->context(); |
+ v8::Handle<v8::Value> result; |
+ String exceptionMessage; |
+ bool exceptionCaught; |
+ { |
+ // Switch to the context of Blink-in-JavaScript's isolated world. |
+ v8::Context::Scope contextScope(context); |
+ |
+ v8::Handle<v8::Value> compiledClass = V8PerIsolateData::from(isolate)->compiledBlinkInJavaScript(className); |
+ if (compiledClass.IsEmpty()) { |
+ v8::Handle<v8::Value> installedClasses = V8PerIsolateData::from(isolate)->compiledBlinkInJavaScript("BlinkInJavaScriptController"); |
+ if (installedClasses.IsEmpty()) { |
+ installedClasses = compileBlinkInJavaScript("BlinkInJavaScriptController", isolate); |
+ V8PerIsolateData::from(isolate)->setCompiledBlinkInJavaScript("BlinkInJavaScriptController", installedClasses); |
+ } |
+ RELEASE_ASSERT(!installedClasses.IsEmpty()); |
+ RELEASE_ASSERT(installedClasses->IsObject()); |
+ |
+ compileBlinkInJavaScript(className, isolate); |
+ |
+ compiledClass = v8::Handle<v8::Object>::Cast(installedClasses)->Get(v8String(isolate, className)); |
+ RELEASE_ASSERT(!compiledClass.IsEmpty()); |
+ RELEASE_ASSERT(compiledClass->IsObject()); |
+ V8PerIsolateData::from(isolate)->setCompiledBlinkInJavaScript(className, compiledClass); |
+ } |
+ |
+ v8::Handle<v8::Value> function = v8::Handle<v8::Object>::Cast(compiledClass)->Get(v8String(isolate, functionName)); |
+ RELEASE_ASSERT(!function.IsEmpty()); |
+ RELEASE_ASSERT(function->IsFunction()); |
+ |
+ // We have to convert argument wrappers to wrappers in Blink-in-JavaScript's isolated world. |
+ receiver = convertWrapperForThisWorld(receiver, isolate); |
+ for (int i = 0; i < argc; i++) { |
+ argv[i] = convertWrapperForThisWorld(argv[i], isolate); |
+ } |
+ |
+ { |
+ v8::TryCatch block; |
+ result = V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(function), document, receiver, argc, argv, isolate); |
+ exceptionCaught = block.HasCaught(); |
+ if (exceptionCaught) { |
+ if (!block.Message().IsEmpty()) |
+ exceptionMessage = toCoreString(block.Message()->Get()); |
+ } |
+ } |
+ |
+ } |
+ |
+ // We have to convert an exception thrown in Blink-in-JavaScript's isolated world |
+ // to an exception in the original world. |
+ if (exceptionCaught) { |
+ // FIXME: Support other error types. We need to add V8 APIs to extract types from Exception objects. |
+ return v8::Exception::Error(v8String(isolate, exceptionMessage)); |
+ } |
+ |
+ // We have to convert a return wrapper created in Blink-in-JavaScript's isolated world |
+ // to a wrapper in the original world. |
+ return convertWrapperForThisWorld(result, isolate); |
+} |
+ |
+} // namespace WebCore |