OLD | NEW |
(Empty) | |
| 1 // Copyright 2012, Google Inc. |
| 2 // All rights reserved. |
| 3 // |
| 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are |
| 6 // met: |
| 7 // |
| 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above |
| 11 // copyright notice, this list of conditions and the following disclaimer |
| 12 // in the documentation and/or other materials provided with the |
| 13 // distribution. |
| 14 // * Neither the name of Google Inc. nor the names of its |
| 15 // contributors may be used to endorse or promote products derived from |
| 16 // this software without specific prior written permission. |
| 17 // |
| 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 |
| 30 #include "config.h" |
| 31 #include "bindings/core/dart/DartNativeUtilities.h" |
| 32 |
| 33 #include "bindings/core/dart/DartController.h" |
| 34 #include "bindings/core/dart/DartDOMData.h" |
| 35 #include "bindings/core/dart/DartDOMWrapper.h" |
| 36 #include "bindings/core/dart/DartJsInterop.h" |
| 37 #include "bindings/core/dart/DartUtilities.h" |
| 38 #include "bindings/core/dart/V8Converter.h" |
| 39 #include "bindings/core/v8/ScriptController.h" |
| 40 #include "bindings/core/v8/V8Document.h" |
| 41 #include "bindings/core/v8/npruntime_impl.h" |
| 42 #include "core/dom/Document.h" |
| 43 #include "core/dom/ExecutionContext.h" |
| 44 #include "core/dom/ExecutionContextTask.h" |
| 45 #include "core/dom/custom/CustomElementProcessingStack.h" |
| 46 #include "core/dom/custom/CustomElementRegistrationContext.h" |
| 47 #include "core/frame/LocalFrame.h" |
| 48 #include "core/html/HTMLElement.h" |
| 49 #include "platform/RuntimeEnabledFeatures.h" |
| 50 |
| 51 #include "wtf/HashMap.h" |
| 52 #include "wtf/StdLibExtras.h" |
| 53 #include "wtf/text/CString.h" |
| 54 #include "wtf/text/StringHash.h" |
| 55 #include <bindings/npruntime.h> |
| 56 #include <dart_api.h> |
| 57 |
| 58 namespace blink { |
| 59 |
| 60 namespace DartNativeUtilitiesInternal { |
| 61 |
| 62 /** |
| 63 * Gadget for testing. |
| 64 * |
| 65 * With DART_FORWARDING_PRINT environment variable set, it invokes dartPrint |
| 66 * JavaScript function on global object to communicate to Dart test framework. |
| 67 */ |
| 68 static void forwardingPrint(Dart_NativeArguments args) |
| 69 { |
| 70 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 71 v8::HandleScope v8Scope(v8Isolate); |
| 72 ExecutionContext* scriptExecutionContext = DartUtilities::scriptExecutionCon
text(); |
| 73 ASSERT(scriptExecutionContext); |
| 74 |
| 75 DartController* dartController = DartController::retrieve(scriptExecutionCon
text); |
| 76 if (!dartController) |
| 77 return; |
| 78 LocalFrame* frame = dartController->frame(); |
| 79 v8::Handle<v8::Context> v8Context = toV8Context(frame, DOMWrapperWorld::main
World()); |
| 80 v8::Context::Scope scope(v8Context); |
| 81 v8::TryCatch tryCatch; |
| 82 |
| 83 v8::Handle<v8::Value> function = v8Context->Global()->Get(v8::String::NewFro
mUtf8(v8Isolate, "dartPrint")); |
| 84 if (function.IsEmpty() || !function->IsFunction()) |
| 85 return; |
| 86 |
| 87 v8::Handle<v8::Value> message = V8Converter::stringToV8(Dart_GetNativeArgume
nt(args, 0)); |
| 88 function.As<v8::Function>()->Call(v8Context->Global(), 1, &message); |
| 89 } |
| 90 |
| 91 static void getNewIsolateId(Dart_NativeArguments args) |
| 92 { |
| 93 static int isolateId = 0; |
| 94 Dart_SetReturnValue(args, DartUtilities::intToDart(isolateId++)); |
| 95 } |
| 96 |
| 97 // Use the first argument of a function as the receiver (this) of the native |
| 98 // C++ implementation of a few special DOM calls (createElement, registerElement
, |
| 99 // etc.). |
| 100 Document * getBlinkJsoAsDocument(Dart_NativeArguments args, DartDOMData* domData
) |
| 101 { |
| 102 Dart_Handle exception = 0; |
| 103 { |
| 104 v8::Local<v8::Value> value = JsInterop::fromDart(domData, Dart_GetNative
Argument(args, 0), exception); |
| 105 if (exception) |
| 106 goto fail; |
| 107 |
| 108 ASSERT(value->IsObject()); |
| 109 |
| 110 v8::Handle<v8::Object> object = value.As<v8::Object>(); |
| 111 v8::Isolate* isolate = object->CreationContext()->GetIsolate(); |
| 112 if (V8Document::hasInstance(object, isolate)) { |
| 113 // FIXME(jacobr): there has to be a faster way to perform this check
. |
| 114 if (!object->CreationContext()->Global()->StrictEquals(DartUtilities
::currentV8Context()->Global())) { |
| 115 // The object is from a different context so do not convert. |
| 116 return 0; |
| 117 } |
| 118 |
| 119 // TODO(terry): Should probably check that this really is a Document
. |
| 120 Document* doc = V8Document::toImpl(object); |
| 121 return doc; |
| 122 } |
| 123 } |
| 124 |
| 125 fail: |
| 126 Dart_ThrowException(exception); |
| 127 return 0; |
| 128 } |
| 129 |
| 130 // dart:html (Dartium only) hookups up the Custom element using JsInterop when |
| 131 // JS createCallback is invoked this function is called to allocate the custom |
| 132 // Dart class (user's class) setup the blink_jsObject to point to the JS custom |
| 133 // element just created and call the custom Dart class created constructor. |
| 134 void customConstructorCreate(Dart_NativeArguments args) |
| 135 { |
| 136 Dart_Handle exception = 0; |
| 137 { |
| 138 DartDOMData* domData = DartDOMData::current(); |
| 139 |
| 140 Dart_Handle dartElementType = Dart_GetNativeArgument(args, 0); |
| 141 ASSERT(Dart_IsType(dartElementType)); |
| 142 |
| 143 Dart_Handle blinkJsObject = Dart_GetNativeArgument(args, 1); |
| 144 |
| 145 Dart_Handle newObject = Dart_Allocate(dartElementType); |
| 146 ASSERT(!Dart_IsError(newObject)); |
| 147 |
| 148 Dart_Handle jsObject = Dart_SetField(newObject, Dart_NewStringFromCStrin
g("blink_jsObject"), blinkJsObject); |
| 149 if (Dart_IsError(jsObject)) { |
| 150 DartUtilities::reportProblem(domData->scriptExecutionContext(), jsOb
ject); |
| 151 goto fail; |
| 152 } |
| 153 |
| 154 newObject = Dart_InvokeConstructor(newObject, Dart_NewStringFromCString(
"created"), 0, 0); |
| 155 if (Dart_IsError(newObject)) { |
| 156 DartUtilities::reportProblem(domData->scriptExecutionContext(), newO
bject); |
| 157 goto fail; |
| 158 } |
| 159 |
| 160 Dart_SetReturnValue(args, newObject); |
| 161 return; |
| 162 } |
| 163 |
| 164 fail: |
| 165 Dart_ThrowException(exception); |
| 166 ASSERT_NOT_REACHED(); |
| 167 } |
| 168 |
| 169 void initializeCustomElement(Dart_NativeArguments args) |
| 170 { |
| 171 ASSERT_NOT_REACHED(); |
| 172 } |
| 173 |
| 174 void spawnDomUri(Dart_NativeArguments args) |
| 175 { |
| 176 Dart_Handle exception = 0; |
| 177 { |
| 178 ExecutionContext* scriptExecutionContext = DartUtilities::scriptExecutio
nContext(); |
| 179 ASSERT(scriptExecutionContext); |
| 180 DartController* dartController = DartController::retrieve(scriptExecutio
nContext); |
| 181 if (!dartController) |
| 182 return; |
| 183 DartStringAdapter uri = DartUtilities::dartToString(args, 0, exception); |
| 184 if (exception) |
| 185 goto fail; |
| 186 // TODO(vsm): Return isolate future. |
| 187 dartController->spawnDomUri(uri); |
| 188 return; |
| 189 } |
| 190 |
| 191 fail: |
| 192 Dart_ThrowException(exception); |
| 193 ASSERT_NOT_REACHED(); |
| 194 } |
| 195 |
| 196 void changeElementWrapper(Dart_NativeArguments args) |
| 197 { |
| 198 ASSERT_NOT_REACHED(); |
| 199 } |
| 200 |
| 201 class SpawnDomFunctionTask : public ExecutionContextTask { |
| 202 public: |
| 203 SpawnDomFunctionTask(const char* libraryUrl, const char* functionName, Dart_
Port replyTo, DartDOMData* parentDOMData) |
| 204 : m_libraryUrl(strdup(libraryUrl)) |
| 205 , m_functionName(strdup(functionName)) |
| 206 , m_replyTo(replyTo) |
| 207 , m_parentDOMData(parentDOMData) { } |
| 208 |
| 209 ~SpawnDomFunctionTask() |
| 210 { |
| 211 free(m_functionName); |
| 212 free(m_libraryUrl); |
| 213 } |
| 214 |
| 215 virtual void performTask(ExecutionContext* context) |
| 216 { |
| 217 ASSERT(isMainThread()); |
| 218 // controller can be 0 if context has been partially destroyed. |
| 219 if (DartController* controller = DartController::retrieve(context)) { |
| 220 controller->spawnHelperDomIsolate(String(m_libraryUrl), |
| 221 String(m_functionName), m_parentDOMData, m_replyTo); |
| 222 } |
| 223 } |
| 224 |
| 225 private: |
| 226 char* const m_libraryUrl; |
| 227 char* const m_functionName; |
| 228 const Dart_Port m_replyTo; |
| 229 DartDOMData * const m_parentDOMData; |
| 230 }; |
| 231 |
| 232 static Dart_Handle spawnDomHelperErrorMessage() |
| 233 { |
| 234 return Dart_NewStringFromCString("spawnDomHelper expects a top-level functio
n."); |
| 235 } |
| 236 |
| 237 static void spawnDomHelper(Dart_NativeArguments args) |
| 238 { |
| 239 // NB: can be invoked on _any_ thread. DartUtilities assume main thread. |
| 240 Dart_Handle exception = 0; |
| 241 { |
| 242 Dart_Handle closure = Dart_GetNativeArgument(args, 0); |
| 243 ASSERT(!Dart_IsError(closure)); |
| 244 if (!Dart_IsClosure(closure)) { |
| 245 exception = spawnDomHelperErrorMessage(); |
| 246 goto fail; |
| 247 } |
| 248 |
| 249 Dart_Handle function = Dart_ClosureFunction(closure); |
| 250 ASSERT(!Dart_IsError(function)); |
| 251 bool isStatic = false; |
| 252 Dart_Handle ALLOW_UNUSED result = Dart_FunctionIsStatic(function, &isSta
tic); |
| 253 ASSERT(!Dart_IsError(result)); |
| 254 if (!isStatic) { |
| 255 exception = spawnDomHelperErrorMessage(); |
| 256 goto fail; |
| 257 } |
| 258 |
| 259 Dart_Handle container = Dart_FunctionOwner(function); |
| 260 ASSERT(!Dart_IsError(container)); |
| 261 // FIXME: Check if the container is a function once dartbug.com/4337 is
resolved. |
| 262 if (!Dart_IsLibrary(container)) { |
| 263 // FIXME: Support static class methods. |
| 264 exception = spawnDomHelperErrorMessage(); |
| 265 goto fail; |
| 266 } |
| 267 Dart_Handle libraryUrlHandle = Dart_LibraryUrl(container); |
| 268 ASSERT(!Dart_IsError(libraryUrlHandle)); |
| 269 const char* libraryUrl = 0; |
| 270 Dart_StringToCString(libraryUrlHandle, &libraryUrl); |
| 271 |
| 272 Dart_Handle functionNameHandle = Dart_FunctionName(function); |
| 273 ASSERT(!Dart_IsError(functionNameHandle)); |
| 274 const char* functionName; |
| 275 Dart_StringToCString(functionNameHandle, &functionName); |
| 276 |
| 277 Dart_Port portId = ILLEGAL_PORT; |
| 278 Dart_IntegerToInt64(Dart_GetNativeArgument(args, 1), &portId); |
| 279 |
| 280 DartDOMData* parentDOMData = DartDOMData::current(); |
| 281 |
| 282 ExecutionContext* context = DartDOMData::current()->scriptExecutionConte
xt(); |
| 283 if (!context) { |
| 284 exception = DartUtilities::internalErrorException("[spawnDomHelper]
failed to retrieve ExecutionContext"); |
| 285 goto fail; |
| 286 } |
| 287 |
| 288 context->postTask(adoptPtr(new SpawnDomFunctionTask(libraryUrl, function
Name, portId, parentDOMData))); |
| 289 return; |
| 290 } |
| 291 |
| 292 fail: |
| 293 Dart_ThrowException(exception); |
| 294 ASSERT_NOT_REACHED(); |
| 295 } |
| 296 |
| 297 } // namespace DartNativeUtilitiesInternal |
| 298 |
| 299 extern Dart_NativeFunction blinkSnapshotResolver(Dart_Handle name, int argumentC
ount, bool* autoSetupScope); |
| 300 extern Dart_NativeFunction customDartDOMStringMapResolver(Dart_Handle name, int
argumentCount, bool* autoSetupScope); |
| 301 |
| 302 static DartNativeEntry nativeEntries[] = { |
| 303 { DartNativeUtilitiesInternal::forwardingPrint, 1, "Utils_forwardingPrint" }
, |
| 304 { DartNativeUtilitiesInternal::getNewIsolateId, 0, "Utils_getNewIsolateId" }
, |
| 305 { DartNativeUtilitiesInternal::changeElementWrapper, 2, "Utils_changeElement
Wrapper" }, |
| 306 { DartNativeUtilitiesInternal::customConstructorCreate, 2, "Utils_constructo
r_create" }, |
| 307 { DartNativeUtilitiesInternal::spawnDomUri, 1, "Utils_spawnDomUri" }, |
| 308 { 0, 0, 0 }, |
| 309 }; |
| 310 |
| 311 Dart_NativeFunction commonHtmlResolver(Dart_Handle name, int argumentCount, bool
* autoSetupScope) |
| 312 { |
| 313 String str = DartUtilities::toString(name); |
| 314 if (argumentCount == 2 && str == "Utils_spawnDomHelper") |
| 315 return DartNativeUtilitiesInternal::spawnDomHelper; |
| 316 return 0; |
| 317 } |
| 318 |
| 319 Dart_NativeFunction domIsolateHtmlResolver(Dart_Handle name, int argumentCount,
bool* autoSetupScope) |
| 320 { |
| 321 // Some utility functions. |
| 322 if (Dart_NativeFunction func = commonHtmlResolver(name, argumentCount, autoS
etupScope)) |
| 323 return func; |
| 324 if (Dart_NativeFunction func = JsInterop::resolver(name, argumentCount, auto
SetupScope)) |
| 325 return func; |
| 326 |
| 327 String str = DartUtilities::toString(name); |
| 328 ASSERT(autoSetupScope); |
| 329 *autoSetupScope = true; |
| 330 for (intptr_t i = 0; nativeEntries[i].nativeFunction != 0; i++) { |
| 331 if (argumentCount == nativeEntries[i].argumentCount && str == nativeEntr
ies[i].name) { |
| 332 return nativeEntries[i].nativeFunction; |
| 333 } |
| 334 } |
| 335 return 0; |
| 336 } |
| 337 |
| 338 |
| 339 const uint8_t* domIsolateHtmlSymbolizer(Dart_NativeFunction nf) |
| 340 { |
| 341 const uint8_t* r = 0; |
| 342 r = JsInterop::symbolizer(nf); |
| 343 if (r) { |
| 344 return r; |
| 345 } |
| 346 |
| 347 for (intptr_t i = 0; nativeEntries[i].nativeFunction != 0; i++) { |
| 348 if (nf == nativeEntries[i].nativeFunction) { |
| 349 return reinterpret_cast<const uint8_t*>(nativeEntries[i].name); |
| 350 } |
| 351 } |
| 352 |
| 353 return 0; |
| 354 } |
| 355 |
| 356 |
| 357 } |
OLD | NEW |