Index: Source/core/html/HTMLImportsController.cpp |
diff --git a/Source/core/html/HTMLImportsController.cpp b/Source/core/html/HTMLImportsController.cpp |
index bdc16949269fe6d41d5f5acdc64f9667b91fb6f1..203d95536da0ff00c754489f3caca4e6e12e8ad4 100644 |
--- a/Source/core/html/HTMLImportsController.cpp |
+++ b/Source/core/html/HTMLImportsController.cpp |
@@ -70,20 +70,19 @@ void LinkImport::process() |
if (!m_owner) |
return; |
- if (!m_owner->document()->frame() && !m_owner->document()->imports()) |
+ if (!m_owner->document()->frame() && !m_owner->document()->import()) |
return; |
LinkRequestBuilder builder(m_owner); |
if (!builder.isValid()) |
return; |
- HTMLImportsController* controller = m_owner->document()->imports(); |
- if (!controller) { |
+ if (!m_owner->document()->import()) { |
ASSERT(m_owner->document()->frame()); // The document should be the master. |
- m_owner->document()->setImports(HTMLImportsController::create(m_owner->document())); |
- controller = m_owner->document()->imports(); |
+ HTMLImportsController::provideTo(m_owner->document()); |
} |
+ HTMLImportsController* controller = m_owner->document()->import()->controller(); |
if (RefPtr<HTMLImportLoader> found = controller->findLinkFor(builder.url())) { |
m_loader = found; |
return; |
@@ -105,15 +104,15 @@ void LinkImport::ownerRemoved() |
} |
-PassRefPtr<HTMLImportLoader> HTMLImportLoader::create(HTMLImportsController* controller, const KURL& url, const CachedResourceHandle<CachedScript>& resource) |
+PassRefPtr<HTMLImportLoader> HTMLImportLoader::create(HTMLImport* parent, const KURL& url, const CachedResourceHandle<CachedScript>& resource) |
{ |
- RefPtr<HTMLImportLoader> loader = adoptRef(new HTMLImportLoader(controller, url, resource)); |
- controller->addImport(loader); |
- return loader; |
+ RefPtr<HTMLImportLoader> loader = adoptRef(new HTMLImportLoader(parent, url, resource)); |
+ loader->controller()->addImport(loader); |
+ return loader.release(); |
} |
-HTMLImportLoader::HTMLImportLoader(HTMLImportsController* controller, const KURL& url, const CachedResourceHandle<CachedScript>& resource) |
- : m_controller(controller) |
+HTMLImportLoader::HTMLImportLoader(HTMLImport* parent, const KURL& url, const CachedResourceHandle<CachedScript>& resource) |
+ : m_parent(parent) |
, m_state(StateLoading) |
, m_resource(resource) |
, m_url(url) |
@@ -123,6 +122,9 @@ HTMLImportLoader::HTMLImportLoader(HTMLImportsController* controller, const KURL |
HTMLImportLoader::~HTMLImportLoader() |
{ |
+ // importDestroyed() should be called before the destruction. |
+ ASSERT(!m_parent); |
+ ASSERT(!m_importedDocument); |
if (m_resource) |
m_resource->removeClient(this); |
} |
@@ -167,18 +169,18 @@ void HTMLImportLoader::dispose() |
} |
- if (m_controller) |
- m_controller->didLoad(); |
+ if (HTMLImportsController* controller = this->controller()) |
+ controller->didLoad(this); |
} |
HTMLImportLoader::State HTMLImportLoader::startParsing(const ResourceResponse& response) |
{ |
// Current canAccess() implementation isn't sufficient for catching cross-domain redirects: http://crbug.com/256976 |
- if (!m_controller->cachedResourceLoader()->canAccess(m_resource.get())) |
+ if (!controller()->cachedResourceLoader()->canAccess(m_resource.get())) |
return StateError; |
m_importedDocument = HTMLDocument::create(0, response.url()); |
- m_importedDocument->setImports(m_controller); |
+ m_importedDocument->setImport(this); |
m_writer = DocumentWriter::create(m_importedDocument.get(), response.mimeType(), response.textEncodingName()); |
return StateLoading; |
@@ -186,7 +188,7 @@ HTMLImportLoader::State HTMLImportLoader::startParsing(const ResourceResponse& r |
HTMLImportLoader::State HTMLImportLoader::finish() |
{ |
- if (!m_controller) |
+ if (!m_parent) |
return StateError; |
// The writer instance indicates that a part of the document can be already loaded. |
// We don't take such a case as an error because the partially-loaded document has been visible from script at this point. |
@@ -204,14 +206,39 @@ Document* HTMLImportLoader::importedDocument() const |
void HTMLImportLoader::importDestroyed() |
{ |
- m_controller = 0; |
- m_importedDocument.clear(); |
+ m_parent = 0; |
+ if (RefPtr<Document> document = m_importedDocument.release()) |
+ document->setImport(0); |
} |
+HTMLImportsController* HTMLImportLoader::controller() |
+{ |
+ return m_parent ? m_parent->controller() : 0; |
+} |
+ |
+HTMLImport* HTMLImportLoader::parent() |
+{ |
+ return m_parent; |
+} |
-PassRefPtr<HTMLImportsController> HTMLImportsController::create(Document* master) |
+Document* HTMLImportLoader::document() |
{ |
- return adoptRef(new HTMLImportsController(master)); |
+ return m_importedDocument.get(); |
+} |
+ |
+void HTMLImportLoader::wasDetachedFromDocument() |
+{ |
+ // For imported documens this shouldn't be called because Document::m_import is |
+ // cleared before Document is destroyed by HTMLImportLoader::importDestroyed(). |
+ ASSERT_NOT_REACHED(); |
+} |
+ |
+void HTMLImportsController::provideTo(Document* master) |
+{ |
+ DEFINE_STATIC_LOCAL(const char*, name, ("HTMLImportsController")); |
+ OwnPtr<HTMLImportsController> controller = adoptPtr(new HTMLImportsController(master)); |
+ master->setImport(controller.get()); |
+ Supplement<ScriptExecutionContext>::provideTo(master, name, controller.release()); |
} |
HTMLImportsController::HTMLImportsController(Document* master) |
@@ -221,8 +248,16 @@ HTMLImportsController::HTMLImportsController(Document* master) |
HTMLImportsController::~HTMLImportsController() |
{ |
+ ASSERT(!m_master); |
+} |
+ |
+void HTMLImportsController::clear() |
+{ |
for (size_t i = 0; i < m_imports.size(); ++i) |
m_imports[i]->importDestroyed(); |
+ if (m_master) |
+ m_master->setImport(0); |
+ m_master = 0; |
} |
void HTMLImportsController::addImport(PassRefPtr<HTMLImportLoader> link) |
@@ -236,10 +271,12 @@ void HTMLImportsController::showSecurityErrorMessage(const String& message) |
m_master->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); |
} |
-void HTMLImportsController::didLoad() |
+void HTMLImportsController::didLoad(HTMLImportLoader* loadedImport) |
{ |
- if (haveLoaded()) |
- m_master->didLoadAllImports(); |
+ for (HTMLImport* ancestorToNotify = loadedImport->parent(); ancestorToNotify; ancestorToNotify = ancestorToNotify->parent()) { |
+ if (haveChildrenLoaded(ancestorToNotify)) |
+ ancestorToNotify->document()->didLoadAllImports(); |
+ } |
} |
PassRefPtr<HTMLImportLoader> HTMLImportsController::findLinkFor(const KURL& url) const |
@@ -262,14 +299,34 @@ CachedResourceLoader* HTMLImportsController::cachedResourceLoader() const |
return m_master->cachedResourceLoader(); |
} |
-bool HTMLImportsController::haveLoaded() const |
+bool HTMLImportsController::haveChildrenLoaded(HTMLImport* parent) const |
{ |
for (size_t i = 0; i < m_imports.size(); ++i) { |
- if (!m_imports[i]->isDone()) |
+ if (!m_imports[i]->isDone() && m_imports[i]->parent() == parent) |
return false; |
} |
return true; |
} |
+HTMLImportsController* HTMLImportsController::controller() |
+{ |
+ return this; |
+} |
+ |
+HTMLImport* HTMLImportsController::parent() |
+{ |
+ return 0; |
+} |
+ |
+Document* HTMLImportsController::document() |
+{ |
+ return m_master; |
+} |
+ |
+void HTMLImportsController::wasDetachedFromDocument() |
+{ |
+ clear(); |
+} |
+ |
} // namespace WebCore |