Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: sky/engine/bindings-dart/core/dart/DartController.cpp

Issue 875013003: Import Dart bindings as of Blink r188698. This merely copies the files over and does not attach any… (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009, 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/DartController.h"
32
33 #if OS(ANDROID)
34 #include <sys/system_properties.h>
35 #endif
36
37
38 #include "core/HTMLNames.h"
39 #include "bindings/common/ScheduledAction.h"
40 #include "bindings/core/dart/DartApplicationLoader.h"
41 #include "bindings/core/dart/DartDOMData.h"
42 #include "bindings/core/dart/DartDOMWrapper.h"
43 #include "bindings/core/dart/DartDocument.h"
44 #include "bindings/core/dart/DartGCController.h"
45 #include "bindings/core/dart/DartInspectorTimeline.h"
46 #include "bindings/core/dart/DartIsolateDestructionObserver.h"
47 #include "bindings/core/dart/DartJsInterop.h"
48 #include "bindings/core/dart/DartNativeUtilities.h"
49 #include "bindings/core/dart/DartScriptDebugServer.h"
50 #include "bindings/core/dart/DartScriptState.h"
51 #include "bindings/core/dart/DartService.h"
52 #include "bindings/core/dart/DartUtilities.h"
53 #include "bindings/core/dart/DartWindow.h"
54 #include "bindings/core/dart/ThreadSafeDartIsolateWrapper.h"
55 #include "bindings/core/v8/ScriptController.h"
56 #include "bindings/core/v8/V8Binding.h"
57 #include "core/dom/Document.h"
58 #include "core/dom/ExecutionContext.h"
59 #include "core/dom/ExecutionContextTask.h"
60 #include "core/dom/MutationObserver.h"
61 #include "core/dom/NodeList.h"
62 #include "core/dom/ScriptLoader.h"
63 #include "core/frame/DOMTimer.h"
64 #include "core/frame/LocalDOMWindow.h"
65 #include "core/frame/LocalFrame.h"
66 #include "core/frame/Settings.h"
67 #include "core/html/HTMLDocument.h"
68 #include "core/html/HTMLLinkElement.h"
69 #include "core/html/HTMLScriptElement.h"
70 #include "core/page/Page.h"
71 #include "core/storage/StorageNamespace.h"
72 #include "core/svg/SVGScriptElement.h"
73 #include "modules/indexeddb/IDBPendingTransactionMonitor.h"
74 #include "public/platform/Platform.h"
75
76 #include <ctype.h>
77
78 #include <dart_api.h>
79 #include <dart_debugger_api.h>
80
81 namespace blink {
82
83 static void copyValue(Dart_Handle source, const char* fieldName,
84 Dart_Handle targetLibrary, const char* targetClass, const char* targetField)
85 {
86 Dart_Handle value = Dart_GetField(source, Dart_NewStringFromCString(fieldNam e));
87 ASSERT(!Dart_IsError(value));
88
89 Dart_Handle target = targetClass ? Dart_GetType(targetLibrary, Dart_NewStrin gFromCString(targetClass), 0, 0) : targetLibrary;
90 ASSERT(!Dart_IsError(target));
91
92 Dart_SetField(target, Dart_NewStringFromCString(targetField), value);
93 }
94
95 static void messageNotifyCallback(Dart_Isolate);
96
97 extern Dart_NativeFunction blinkSnapshotResolver(Dart_Handle name, int argumentC ount, bool* autoSetupScope);
98
99 static void throwDomDisabled(Dart_NativeArguments)
100 {
101 DartApiScope apiScope;
102 Dart_ThrowException(Dart_NewStringFromCString("DOM access is not enabled in this isolate"));
103 }
104
105 Dart_NativeFunction pureIsolateResolver(Dart_Handle name, int argumentCount, boo l* autoSetupScope)
106 {
107 return throwDomDisabled;
108 }
109
110 const uint8_t* pureIsolateSymbolizer(Dart_NativeFunction nf)
111 {
112 return 0;
113 }
114
115 void DartController::weakCallback(void* isolateCallbackData, Dart_WeakPersistent Handle handle, void* peer)
116 {
117 // This weak handle has no peer associated with it, it is used to temporaril y make
118 // weak handles strong during GC.
119 ASSERT(!peer);
120 DartDOMData* domData = reinterpret_cast<DartDOMData*>(isolateCallbackData);
121 domData->setReachableWeakHandle(0);
122 }
123
124 Dart_Isolate DartController::createIsolate(const char* scriptURL, const char* en tryPoint, Document* document, bool isDOMEnabled, bool isDebuggerEnabled, char** errorMessage)
125 {
126 DART_START_TIMER();
127 const uint8_t* snapshot = DartUtilities::fullSnapshot(document->frame());
128 DartDOMData* domData = new DartDOMData(document, scriptURL, isDOMEnabled);
129 Dart_Isolate isolate = Dart_CreateIsolate(scriptURL, entryPoint, snapshot, d omData, errorMessage);
130 if (!isolate) {
131 delete domData;
132 return 0;
133 }
134 DART_RECORD_TIMER(" createIsolate after Dart_CreateIsolate call");
135
136 DartApiScope apiScope;
137
138 domData->setThreadSafeIsolateWrapper(ThreadSafeDartIsolateWrapper::create()) ;
139
140 Dart_Handle blink = Dart_LookupLibrary(Dart_NewStringFromCString("dart:_blin k"));
141 ASSERT(!Dart_IsError(blink));
142 // FIXME: this should be blinkSnapshotResolver
143 Dart_SetNativeResolver(blink, isDOMEnabled ? domIsolateHtmlResolver : pureIs olateResolver, isDOMEnabled ? domIsolateHtmlSymbolizer : pureIsolateSymbolizer);
144 domData->setBlinkLibrary(Dart_NewPersistentHandle(blink));
145
146 // Fix the html library.
147 Dart_Handle html = Dart_LookupLibrary(Dart_NewStringFromCString("dart:html") );
148 ASSERT(!Dart_IsError(html));
149 domData->setHtmlLibrary(Dart_NewPersistentHandle(html));
150
151 Dart_Handle js = Dart_LookupLibrary(Dart_NewStringFromCString("dart:js"));
152 ASSERT(!Dart_IsError(js));
153 Dart_SetNativeResolver(js, isDOMEnabled ? JsInterop::resolver : pureIsolateR esolver, 0);
154 domData->setJsLibrary(Dart_NewPersistentHandle(js));
155
156 Dart_Handle core = Dart_LookupLibrary(Dart_NewStringFromCString("dart:core") );
157 ASSERT(!Dart_IsError(core));
158
159 domData->setSvgLibrary(0);
160
161 Dart_Handle functionType = Dart_GetType(core, Dart_NewStringFromCString("Fun ction"), 0, 0);
162 ASSERT(!Dart_IsError(functionType));
163 domData->setFunctionType(Dart_NewPersistentHandle(functionType));
164
165 domData->setCurrentException(Dart_NewPersistentHandle(Dart_Null()));
166
167 // Setup configuration closures
168 char forwardingProp[DartUtilities::PROP_VALUE_MAX_LEN];
169 int propLen = DartUtilities::getProp("DART_FORWARDING_PRINT",
170 forwardingProp, DartUtilities::PROP_VALUE_MAX_LEN);
171 bool forwardPrint = propLen > 0;
172 const char * const printClosure = forwardPrint ?
173 "_forwardingPrintClosure" :
174 (isDOMEnabled ? "_printClosure" : "_pureIsolatePrintClosure");
175 Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:as ync"));
176 ASSERT(!Dart_IsError(asyncLib));
177 Dart_Handle internalLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart :_internal"));
178 ASSERT(!Dart_IsError(internalLib));
179 copyValue(html, printClosure, internalLib, 0, "_printClosure");
180 copyValue(html, isDOMEnabled ? "_timerFactoryClosure" : "_pureIsolateTimerFa ctoryClosure", asyncLib, "_TimerFactory", "_factory");
181 if (isDOMEnabled) {
182 copyValue(html, "_scheduleImmediateClosure", asyncLib, "_ScheduleImmedia te", "_closure");
183 } else {
184 // Use the VM implementation (from dart:isolate) for scheduleImmediate.
185 Dart_Handle isolateLibrary = Dart_LookupLibrary(Dart_NewStringFromCStrin g("dart:isolate"));
186 ASSERT(!Dart_IsError(isolateLibrary));
187
188 Dart_Handle value = Dart_Invoke(isolateLibrary, Dart_NewStringFromCStrin g("_getIsolateScheduleImmediateClosure"), 0, 0);
189 ASSERT(!Dart_IsError(value));
190
191 Dart_Handle target = Dart_GetType(asyncLib, Dart_NewStringFromCString("_ ScheduleImmediate"), 0, 0);
192 ASSERT(!Dart_IsError(target));
193
194 Dart_SetField(target, Dart_NewStringFromCString("_closure"), value);
195 }
196 copyValue(html, isDOMEnabled ? "_uriBaseClosure" : "_pureIsolateUriBaseClosu re", core, 0, "_uriBaseClosure");
197
198 if (isDOMEnabled) {
199 // We need a weak handle to an always reachable object in order to tempo rarily make
200 // weak handles strong during GC, see the corresponding logic in DartGCC ontroller.
201 // We use the always reachable boolean 'True' object for this.
202 domData->setReachableWeakHandle(Dart_NewWeakPersistentHandle(Dart_True() , 0, 0, DartController::weakCallback));
203 Dart_SetMessageNotifyCallback(&messageNotifyCallback);
204 Dart_SetGcCallbacks(&DartGCController::prologueCallback, &DartGCControll er::epilogueCallback);
205
206 if (isDebuggerEnabled) {
207 DART_RECORD_TIMER(" createIsolate before debug setup");
208 DartScriptDebugServer::shared().registerIsolate(isolate, document->p age());
209 DART_RECORD_TIMER(" createIsolate after debug setup");
210 }
211 }
212 DART_RECORD_TIMER(" createIsolate done %.3f ms");
213
214 return isolate;
215 }
216
217 Dart_Isolate DartController::createDOMEnabledIsolate(const String& scriptURL, co nst String& entryPoint, Document* document)
218 {
219 DART_START_TIMER();
220 ASSERT(!Dart_CurrentIsolate());
221
222 // FIXME: proper error reporting.
223 char* errorMessage = 0;
224 Dart_Isolate newIsolate = createIsolate(scriptURL.utf8().data(), entryPoint. utf8().data(), document, true, true, &errorMessage);
225 ASSERT(newIsolate);
226 m_isolates.append(newIsolate);
227 DART_RECORD_TIMER(" createDOMEnabledIsolate took");
228 return newIsolate;
229 }
230
231 void DartController::shutdownIsolate(Dart_Isolate isolate)
232 {
233 DartDOMData* domData = DartDOMData::current();
234 ASSERT(domData->isDOMEnabled());
235 // If the following assert triggers, we have hit dartbug.com/14183
236 // FIXME: keep the isolate alive until the recursion level is 0.
237 ASSERT(!*(domData->recursion()));
238 DartScriptDebugServer::shared().unregisterIsolate(isolate, m_frame->page());
239 DartIsolateDestructionObservers* observers = domData->isolateDestructionObse rvers();
240 for (DartIsolateDestructionObservers::iterator it = observers->begin(); it ! = observers->end(); ++it)
241 (*it)->isolateDestroyed();
242 Dart_ShutdownIsolate();
243 delete domData;
244 }
245
246 DartController::DartController(LocalFrame* frame)
247 : m_frame(frame)
248 , m_npObjectMap()
249 {
250 // The DartController's constructor must be called in the LocalFrame's
251 // constructor, so it can properly maintain the unit of related
252 // browsing contexts.
253 }
254
255 DartController::~DartController()
256 {
257 clearWindowShell();
258 }
259
260 void DartController::clearWindowShell()
261 {
262 DART_START_TIMER();
263 initVMIfNeeded();
264 DART_RECORD_TIMER("clearWindowShell::initVM took");
265 m_documentsWithDart.clear();
266 if (m_loader) {
267 m_loader = nullptr;
268 }
269
270 // Due to synchronous dispatch, we may be in an isolate corresponding to ano ther frame.
271 // If so, exit here but re-enter before returning.
272 Dart_Isolate currentIsolate = Dart_CurrentIsolate();
273 if (currentIsolate)
274 Dart_ExitIsolate();
275
276 Vector<Dart_Isolate>::iterator iterator;
277 for (iterator = m_isolates.begin(); iterator != m_isolates.end(); ++iterator ) {
278 Dart_Isolate isolate = *iterator;
279 Dart_EnterIsolate(isolate);
280 shutdownIsolate(isolate);
281 }
282 m_isolates.clear();
283
284 DartScriptDebugServer::shared().clearWindowShell(m_frame->page());
285
286 for (ScriptStatesMap::iterator it = m_scriptStates.begin(); it != m_scriptSt ates.end(); ++it) {
287 LibraryIdMap* libraryIdMap = it->value;
288 delete libraryIdMap;
289 }
290 m_scriptStates.clear();
291
292 // Restore previous isolate.
293 if (currentIsolate)
294 Dart_EnterIsolate(currentIsolate);
295 }
296
297 void DartController::clearScriptObjects()
298 {
299 // FIXME(dartbug.com/18427): Clear plugin / NP objects.
300 }
301
302 class MessageNotifyTask : public ExecutionContextTask {
303 public:
304 explicit MessageNotifyTask(PassRefPtr<ThreadSafeDartIsolateWrapper> destinat ionIsolate)
305 : m_destinationIsolate(destinationIsolate)
306 { }
307
308 virtual void performTask(ExecutionContext* context)
309 {
310 if (!m_destinationIsolate->isIsolateAlive())
311 return;
312
313 DartIsolateScope scope(m_destinationIsolate->isolate());
314 DartApiScope apiScope;
315
316 DartDOMData* domData = DartDOMData::current();
317 // FIXME(dartbug.com/20303): we cannot safely initialize a V8 scope
318 // for the observatory isolate as it is not associated with a fully
319 // initialized document.
320 if (domData->isObservatoryFakeDartDOMData()) {
321 Dart_Handle result = Dart_HandleMessage();
322 if (Dart_IsError(result))
323 DartUtilities::reportProblem(context, result);
324 } else {
325 V8Scope v8scope(domData);
326 Dart_Handle result = Dart_HandleMessage();
327 if (Dart_IsError(result))
328 DartUtilities::reportProblem(context, result);
329 }
330 }
331
332 private:
333 RefPtr<ThreadSafeDartIsolateWrapper> m_destinationIsolate;
334 };
335
336 static void messageNotifyCallback(Dart_Isolate destinationIsolate)
337 {
338 DartDOMData* domData = static_cast<DartDOMData*>(Dart_IsolateData(destinatio nIsolate));
339 ASSERT(domData->isDOMEnabled());
340 ExecutionContext* destinationContext = domData->scriptExecutionContext();
341 destinationContext->postTask(adoptPtr(new MessageNotifyTask(domData->threadS afeIsolateWrapper())));
342 }
343
344 class SpawnUriErrorEventDispatcher : public DartErrorEventDispatcher {
345 public:
346 // TODO(antonm): this is used to dispatch DOM error event. Most probably we need
347 // nothing like that for spawnDomUri, but need to double check.
348 void dispatchErrorEvent() { }
349 };
350
351 class DartSpawnUriCallback : public DartApplicationLoader::Callback {
352 public:
353 DartSpawnUriCallback(Dart_Isolate isolate, PassRefPtr<DartApplicationLoader> loader, const String& url, Document* originDocument)
354 : Callback(originDocument)
355 , m_isolate(isolate)
356 , m_loader(loader)
357 , m_url(url)
358 {
359 }
360
361 ~DartSpawnUriCallback() { }
362
363 virtual void initialize() = 0;
364 virtual bool domEnabled() = 0;
365
366 void ready()
367 {
368 RefPtr<SpawnUriErrorEventDispatcher> errorEventDispatcher = adoptRef(new SpawnUriErrorEventDispatcher());
369
370 m_loader->load(errorEventDispatcher);
371 initialize();
372 }
373
374 protected:
375 Dart_Isolate m_isolate;
376 RefPtr<DartApplicationLoader> m_loader;
377 String m_url;
378 };
379
380 class DartSpawnBackgroundUriCallback : public DartSpawnUriCallback {
381 public:
382 DartSpawnBackgroundUriCallback(Dart_Isolate isolate, PassRefPtr<DartApplicat ionLoader> loader, const String& url, Document* originDocument)
383 : DartSpawnUriCallback(isolate, loader, url, originDocument)
384 {
385 }
386
387 void initialize()
388 {
389 // The VM initiates background isolates.
390 Dart_IsolateMakeRunnable(m_isolate);
391 }
392
393 bool domEnabled() { return false; }
394 };
395
396 class DartSpawnDomUriCallback : public DartSpawnUriCallback {
397 public:
398 DartSpawnDomUriCallback(Dart_Isolate isolate, PassRefPtr<DartApplicationLoad er> loader, const String& url, Document* originDocument)
399 : DartSpawnUriCallback(isolate, loader, url, originDocument)
400 {
401 }
402
403 void initialize()
404 {
405 // The browser initiates DOM isolates directly.
406 }
407
408 bool domEnabled() { return true; }
409 };
410
411 Dart_Isolate DartController::createServiceIsolateCallback(void* callbackData, ch ar** error)
412 {
413 // FIXME(dartbug.com/20303): we create an empty document for the service
414 // isolate that is never GCed so that its lifecycle is not dependent on
415 // pages. One we support service isolates we can remove this hack.
416 Document* document = HTMLDocument::create().leakRef();
417
418 Dart_Isolate serviceIsolate = DartController::createIsolate("dart:vmservice_ dartium", "main", document, true, false, error);
419 DartDOMData* domData = DartDOMData::current();
420 domData->setIsObservatoryFakeDartDOMData(true);
421 Dart_ExitIsolate();
422 return serviceIsolate;
423 }
424
425
426 Dart_Isolate DartController::createPureIsolateCallback(const char* scriptURL, co nst char* entryPoint, const char* packageRoot, void* data, char** errorMsg)
427 {
428 bool isSpawnUri = scriptURL ? true : false;
429
430 if (isSpawnUri && !WTF::isMainThread()) {
431 // FIXME(14463): We need to forward this request to the main thread to f etch the URI.
432 *errorMsg = strdup("spawnUri is not yet supported on background isolates .");
433 return 0;
434 }
435
436 DartDOMData* parentDOMData = static_cast<DartDOMData*>(data);
437 ExecutionContext* context = parentDOMData->scriptExecutionContext();
438
439 if (parentDOMData->isDOMEnabled() && !isSpawnUri) {
440 // spawnFunction is not allowed from a DOM enabled isolate.
441 // This triggers an exception in the caller.
442 *errorMsg = strdup("spawnFunction is not supported from a dom-enabled is olate. Please use spawnUri instead.");
443 return 0;
444 }
445 if (!isSpawnUri) {
446 scriptURL = parentDOMData->scriptURL();
447 }
448
449 ASSERT(context->isDocument());
450 Document* document = static_cast<Document*>(context);
451
452 Dart_Isolate isolate = createIsolate(scriptURL, entryPoint, document, false, true, errorMsg);
453
454 if (!isolate) {
455 // This triggers an exception in the caller.
456 *errorMsg = strdup("Isolate spawn failed.");
457 return 0;
458 }
459
460 // FIXME: If a spawnFunction, we should not need to request resources again. But, it's not clear
461 // we need this callback in the first place for spawnFunction.
462
463 // We need to request the sources asynchronously.
464 RefPtr<DartApplicationLoader> loader = DartApplicationLoader::create(documen t, false);
465 RefPtr<DartSpawnUriCallback> callback = adoptRef(new DartSpawnBackgroundUriC allback(isolate, loader, scriptURL, document));
466 Dart_ExitIsolate();
467 loader->processSingleRequest(isolate, scriptURL, callback);
468
469 return isolate;
470 }
471
472 static char* skipWhiteSpace(char* p)
473 {
474 for (; *p != '\0' && isspace(*p); p++) { }
475 return p;
476 }
477
478 static char* skipBlackSpace(char* p)
479 {
480 for (; *p != '\0' && !isspace(*p); p++) { }
481 return p;
482 }
483
484 static void setDartFlags(const char* str)
485 {
486 if (!str) {
487 Dart_SetVMFlags(0, 0);
488 return;
489 }
490
491 size_t length = strlen(str);
492 char* copy = new char[length + 1];
493 memmove(copy, str, length);
494 copy[length] = '\0';
495
496 // Strip leading white space.
497 char* start = skipWhiteSpace(copy);
498
499 // Count the number of 'arguments'.
500 int argc = 0;
501 for (char* p = start; *p != '\0'; argc++) {
502 p = skipBlackSpace(p);
503 p = skipWhiteSpace(p);
504 }
505
506 // Allocate argument array.
507 const char** argv = new const char*[argc];
508
509 // Split the flags string into arguments.
510 argc = 0;
511 for (char* p = start; *p != '\0'; argc++) {
512 argv[argc] = p;
513 p = skipBlackSpace(p);
514 if (*p != '\0')
515 *p++ = '\0'; // 0-terminate argument
516 p = skipWhiteSpace(p);
517 }
518
519 // Set the flags.
520 Dart_SetVMFlags(argc, argv);
521
522 delete[] argv;
523 delete[] copy;
524 }
525
526 namespace {
527
528 #if OS(LINUX)
529
530 static void* openFileCallback(const char* name, bool write)
531 {
532 return fopen(name, write ? "w" : "r");
533 }
534
535 static void readFileCallback(const uint8_t** data, intptr_t* fileLength, void* s tream)
536 {
537 if (!stream) {
538 *data = 0;
539 *fileLength = 0;
540 } else {
541 FILE* file = reinterpret_cast<FILE*>(stream);
542
543 // Get the file size.
544 fseek(file, 0, SEEK_END);
545 *fileLength = ftell(file);
546 rewind(file);
547
548 // Allocate data buffer.
549 *data = new uint8_t[*fileLength];
550 *fileLength = fread(const_cast<uint8_t*>(*data), 1, *fileLength, file);
551 }
552 }
553
554 static void writeFileCallback(const void* data, intptr_t length, void* file)
555 {
556 fwrite(data, 1, length, reinterpret_cast<FILE*>(file));
557 }
558
559 static void closeFileCallback(void* file)
560 {
561 fclose(reinterpret_cast<FILE*>(file));
562 }
563
564 #else
565
566 static Dart_FileOpenCallback openFileCallback = 0;
567 static Dart_FileReadCallback readFileCallback = 0;
568 static Dart_FileWriteCallback writeFileCallback = 0;
569 static Dart_FileCloseCallback closeFileCallback = 0;
570
571 #endif // OS(LINUX)
572
573 }
574
575 static bool generateEntropy(uint8_t* buffer, intptr_t length)
576 {
577 if (blink::Platform::current()) {
578 blink::Platform::current()->cryptographicallyRandomValues(buffer, length );
579 return true;
580 }
581 return false;
582 }
583
584 void DartController::initVMIfNeeded()
585 {
586 static bool hasBeenInitialized = false;
587 if (hasBeenInitialized)
588 return;
589
590 char flagsProp[DartUtilities::PROP_VALUE_MAX_LEN];
591 int propLen = DartUtilities::getProp(
592 "DART_FLAGS", flagsProp, DartUtilities::PROP_VALUE_MAX_LEN);
593 if (propLen > 0) {
594 setDartFlags(flagsProp);
595 } else {
596 setDartFlags(0);
597 }
598
599 // FIXME(antonm): implement proper unhandled exception callback.
600 Dart_Initialize(&createPureIsolateCallback, 0, 0, 0, openFileCallback, readF ileCallback, writeFileCallback, closeFileCallback, generateEntropy, createServic eIsolateCallback);
601 hasBeenInitialized = true;
602 }
603
604 static bool checkForExpiration()
605 {
606 const time_t ExpirationTimeSecsSinceEpoch =
607 #include "bindings/dart/ExpirationTimeSecsSinceEpoch.time_t"
608 ;
609 const char* override = getenv("DARTIUM_EXPIRATION_TIME");
610 time_t expiration;
611 if (override) {
612 expiration = static_cast<time_t>(String(override).toInt64());
613 } else {
614 expiration = ExpirationTimeSecsSinceEpoch;
615 }
616 const time_t now = time(0);
617 double diff = difftime(now, expiration);
618 if (diff > 0) {
619 fprintf(stderr, "[dartToStderr]: Dartium build has expired\n");
620 return true;
621 }
622
623 return false;
624 }
625
626 class DartDomLoadCallback : public DartApplicationLoader::Callback {
627 public:
628 DartDomLoadCallback(DartController* controller, const String& url, Dart_Isol ate domIsolate, Document* originDocument, PassRefPtr<DartScriptInfo> info)
629 : Callback(originDocument, info)
630 , m_controller(controller)
631 , m_url(url)
632 , m_isolate(domIsolate)
633 {
634 }
635
636 void ready()
637 {
638 m_controller->scheduleScriptExecution(m_url, m_isolate, scriptInfo());
639 }
640
641 private:
642 DartController* m_controller;
643 String m_url;
644 Dart_Isolate m_isolate;
645 };
646
647 class DartScriptRunner : public EventListener {
648 public:
649 static PassRefPtr<DartScriptRunner> create(const String& url, Dart_Isolate i solate, PassRefPtr<DartScriptInfo> info)
650 {
651 return adoptRef(new DartScriptRunner(url, isolate, info));
652 }
653
654 virtual void handleEvent(ExecutionContext* context, Event*)
655 {
656 ASSERT(context->isDocument());
657 Document* document = static_cast<Document*>(context);
658
659 // this gets removed below, so protect it while handler runs.
660 RefPtr<DartScriptRunner> protect(this);
661 document->domWindow()->removeEventListener(AtomicString("DOMContentLoade d"), this, false);
662
663 DartController::retrieve(context)->loadAndRunScript(m_url, m_isolate, m_ info);
664 }
665
666 virtual bool operator==(const EventListener& other)
667 {
668 return this == &other;
669 }
670
671 private:
672 DartScriptRunner(const String& url, Dart_Isolate isolate, PassRefPtr<DartScr iptInfo> info)
673 : EventListener(EventListener::NativeEventListenerType)
674 , m_url(url)
675 , m_isolate(isolate)
676 , m_info(info)
677 {
678 }
679
680 String m_url;
681 Dart_Isolate m_isolate;
682 RefPtr<DartScriptInfo> m_info;
683 };
684
685 void DartController::scheduleScriptExecution(const String& url, Dart_Isolate iso late, PassRefPtr<DartScriptInfo> info)
686 {
687 Document* document = frame()->document();
688 if (document->readyState() == "loading")
689 document->domWindow()->addEventListener(AtomicString("DOMContentLoaded") , DartScriptRunner::create(url, isolate, info), false);
690 else
691 loadAndRunScript(url, isolate, info);
692 }
693
694 void DartController::loadAndRunScript(const String& url, Dart_Isolate isolate, P assRefPtr<DartScriptInfo> info)
695 {
696 DART_START_TIMER();
697 RefPtr<DartScriptInfo> scriptInfo = info;
698 Document* ALLOW_UNUSED document = frame()->document();
699
700 // Invoke only if this is the main document.
701 ASSERT(scriptInfo->ownerDocument() == document);
702
703 ASSERT(m_loader);
704 // Due to deferred loading we might already be running Dart code on
705 // an isolate and the library tag handler callback could result in a call
706 // to this code, we skip the Enter/Exit Isolate calls in that case.
707 if (isolate == Dart_CurrentIsolate()) {
708 m_loader->load(scriptInfo);
709 } else {
710 Dart_EnterIsolate(isolate);
711 m_loader->load(scriptInfo);
712 Dart_ExitIsolate();
713 }
714
715 DART_RECORD_TIMER("DartController::loadAndRunScript took");
716 }
717
718 void DartController::evaluate(const ScriptSourceCode& sourceCode, ScriptLoader* loader)
719 {
720 if (checkForExpiration())
721 return;
722
723 DART_START_TIMER();
724 initVMIfNeeded();
725 DART_RECORD_TIMER("evaluate::initVM took");
726 Document* document = frame()->document();
727 RefPtr<Element> element(loader->element());
728
729 RefPtr<DartScriptInfo> scriptInfo = DartScriptInfo::create(element);
730 if (!scriptInfo) {
731 DartUtilities::reportProblem(document, "Dart script must be in HTML or S VG document.");
732 ASSERT_NOT_REACHED();
733 return;
734 }
735
736 Document* owner = scriptInfo->ownerDocument();
737 if (m_documentsWithDart.contains(owner)) {
738 int line = scriptInfo->startLineNumber().zeroBasedInt();
739 DartUtilities::reportProblem(owner, "Only one Dart script tag allowed pe r document", line);
740 return;
741 }
742 m_documentsWithDart.add(owner);
743
744 if (m_loader) {
745 if (m_loader->running()) {
746 // Main has already been invoked.
747 String scriptURL = scriptInfo->sourceAttributeValue();
748
749 // Enforce that no new code is loaded. We've already invoked main at this point.
750 // Any referenced code must already be in the isolate.
751 if (scriptURL.isEmpty()) {
752 int line = scriptInfo->startLineNumber().zeroBasedInt();
753 DartUtilities::reportProblem(document, "Inline Darts scripts not supported after main script is invoked.", line);
754 } else {
755 m_loader->validateUrlLoaded(scriptURL);
756 }
757 return;
758 }
759 if (m_loader->error()) {
760 return;
761 }
762 }
763
764 if (!m_loader) {
765 m_loader = DartApplicationLoader::create(document, true);
766 }
767
768 DART_RECORD_TIMER("evaluate::prep for loading took");
769 if (document == scriptInfo->ownerDocument()) {
770 String url = scriptInfo->url();
771 // FIXME: This should be the first DOM enabled isolate. There is a race condition
772 // however - m_loader above won't catch this if it hasn't been set yet.
773 // This problem goes away once we map each script to a separate isolate.
774 if (!m_isolates.isEmpty())
775 return;
776 DART_RECORD_TIMER("evaluate before createIsolate");
777 Dart_Isolate isolate = createDOMEnabledIsolate(url, "main", document);
778 DART_RECORD_TIMER("evaluate after createIsolate");
779 RefPtr<DartDomLoadCallback> callback = adoptRef(new DartDomLoadCallback( this, url, isolate, document, scriptInfo));
780 Dart_ExitIsolate();
781 m_loader->processRequests(isolate, sourceCode, callback);
782 DART_RECORD_TIMER("evaluate process request took");
783 } else {
784 m_loader->addRequest(scriptInfo);
785 }
786 DART_RECORD_TIMER("evaluate took");
787 }
788
789 void DartController::bindToWindowObject(LocalFrame* frame, const String& key, NP Object* object)
790 {
791 // FIXME: proper management of lifetime.
792 m_npObjectMap.set(key, object);
793 }
794
795 NPObject* DartController::npObject(const String& key)
796 {
797 return m_npObjectMap.get(key);
798 }
799
800 Dart_Handle DartController::callFunction(Dart_Handle function, int argc, Dart_Ha ndle* argv)
801 {
802 V8Scope v8scope(DartDOMData::current());
803
804 // FIXME: Introduce Dart variant of V8GCController::checkMemoryUsage();
805
806 if (V8RecursionScope::recursionLevel(v8::Isolate::GetCurrent()) >= kMaxRecur sionDepth)
807 return Dart_NewApiError("Maximum call stack size exceeded");
808
809 // FIXME: implement InspectorInstrumentationCookie stuff a la v8.
810 Dart_Handle result = Dart_InvokeClosure(function, argc, argv);
811
812 // Handle fatal error in Dart VM a la v8.
813
814 return result;
815 }
816
817 DartController* DartController::retrieve(LocalFrame* frame)
818 {
819 if (!frame)
820 return 0;
821 return &frame->dart();
822 }
823
824 DartController* DartController::retrieve(ExecutionContext* context)
825 {
826 if (!context || !context->isDocument())
827 return 0;
828 return retrieve(static_cast<Document*>(context)->frame());
829 }
830
831 void DartController::collectScriptStates(V8ScriptState* v8ScriptState, Vector<Da rtScriptState*>& result)
832 {
833 if (m_isolates.isEmpty())
834 return;
835
836 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
837 v8::Handle<v8::Context> v8Context = v8ScriptState->context();
838
839 Vector<Dart_Isolate>::iterator iterator;
840 for (iterator = m_isolates.begin(); iterator != m_isolates.end(); ++iterator ) {
841 Dart_Isolate isolate = *iterator;
842 collectScriptStatesForIsolate(isolate, v8Context, result);
843 }
844 }
845
846 LibraryIdMap* DartController::libraryIdMapForIsolate(Dart_Isolate isolate)
847 {
848 LibraryIdMap* libraryIdMap;
849 ScriptStatesMap::iterator it = m_scriptStates.find(isolate);
850 if (it == m_scriptStates.end()) {
851 libraryIdMap = new LibraryIdMap();
852 m_scriptStates.set(isolate, libraryIdMap);
853 } else {
854 libraryIdMap = it->value;
855 }
856 return libraryIdMap;
857 }
858
859 DartScriptState* DartController::lookupScriptState(Dart_Isolate isolate, v8::Han dle<v8::Context> v8Context, intptr_t libraryId)
860 {
861 return lookupScriptStateFromLibraryIdMap(isolate, v8Context, libraryIdMapFor Isolate(isolate), libraryId);
862 }
863
864 DartScriptState* DartController::lookupScriptStateFromLibraryIdMap(Dart_Isolate isolate, v8::Handle<v8::Context> v8Context, LibraryIdMap* libraryIdMap, intptr_t libraryId)
865 {
866 // -1 cannot be used as a HashMap key however library ids are
867 // guaranteed to be non-negative so it is a non-issue.
868 ASSERT(libraryId >= 0);
869 // 0 cannot be used as a HashMap key so we add 1 to the library id to
870 // create a valid key.
871 intptr_t libraryIdKey = libraryId + 1;
872 LibraryIdMap::iterator libraryIter = libraryIdMap->find(libraryIdKey);
873 DartScriptState* scriptState;
874 if (libraryIter == libraryIdMap->end()) {
875 V8ScriptState* v8ScriptState = V8ScriptState::from(v8Context);
876 RefPtr<DartScriptState> scriptStatePtr = DartScriptState::create(isolate , libraryId, v8ScriptState);
877 libraryIdMap->set(libraryIdKey, scriptStatePtr);
878 scriptState = scriptStatePtr.get();
879 } else {
880 scriptState = libraryIter->value.get();
881 ASSERT(scriptState);
882 }
883 return scriptState;
884 }
885
886 void DartController::collectScriptStatesForIsolate(Dart_Isolate isolate, v8::Han dle<v8::Context> v8Context, Vector<DartScriptState*>& result)
887 {
888 if (!isolate)
889 return;
890 DartIsolateScope scope(isolate);
891 DartApiScope apiScope;
892 LibraryIdMap* libraryIdMap = libraryIdMapForIsolate(isolate);
893 Dart_Handle libraryIdList = Dart_GetLibraryIds();
894
895 intptr_t length = 0;
896 Dart_Handle ALLOW_UNUSED valid = Dart_ListLength(libraryIdList, &length);
897 ASSERT(!Dart_IsError(valid));
898
899
900 for (intptr_t i = 0; i < length; i++) {
901 Dart_Handle libraryIdHandle = Dart_ListGetAt(libraryIdList, i);
902 Dart_Handle exception = 0;
903 intptr_t libraryId = DartUtilities::toInteger(libraryIdHandle, exception );
904 ASSERT(!exception);
905 DartScriptState* scriptState = lookupScriptStateFromLibraryIdMap(isolate , v8Context, libraryIdMap, libraryId);
906 result.append(scriptState);
907 }
908 }
909
910 void DartController::spawnDomUri(const String& url)
911 {
912 // Save caller isolate.
913 Dart_Isolate caller = Dart_CurrentIsolate();
914 ASSERT(caller);
915 Dart_ExitIsolate();
916
917 // Create DOM isolate.
918 Document* document = frame()->document();
919 Dart_Isolate isolate = createDOMEnabledIsolate(url, "main", document);
920
921 // Fetch and start.
922 RefPtr<DartApplicationLoader> loader = DartApplicationLoader::create(documen t, true);
923 RefPtr<DartSpawnUriCallback> callback = adoptRef(new DartSpawnDomUriCallback (isolate, loader, url, document));
924 Dart_ExitIsolate();
925 loader->processSingleRequest(isolate, url, callback);
926
927 // Restore caller isolate.
928 Dart_EnterIsolate(caller);
929
930 // FIXME: We need some way to return a Dart_Handle to the isolate we just cr eated.
931 }
932
933 }
OLDNEW
« no previous file with comments | « sky/engine/bindings-dart/core/dart/DartController.h ('k') | sky/engine/bindings-dart/core/dart/DartCustomElementBinding.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698