blob: 63c783c6c1367b63e05110b17cb9c130b5649fe2 [file] [log] [blame]
// Copyright 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DartApplicationLoader_h
#define DartApplicationLoader_h
#include "bindings/core/v8/ScriptSourceCode.h"
#include "core/dom/Document.h"
#include "core/html/HTMLScriptElement.h"
#include "core/html/VoidCallback.h"
#include <dart_api.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/text/StringHash.h>
namespace blink {
class FetchRequest;
class KURL;
class ScriptLoader;
class ScriptLoaderClient;
class ScriptResource;
class DartErrorEventDispatcher : public RefCounted<DartErrorEventDispatcher> {
public:
virtual ~DartErrorEventDispatcher() { }
virtual void dispatchErrorEvent() = 0;
};
// FIXME(vsm): We should be able to eliminate this class and reuse v8/ScriptSourceCode.
// Abstraction for HTMLScriptElement or SVGScriptElement.
class DartScriptInfo : public DartErrorEventDispatcher {
public:
static PassRefPtr<DartScriptInfo> create(PassRefPtr<Element> scriptElement);
String sourceAttributeValue() const;
String typeAttributeValue() const;
String scriptContent();
void dispatchErrorEvent();
WTF::OrdinalNumber startLineNumber();
ScriptLoader* loader();
Document* ownerDocument();
String url();
virtual ~DartScriptInfo() { }
protected:
DartScriptInfo(PassRefPtr<Element>);
// Note, the element keeps the corresponding ScriptLoader and ScriptLoaderClient alive.
RefPtr<Element> m_element;
ScriptLoader* m_loader;
ScriptLoaderClient* m_client;
};
class DartApplicationLoader : public RefCounted<DartApplicationLoader> {
public:
class Callback : public RefCounted<Callback> {
public:
Callback(Document* originDocument, PassRefPtr<DartScriptInfo> scriptInfo = nullptr)
: m_originDocument(originDocument)
, m_scriptInfo(scriptInfo) { }
virtual ~Callback() { }
virtual void ready() = 0;
void reportError(const String& error, const String& url);
KURL completeURL(const String& url) { return document()->completeURL(url); }
ResourcePtr<ScriptResource> requestScript(FetchRequest&);
Document* document();
Document* originDocument() const { return m_originDocument; }
PassRefPtr<DartScriptInfo> scriptInfo() const { return m_scriptInfo; }
private:
Document* m_originDocument;
RefPtr<DartScriptInfo> m_scriptInfo;
};
static PassRefPtr<DartApplicationLoader> create(Document* document, bool domEnabled)
{
return adoptRef(new DartApplicationLoader(document, domEnabled));
}
void load(PassRefPtr<DartErrorEventDispatcher>);
Document* document() { return m_originDocument; }
void callEntryPoint();
void logObservatoryInformation();
void validateUrlLoaded(const String& url);
// Registers a request to be fetched later.
void addRequest(PassRefPtr<DartScriptInfo>);
// Fetches all pending requests and invokes callback when done.
void processRequests(Dart_Isolate, const ScriptSourceCode&, PassRefPtr<Callback>);
void processSingleRequest(Dart_Isolate, const String& url, PassRefPtr<Callback>);
bool running() const { return m_state >= Running; }
bool error() const { return m_state == Error; }
bool uninitialized() const { return m_state == Uninitialized; }
const KURL& scriptUrl() { return m_scriptUrl; }
private:
enum State {
// The application failed to load.
Error = -1,
// The isolate is not set.
Uninitialized = 0,
// The isolate is initialized, but no user scripts have been requested or loaded.
Initialized,
// The isolate is not running. The main script has been requested, but not loaded.
Fetching,
// The isolate is not running as requests are in the process of loading.
Loading,
// The isolate is not running, but is ready to run. There are no outstanding requests.
Ready,
// The isolate is running. There no outstanding requests or deferred libraries.
Running,
// The isolate is running, but deferred requests are outstanding.
DeferredLoading,
// The isolate is running, but there are deferred requests ready to finalize.
DeferredReady,
};
enum SnapshotMode {
// Snapshots are disabled.
SnapshotOff,
// Snapshot only single resource cacheable apps.
SnapshotSingle,
// Snapshot everything (experimental).
SnapshotAll,
};
typedef HashSet<String> UrlSet;
typedef Vector<Dart_PersistentHandle> HandleSet;
typedef HashMap<String, HandleSet*> UrlHandleMap;
typedef Deque<RefPtr<DartScriptInfo> > ScriptList;
DartApplicationLoader(Document*, bool domEnabled = true);
void loadScriptFromSnapshot(const String& url, const uint8_t* snapshot, intptr_t snapshotSize);
Dart_Handle topLevelLibrary();
// FIXME(vsm): Do we need all of these?
void scriptLoadError(String failedUrl);
void reportDartError(Dart_Handle);
void reportError(Dart_Handle error, const String& url);
void reportError(const String& error, const String& url);
void initialize(Dart_Isolate, const String& scriptUrl, PassRefPtr<Callback>);
void process(const String& url, const String& source, intptr_t lineNumber);
void fetchScriptResource(const String& url);
// All dependences are available.
bool ready() const { return m_pendingLibraries.isEmpty() && m_pendingSource.isEmpty() && m_htmlImportedScripts.isEmpty() && (m_state >= Loading); }
void findDependences(const String& url, const String& source, intptr_t lineNumber);
void processLibrary(const String& url, const String& source, intptr_t lineNumber);
void processSource(const String& url, const String& source, intptr_t lineNumber);
static Dart_Handle libraryTagHandlerCallback(Dart_LibraryTag, Dart_Handle library, Dart_Handle urlHandle);
Dart_Isolate m_isolate;
// Client must ensure that DartApplicationLoader doesn't outlive corresponding document.
Document* m_originDocument;
RefPtr<DartErrorEventDispatcher> m_errorEventDispatcher;
RefPtr<Callback> m_loadCallback;
bool m_domEnabled;
bool m_cacheable;
ScriptList m_htmlImportedScripts;
UrlSet m_pendingLibraries;
UrlHandleMap m_pendingSource;
KURL m_scriptUrl;
String m_scriptUrlString;
String m_packageRoot;
State m_state;
SnapshotMode m_snapshotMode;
friend class DartService;
friend class ScriptLoadedCallback;
};
}
#endif // DartApplicationLoader_h