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

Side by Side Diff: Source/bindings/core/dart/DartController.cpp

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

Powered by Google App Engine
This is Rietveld 408576698