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

Side by Side Diff: Source/bindings/core/dart/DartApplicationLoader.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
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/DartApplicationLoader.h"
32
33 #include "core/FetchInitiatorTypeNames.h"
34 #include "bindings/core/dart/DartDOMWrapper.h"
35 #include "bindings/core/dart/DartInspectorTimeline.h"
36 #include "bindings/core/dart/DartScriptDebugServer.h"
37 #include "bindings/core/dart/DartService.h"
38 #include "bindings/core/dart/DartUtilities.h"
39 #if defined(ENABLE_DART_NATIVE_EXTENSIONS)
40 #include "bindings/core/dart/shared_lib/DartNativeExtensions.h"
41 #endif
42 #include "bindings/core/v8/ScriptSourceCode.h"
43 #include "core/dom/Document.h"
44 #include "core/dom/Element.h"
45 #include "core/dom/ScriptLoader.h"
46 #include "core/dom/ScriptLoaderClient.h"
47 #include "core/fetch/CachedMetadata.h"
48 #include "core/fetch/FetchRequest.h"
49 #include "core/fetch/ResourceClient.h"
50 #include "core/fetch/ResourceFetcher.h"
51 #include "core/fetch/ScriptResource.h"
52 #include "core/frame/LocalDOMWindow.h"
53 #include "core/frame/LocalFrame.h"
54 #include "core/html/HTMLScriptElement.h"
55 #include "core/inspector/ScriptCallStack.h"
56 #include "core/svg/SVGScriptElement.h"
57
58 #include <dart_api.h>
59 #include <dart_mirrors_api.h>
60
61 namespace blink {
62
63 // FIXME(vsm): Define this in a central place.
64 static const unsigned dartTypeID = 0xDAADDAAD;
65
66 PassRefPtr<DartScriptInfo> DartScriptInfo::create(PassRefPtr<Element> scriptElem ent)
67 {
68 RefPtr<DartScriptInfo> scriptInfo = adoptRef(new DartScriptInfo(scriptElemen t));
69 if (scriptInfo->loader())
70 return scriptInfo;
71 return nullptr;
72 }
73
74 String DartScriptInfo::sourceAttributeValue() const
75 {
76 return m_client->sourceAttributeValue();
77 }
78
79 String DartScriptInfo::typeAttributeValue() const
80 {
81 return m_client->typeAttributeValue();
82 }
83
84 String DartScriptInfo::scriptContent()
85 {
86 return m_loader->scriptContent();
87 }
88
89 void DartScriptInfo::dispatchErrorEvent()
90 {
91 m_loader->dispatchErrorEvent();
92 }
93
94 WTF::OrdinalNumber DartScriptInfo::startLineNumber()
95 {
96 return m_loader->startLineNumber();
97 }
98
99 ScriptLoader* DartScriptInfo::loader()
100 {
101 return m_loader;
102 }
103
104 Document* DartScriptInfo::ownerDocument()
105 {
106 return m_element->ownerDocument();
107 }
108
109 String DartScriptInfo::url()
110 {
111 String scriptURL = sourceAttributeValue();
112 KURL ownerURL = ownerDocument()->url();
113 return scriptURL.isEmpty() ? ownerURL : KURL(ownerURL, scriptURL);
114 }
115
116 DartScriptInfo::DartScriptInfo(PassRefPtr<Element> element)
117 {
118 m_element = element;
119 if (m_element->document().isHTMLDocument()) {
120 HTMLScriptElement* scriptElement = static_cast<HTMLScriptElement*>(m_ele ment.get());
121 m_loader = scriptElement->loader();
122 m_client = static_cast<ScriptLoaderClient*>(scriptElement);
123 } else if (m_element->document().isSVGDocument()) {
124 SVGScriptElement* scriptElement = static_cast<SVGScriptElement*>(m_eleme nt.get());
125 m_loader = scriptElement->loader();
126 m_client = static_cast<ScriptLoaderClient*>(scriptElement);
127 } else {
128 // Invalid script element.
129 m_loader = 0;
130 m_client = 0;
131 m_element = nullptr;
132 }
133 }
134
135 void DartApplicationLoader::Callback::reportError(const String& error, const Str ing& url)
136 {
137 m_originDocument->logExceptionToConsole(error + ": " + url, 0, url, 0, 0, nu llptr);
138 if (m_scriptInfo)
139 m_scriptInfo->loader()->dispatchErrorEvent();
140 }
141
142 ResourcePtr<ScriptResource> DartApplicationLoader::Callback::requestScript(Fetch Request& request)
143 {
144 return m_originDocument->fetcher()->fetchScript(request);
145 }
146
147 Document* DartApplicationLoader::Callback::document()
148 {
149 return m_scriptInfo ? m_scriptInfo->ownerDocument() : m_originDocument;
150 }
151
152 DartApplicationLoader::DartApplicationLoader(
153 Document* document,
154 bool domEnabled)
155 : m_isolate(0)
156 , m_originDocument(document)
157 , m_loadCallback(nullptr)
158 , m_domEnabled(domEnabled)
159 , m_cacheable(false)
160 , m_state(Uninitialized)
161 , m_snapshotMode(SnapshotOff)
162 {
163 ASSERT(m_originDocument);
164
165 DEFINE_STATIC_LOCAL(String, setting, (getenv("DART_SNAPSHOT_MODE")));
166 if (!setting.isNull()) {
167 if (setting == "all")
168 m_snapshotMode = SnapshotAll;
169 else if (setting == "off")
170 m_snapshotMode = SnapshotOff;
171 else if (setting == "single")
172 m_snapshotMode = SnapshotSingle;
173 else
174 DartUtilities::reportProblem(m_originDocument, String("Invalid DART_ SNAPSHOT_MODE: ") + setting);
175 }
176 }
177
178 void DartApplicationLoader::addRequest(PassRefPtr<DartScriptInfo> scriptInfo)
179 {
180 // FIXME(vsm): Temporary support to load extra Dart libraries via HTML impor ts before we encounter the main
181 // script. In the future, this should map to deferred loading.
182 RELEASE_ASSERT(m_state == Uninitialized);
183 m_htmlImportedScripts.append(scriptInfo);
184 }
185
186 void DartApplicationLoader::initialize(Dart_Isolate isolate, const String& scrip tUrl, PassRefPtr<Callback> loadCallback)
187 {
188 RELEASE_ASSERT(m_state == Uninitialized && !m_isolate);
189 m_isolate = isolate;
190 m_loadCallback = loadCallback;
191
192 Document* document = m_loadCallback->document();
193
194 m_scriptUrl = KURL(document->baseURL(), scriptUrl);
195 m_scriptUrlString = m_scriptUrl.string();
196
197 RELEASE_ASSERT(m_isolate == isolate);
198 Dart_EnterIsolate(isolate);
199
200 DartDOMData* domData = DartDOMData::current();
201 if (!domData->packageRoot()) {
202 m_packageRoot = String();
203 } else {
204 m_packageRoot = String(domData->packageRoot());
205 }
206 // Associate application loader with current isolate, so we can retrieve it in libraryTagHandlerCallback.
207 domData->setApplicationLoader(this);
208 Dart_Handle ALLOW_UNUSED result = Dart_SetLibraryTagHandler(&libraryTagHandl erCallback);
209 ASSERT(!Dart_IsError(result));
210
211 // FIXME: Stay in isolate for processing below.
212 Dart_ExitIsolate();
213 m_state = Initialized;
214 }
215
216 void DartApplicationLoader::processRequests(Dart_Isolate isolate, const ScriptSo urceCode& sourceCode, PassRefPtr<Callback> loadCallback)
217 {
218 DART_START_TIMER();
219 const String& scriptUrl = sourceCode.url();
220 initialize(isolate, scriptUrl, loadCallback);
221 DART_RECORD_TIMER(" DartApplicationLoader::initialize took");
222
223 m_state = Fetching;
224
225 // Check for cached snapshot.
226 ScriptResource* scriptResource = sourceCode.resource();
227 if (scriptResource && m_snapshotMode != SnapshotOff) {
228 // This is cacheable if there is a resource we can cache the snapshot on .
229 m_cacheable = true;
230 CachedMetadata* cachedMetadata = scriptResource->cachedMetadata(dartType ID);
231 if (cachedMetadata) {
232 loadScriptFromSnapshot(sourceCode.url(), reinterpret_cast<const uint 8_t*>(cachedMetadata->data()), cachedMetadata->size());
233 return;
234 }
235 }
236
237 // Set up root library for main DOM isolate.
238 {
239 DartIsolateScope isolateScope(m_isolate);
240 DartApiScope apiScope;
241
242 ASSERT(Dart_IsNull(Dart_RootLibrary()));
243
244 Document* document = m_loadCallback->document();
245 const String& source = sourceCode.source();
246 int lineNumber = sourceCode.startLine();
247
248 // Use zero-based counting instead of one-based.
249 lineNumber = (lineNumber <= 0) ? 0 : lineNumber - 1;
250
251 String canonical = KURL(document->url(), scriptUrl).string();
252 m_pendingLibraries.add(canonical);
253 process(canonical, source, lineNumber);
254
255 // Any problem loading main script we're done.
256 if (m_state == Error)
257 return;
258
259 RELEASE_ASSERT(m_state >= Loading);
260 }
261
262 // FIXME(vsm): This will go away.
263 // Load HTML imported dart scripts.
264 while (!m_htmlImportedScripts.isEmpty()) {
265 RefPtr<DartScriptInfo> script = m_htmlImportedScripts.takeFirst();
266 const String& src = script->sourceAttributeValue();
267 const String& url = script->url();
268 if (src.isEmpty()) {
269 // Inline script.
270 ASSERT(!m_pendingLibraries.contains(url));
271 m_pendingLibraries.add(url);
272 intptr_t lineOffset = script->startLineNumber().zeroBasedInt();
273 // Blink gives generated script tags an invalid start line.
274 if (lineOffset < 0)
275 lineOffset = 0;
276 process(script->url(), script->scriptContent(), lineOffset);
277 } else {
278 // Canonicalize the src attribute url.
279 String canonical = KURL(script->ownerDocument()->url(), src).string( );
280
281 // Check if this was loaded by an earlier script.
282 {
283 DartIsolateScope isolateScope(m_isolate);
284 DartApiScope apiScope;
285 Dart_Handle library = Dart_LookupLibrary(DartUtilities::safeStri ngToDartString(canonical));
286 if (!Dart_IsError(library))
287 continue;
288 }
289
290 // Request if we don't have the script or haven't already requested it.
291 if (!m_pendingLibraries.contains(canonical)) {
292 m_pendingLibraries.add(canonical);
293 fetchScriptResource(canonical);
294 }
295 }
296 }
297
298 // FIXME(vsm): Once m_htmlImportedScripts goes away, we should be able to de lete this.
299 // Processing HTML imports may be made the app ready without running.
300 RELEASE_ASSERT(m_state == Error || m_state >= Loading);
301 if (ready() && m_state == Loading) {
302 m_state = Ready;
303 // All dependences are in.
304 m_loadCallback->ready();
305 }
306
307 DART_RECORD_TIMER(" DartApplicationLoader::processRequests took");
308 }
309
310 void DartApplicationLoader::processSingleRequest(Dart_Isolate isolate, const Str ing& scriptUrl, PassRefPtr<Callback> loadCallback)
311 {
312 initialize(isolate, scriptUrl, loadCallback);
313 // Use the resolved scriptUrl.
314 m_pendingLibraries.add(m_scriptUrlString);
315 m_state = Fetching;
316 fetchScriptResource(m_scriptUrlString);
317 }
318
319 void DartApplicationLoader::load(PassRefPtr<DartErrorEventDispatcher> errorEvent Dispatcher)
320 {
321 RELEASE_ASSERT(m_state == Ready || m_state == DeferredReady);
322
323 m_errorEventDispatcher = errorEventDispatcher;
324
325 DartIsolateScope isolateScope(m_isolate);
326 DartApiScope dartApiScope;
327 bool completeFutures = false;
328
329 // Finalize classes and complete futures if there are any deferred loads.
330 if (m_state == DeferredReady) {
331 // We have already invoked the entry point on the main script URL at
332 // this point we will start running dart code again.
333 m_state = Running;
334 completeFutures = true;
335 } else {
336 RELEASE_ASSERT(m_state == Ready);
337 }
338
339 {
340 V8Scope v8scope(DartDOMData::current());
341 Dart_Handle result = Dart_FinalizeLoading(completeFutures);
342
343 if (completeFutures && m_domEnabled) {
344 // Call this after Dart_FinalizeLoading so that everything is ready.
345 Timeline timeline(m_originDocument->frame(), String("notifyDebugServ erDeferredReady@") + m_scriptUrlString);
346 DartScriptDebugServer::shared().deferredReady();
347 }
348
349 if (Dart_IsError(result)) {
350 reportDartError(result);
351 return;
352 }
353 }
354 // Invoke the entry point on the main script URL if it has not yet been
355 // invoked.
356 if (m_state == Ready) {
357 // Call the entry point on the main script URL.
358 callEntryPoint();
359 }
360 }
361
362 void DartApplicationLoader::loadScriptFromSnapshot(const String& url, const uint 8_t* snapshot, intptr_t snapshotSize)
363 {
364 DART_START_TIMER();
365 RELEASE_ASSERT(m_state == Fetching);
366
367 Timeline timeline(m_originDocument->frame(), String("loadSnapshot@") + m_scr iptUrlString);
368 m_scriptUrlString = url;
369 DartIsolateScope isolateScope(m_isolate);
370 DartApiScope apiScope;
371 Dart_Handle result = Dart_LoadScriptFromSnapshot(snapshot, snapshotSize);
372 if (Dart_IsError(result)) {
373 reportDartError(result);
374 return;
375 }
376
377 m_state = Ready;
378 m_loadCallback->ready();
379 DART_RECORD_TIMER(" DartApplicationLoader::loadScriptFromSnapshot took");
380 }
381
382 void DartApplicationLoader::callEntryPoint()
383 {
384 RELEASE_ASSERT(m_state == Ready);
385
386 Timeline timeline(m_originDocument->frame(), String("callEntryPoint@") + m_s criptUrlString);
387
388 if (m_cacheable) {
389 // Snapshot single-script applications.
390 ResourceFetcher* loader = m_originDocument->fetcher();
391 FetchRequest request(m_originDocument->completeURL(m_scriptUrlString), F etchInitiatorTypeNames::document);
392 ResourcePtr<ScriptResource> scriptResource = loader->fetchScript(request );
393
394 // Check if already snapshotted.
395 if (scriptResource && !scriptResource->cachedMetadata(dartTypeID)) {
396 uint8_t* buffer;
397 intptr_t size;
398 Dart_Handle result = Dart_CreateScriptSnapshot(&buffer, &size);
399 if (Dart_IsError(result)) {
400 reportDartError(result);
401 // FIXME: exiting early might be not the best option if error is due to snapshot
402 // creation proper (and not due to compilation), even though it' s unlikely.
403 // Consider other options like Dart_CompileAll.
404 return;
405 }
406
407 Vector<uint8_t>* snapshot = DartDOMData::current()->applicationSnaps hot();
408 ASSERT(snapshot->isEmpty());
409 snapshot->append(buffer, size);
410
411 // Write the snapshot.
412 scriptResource->setCachedMetadata(dartTypeID, reinterpret_cast<const char*>(buffer), size);
413 }
414 }
415
416 m_state = Running;
417
418 if (m_domEnabled) {
419 Timeline timeline(m_originDocument->frame(), String("notifyDebugServer@" ) + m_scriptUrlString);
420 DartScriptDebugServer::shared().isolateLoaded();
421 }
422
423 if (m_domEnabled) {
424 V8Scope v8scope(DartDOMData::current());
425 Dart_Handle mainLibrary = topLevelLibrary();
426
427 logObservatoryInformation();
428
429 // Trampoline to invoke main.
430 // FIXME: Use the page library instead. To do this, we need to import ea ch script tag's library into the page
431 // with a unique prefix to ensure a secondary script doesn't define a ma in.
432 String trampolineUrl = m_scriptUrlString + "$trampoline";
433 Dart_Handle trampoline = Dart_LoadLibrary(DartUtilities::safeStringToDar tString(trampolineUrl), Dart_NewStringFromCString(""), 0, 0);
434 Dart_LibraryImportLibrary(trampoline, mainLibrary, Dart_Null());
435
436 Dart_Handle result = Dart_FinalizeLoading(false);
437 if (Dart_IsError(result)) {
438 DartUtilities::reportProblem(m_originDocument, result, m_scriptUrlSt ring);
439 }
440
441 // FIXME: Settle on proper behavior here. We have not determined exactly when
442 // or how often we'll call the entry point.
443 Dart_Handle entryPoint = Dart_NewStringFromCString("main");
444 Dart_Handle main = Dart_LookupFunction(trampoline, entryPoint);
445 if (!Dart_IsNull(main)) {
446 // FIXME: Avoid relooking up main.
447 Dart_Handle result = Dart_Invoke(trampoline, entryPoint, 0, 0);
448 if (Dart_IsError(result)) {
449 DartUtilities::reportProblem(m_originDocument, result, m_scriptU rlString);
450 }
451 }
452
453 }
454 }
455
456
457 void DartApplicationLoader::logObservatoryInformation()
458 {
459 const char* serverIp = DartService::GetServerIP();
460 const int serverPort = DartService::GetServerPort();
461 String message = String::format("Observatory listening at http://%s:%d/", se rverIp, serverPort);
462 m_originDocument->addConsoleMessage(
463 ConsoleMessage::create(JSMessageSource, InfoMessageLevel, message));
464 }
465
466
467 void DartApplicationLoader::validateUrlLoaded(const String& url)
468 {
469 RELEASE_ASSERT(m_state == Running);
470
471 DartIsolateScope isolateScope(m_isolate);
472 DartApiScope apiScope;
473
474 Dart_Handle library = Dart_LookupLibrary(DartUtilities::safeStringToDartStri ng(url));
475 if (!Dart_IsNull(library)) {
476 DartUtilities::reportProblem(m_originDocument, "URL must be imported by main Dart script: " + url);
477 }
478 }
479
480 Dart_Handle DartApplicationLoader::topLevelLibrary()
481 {
482 Dart_Handle library = Dart_LookupLibrary(DartUtilities::safeStringToDartStri ng(m_scriptUrlString));
483 ASSERT(!Dart_IsError(library));
484 return library;
485 }
486
487 void DartApplicationLoader::findDependences(const String& url, const String& sou rce, intptr_t lineNumber)
488 {
489 ASSERT(m_pendingLibraries.contains(url) || m_pendingSource.contains(url));
490
491 DartIsolateScope isolateScope(m_isolate);
492 DartApiScope dartApiScope;
493
494 if (m_pendingLibraries.contains(url)) {
495 processLibrary(url, source, lineNumber);
496 } else {
497 ASSERT(m_pendingSource.contains(url));
498 processSource(url, source, lineNumber);
499 }
500 }
501
502 void DartApplicationLoader::processLibrary(const String& url, const String& sour ce, intptr_t lineNumber)
503 {
504 ASSERT(m_pendingLibraries.contains(url));
505
506 Dart_Handle result;
507 if (m_state == Fetching) {
508 // A spawned isolate.
509 m_state = Loading;
510 result = Dart_LoadScript(DartUtilities::safeStringToDartString(url), Dar tUtilities::convertSourceString(source), lineNumber, 0);
511 } else {
512 result = Dart_LoadLibrary(DartUtilities::safeStringToDartString(url), Da rtUtilities::convertSourceString(source), lineNumber, 0);
513 }
514 if (Dart_IsError(result))
515 reportError(result, url);
516
517 m_pendingLibraries.remove(url);
518 }
519
520 void DartApplicationLoader::processSource(const String& url, const String& sourc e, intptr_t lineNumber)
521 {
522 ASSERT(m_pendingSource.contains(url));
523 HandleSet* importers = m_pendingSource.take(url);
524 for (HandleSet::iterator i = importers->begin(); i != importers->end(); ++i) {
525 Dart_Handle persistent = *i;
526 Dart_Handle library = Dart_HandleFromPersistent(persistent);
527 Dart_DeletePersistentHandle(persistent);
528
529 Dart_Handle result = Dart_LoadSource(library, DartUtilities::safeStringT oDartString(url), DartUtilities::convertSourceString(source), lineNumber, 0);
530 if (Dart_IsError(result))
531 reportError(result, url);
532 }
533 delete importers;
534 }
535
536 void DartApplicationLoader::process(const String& url, const String& source, int ptr_t lineNumber)
537 {
538 if (m_state == Error)
539 return;
540
541 if (url != m_scriptUrlString && m_snapshotMode != SnapshotAll)
542 m_cacheable = false;
543
544 RELEASE_ASSERT(m_state == Fetching || m_state == Loading || m_state == Defer redLoading);
545 findDependences(url, source, lineNumber);
546 RELEASE_ASSERT(m_state == Error || m_state == Loading || m_state == Deferred Loading);
547
548 if (ready()) {
549 m_state = (m_state == Loading) ? Ready : DeferredReady;
550 // All dependences are in.
551 m_loadCallback->ready();
552 }
553 }
554
555 Dart_Handle DartApplicationLoader::libraryTagHandlerCallback(Dart_LibraryTag tag , Dart_Handle library, Dart_Handle urlHandle)
556 {
557 ASSERT(Dart_CurrentIsolate());
558 ASSERT(Dart_IsLibrary(library));
559
560 const String url = DartUtilities::toString(urlHandle);
561
562 if (tag == Dart_kCanonicalizeUrl) {
563 if (url.startsWith("dart:")) {
564 if (url == "dart:io" || url == "dart:_builtin" || url == "dart:vmser viceio") {
565 // We do not allow Dartium isolates to import 'dart:io' and 'dar t:_builtin'.
566 return Dart_NewApiError("The requested built-in library is not a vailable on Dartium.");
567 }
568 }
569 // If a dart application calls spawnUri, the DartVM will call this
570 // libraryTagHandler to canonicalize the url.
571 // DartDOMData::current()->scriptLoader() may be 0 at this point.
572 return DartUtilities::canonicalizeUrl(library, urlHandle, url);
573 }
574
575 if (url.startsWith("dart:")) {
576 // All supported system URLs are already built-in and shouldn't get to t his point.
577 return Dart_NewApiError("The requested built-in library is not available on Dartium.");
578 }
579
580 RefPtr<DartApplicationLoader> loader = DartDOMData::current()->applicationLo ader();
581 ASSERT(loader);
582 // We can only handle requests in one of the following states.
583 if (loader->m_state == Error)
584 return Dart_NewApiError("The isolate is in an invalid state.");
585 RELEASE_ASSERT(loader->m_state == Fetching || loader->m_state == Loading || loader->m_state == Running || loader->m_state == DeferredLoading);
586
587
588 // Fetch non-system URLs.
589 if (tag == Dart_kImportTag) {
590 if (loader->m_pendingLibraries.contains(url))
591 return Dart_True();
592 #if defined(ENABLE_DART_NATIVE_EXTENSIONS)
593 if (url.startsWith("dart-ext:")) {
594 return DartNativeExtensions::loadExtension(url, library);
595 }
596 #endif
597 loader->m_pendingLibraries.add(url);
598 } else if (tag == Dart_kSourceTag) {
599 Dart_PersistentHandle importer = Dart_NewPersistentHandle(library);
600 HandleSet* importers;
601 if (loader->m_pendingSource.contains(url)) {
602 // We have already requested this url. It is a part of more than one library.
603 importers = loader->m_pendingSource.get(url);
604 importers->append(importer);
605 return Dart_True();
606 }
607 importers = new HandleSet();
608 loader->m_pendingSource.add(url, importers);
609 importers->append(importer);
610 } else {
611 ASSERT_NOT_REACHED();
612 }
613
614 // If the isolate is running, this is part of a deferred load request.
615 if (loader->m_state == Running)
616 loader->m_state = DeferredLoading;
617 loader->fetchScriptResource(url);
618 return Dart_True();
619 }
620
621 class ScriptLoadedCallback : public ScriptResourceClient {
622 public:
623 ScriptLoadedCallback(String url, PassRefPtr<DartApplicationLoader> loader, R esourcePtr<ScriptResource> scriptResource)
624 : m_url(url)
625 , m_loader(loader)
626 , m_scriptResource(scriptResource)
627 {
628 }
629
630 virtual void notifyFinished(Resource* cachedResource)
631 {
632 ASSERT(cachedResource->type() == Resource::Script);
633 ASSERT(cachedResource == m_scriptResource.get());
634 ASSERT(WTF::isMainThread());
635
636 if (cachedResource->errorOccurred()) {
637 m_loader->reportError(String("An error occurred loading file"), m_ur l);
638 } else if (cachedResource->wasCanceled()) {
639 // FIXME: shall we let VM know, so it can inform application some of its
640 // resources cannot be loaded?
641 m_loader->reportError(String("File request cancelled"), m_url);
642 } else {
643 ScriptSourceCode sourceCode(m_scriptResource.get());
644
645 // Use the original url associated with the Script so that
646 // redirects do not break the DartScriptLoader.
647 // FIXME: is this the correct behavior? This functionality is
648 // very convenient when you want the source file to act as if
649 // it was from the original location but that isn't always
650 // what the user expects.
651 m_loader->process(m_url, sourceCode.source(), 0);
652 }
653
654 m_scriptResource->removeClient(this);
655 delete this;
656 }
657
658 private:
659 String m_url;
660 RefPtr<DartApplicationLoader> m_loader;
661 ResourcePtr<ScriptResource> m_scriptResource;
662 };
663
664 static String resolveUrl(String mainLibraryURL, const String& url, const String& packageRootOverride)
665 {
666 if (!url.startsWith("package:") || url.startsWith("package://"))
667 return url;
668
669 String packageRoot;
670 String packageUrl;
671 if (!packageRootOverride.isNull()) {
672 // Resolve with respect to the override. Append a
673 // slash to ensure that resolution is against this
674 // path and not its parent.
675 packageRoot = packageRootOverride + "/";
676 // Strip the 'package:' prefix.
677 packageUrl = url.substring(8);
678 if (!(packageRoot.startsWith("file:") || packageRoot.startsWith("http:") || packageRoot.startsWith("https:"))) {
679 return packageRoot + packageUrl;
680 }
681 } else {
682 // Resolve with respect to the entry point's URL. Note, the
683 // trailing file name in the entry point URL (e.g.,
684 // 'rootpath/mainapp.dart') is stripped by the KURL
685 // constructor below.
686 packageRoot = mainLibraryURL;
687 packageUrl = String("packages/") + url.substring(8);
688 }
689 return KURL(KURL(KURL(), packageRoot), packageUrl).string();
690 }
691
692 void DartApplicationLoader::fetchScriptResource(const String& url)
693 {
694 // Request loading of script dependencies.
695 FetchRequest request(m_loadCallback->completeURL(resolveUrl(m_scriptUrl, url , m_packageRoot)),
696 FetchInitiatorTypeNames::document, "utf8");
697 // FIXME: what about charset for this script, maybe use charset of initial s cript tag?
698 ResourcePtr<ScriptResource> scriptResource = m_loadCallback->requestScript(r equest);
699 if (scriptResource) {
700 scriptResource->addClient(new ScriptLoadedCallback(m_loadCallback->compl eteURL(url), this, scriptResource));
701 } else {
702 m_loadCallback->reportError(String("File request error"), url);
703 }
704 }
705
706 // FIXME(vsm): Merge these functions below. We need to be careful about where th e error is dispatched.
707 void DartApplicationLoader::scriptLoadError(String failedUrl)
708 {
709 if (m_state < Running)
710 m_state = Error;
711 // FIXME: try to dig out line number, -1 for now.
712 if (failedUrl.startsWith(String("dart:"))) {
713 m_originDocument->logExceptionToConsole(String("The built-in library '") + failedUrl + String("' is not available on Dartium."), 0, m_scriptUrlString, - 1, 0, nullptr);
714 } else {
715 m_originDocument->logExceptionToConsole(String("Failed to load a file ") + failedUrl, 0, m_scriptUrlString, -1, 0, nullptr);
716 }
717 RELEASE_ASSERT(m_errorEventDispatcher);
718 m_errorEventDispatcher->dispatchErrorEvent();
719 }
720
721 void DartApplicationLoader::reportDartError(Dart_Handle error)
722 {
723 if (m_state < Running)
724 m_state = Error;
725 DartUtilities::reportProblem(m_originDocument, error, m_scriptUrlString);
726 }
727
728 void DartApplicationLoader::reportError(Dart_Handle error, const String& url)
729 {
730 reportError(Dart_GetError(error), url);
731 }
732
733 void DartApplicationLoader::reportError(const String& error, const String& url)
734 {
735 if (m_state < Running)
736 m_state = Error;
737 m_loadCallback->reportError(error, url);
738 }
739
740
741 }
OLDNEW
« no previous file with comments | « Source/bindings/core/dart/DartApplicationLoader.h ('k') | Source/bindings/core/dart/DartBindingsCommonIncludes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698