Index: Source/core/inspector/InspectorResourceContentLoader.cpp |
diff --git a/Source/core/inspector/InspectorResourceContentLoader.cpp b/Source/core/inspector/InspectorResourceContentLoader.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..32ca861fba5bd55b5bbfcd45f09cf42b5e7507ac |
--- /dev/null |
+++ b/Source/core/inspector/InspectorResourceContentLoader.cpp |
@@ -0,0 +1,134 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "config.h" |
+#include "core/inspector/InspectorResourceContentLoader.h" |
+ |
+#include "FetchInitiatorTypeNames.h" |
+#include "core/css/CSSStyleSheet.h" |
+#include "core/css/StyleSheetContents.h" |
+#include "core/fetch/CSSStyleSheetResource.h" |
+#include "core/fetch/Resource.h" |
+#include "core/fetch/ResourceFetcher.h" |
+#include "core/fetch/ResourcePtr.h" |
+#include "core/fetch/StyleSheetResourceClient.h" |
+#include "core/frame/LocalFrame.h" |
+#include "core/html/VoidCallback.h" |
+#include "core/inspector/InspectorCSSAgent.h" |
+#include "core/inspector/InspectorPageAgent.h" |
+#include "core/page/Page.h" |
+ |
+namespace WebCore { |
+ |
+class InspectorResourceContentLoader::ResourceClient FINAL : private StyleSheetResourceClient { |
+public: |
+ ResourceClient(InspectorResourceContentLoader* loader) |
+ : m_loader(loader) |
+ { |
+ } |
+ |
+ void waitForResource(Resource* resource) |
+ { |
+ resource->addClient(this); |
+ } |
+ |
+private: |
+ InspectorResourceContentLoader* m_loader; |
+ |
+ virtual void setCSSStyleSheet(const String&, const KURL&, const String&, const CSSStyleSheetResource*) OVERRIDE; |
+ |
+ friend class InspectorResourceContentLoader; |
+}; |
+ |
+void InspectorResourceContentLoader::ResourceClient::setCSSStyleSheet(const String&, const KURL& url, const String&, const CSSStyleSheetResource* resource) |
+{ |
+ if (m_loader) |
+ m_loader->resourceFinished(this); |
+ const_cast<CSSStyleSheetResource*>(resource)->removeClient(this); |
+ delete this; |
+} |
+ |
+InspectorResourceContentLoader::InspectorResourceContentLoader(Page* page) |
+ : m_allRequestsStarted(false) |
+{ |
+ Vector<Document*> documents; |
+ for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) { |
+ if (!frame->isLocalFrame()) |
+ continue; |
+ LocalFrame* localFrame = toLocalFrame(frame); |
+ documents.append(localFrame->document()); |
+ documents.appendVector(InspectorPageAgent::importsForFrame(localFrame)); |
+ } |
+ for (Vector<Document*>::const_iterator documentIt = documents.begin(); documentIt != documents.end(); ++documentIt) { |
+ Document* document = *documentIt; |
+ |
+ HashSet<String> urlsToFetch; |
+ Vector<CSSStyleSheet*> styleSheets; |
+ InspectorCSSAgent::collectAllDocumentStyleSheets(document, styleSheets); |
+ for (Vector<CSSStyleSheet*>::const_iterator stylesheetIt = styleSheets.begin(); stylesheetIt != styleSheets.end(); ++stylesheetIt) { |
+ CSSStyleSheet* styleSheet = *stylesheetIt; |
+ if (styleSheet->isInline() || !styleSheet->contents()->loadCompleted()) |
+ continue; |
+ String url = styleSheet->baseURL().string(); |
+ if (url.isEmpty() || urlsToFetch.contains(url)) |
+ continue; |
+ urlsToFetch.add(url); |
+ FetchRequest request(ResourceRequest(url), FetchInitiatorTypeNames::internal); |
+ ResourcePtr<Resource> resource = document->fetcher()->fetchCSSStyleSheet(request); |
+ // Prevent garbage collection by holding a reference to this resource. |
+ m_resources.append(resource.get()); |
+ ResourceClient* resourceClient = new ResourceClient(this); |
+ m_pendingResourceClients.add(resourceClient); |
+ resourceClient->waitForResource(resource.get()); |
+ } |
+ } |
+ |
+ m_allRequestsStarted = true; |
+ checkDone(); |
+} |
+ |
+void InspectorResourceContentLoader::addListener(PassOwnPtr<VoidCallback> callback) |
+{ |
+ m_callbacks.append(callback); |
+ checkDone(); |
+} |
+ |
+InspectorResourceContentLoader::~InspectorResourceContentLoader() |
+{ |
+ stop(); |
+} |
+ |
+void InspectorResourceContentLoader::stop() |
+{ |
+ HashSet<ResourceClient*> pendingResourceClients; |
+ m_pendingResourceClients.swap(pendingResourceClients); |
+ for (HashSet<ResourceClient*>::const_iterator it = pendingResourceClients.begin(); it != pendingResourceClients.end(); ++it) |
+ (*it)->m_loader = 0; |
+ m_resources.clear(); |
+ // Make sure all callbacks are called to prevent infinite waiting time. |
+ checkDone(); |
+} |
+ |
+bool InspectorResourceContentLoader::hasFinished() |
+{ |
+ return m_allRequestsStarted && m_pendingResourceClients.size() == 0; |
+} |
+ |
+void InspectorResourceContentLoader::checkDone() |
+{ |
+ if (!hasFinished()) |
+ return; |
+ Vector<OwnPtr<VoidCallback> > callbacks; |
+ callbacks.swap(m_callbacks); |
+ for (Vector<OwnPtr<VoidCallback> >::const_iterator it = callbacks.begin(); it != callbacks.end(); ++it) |
+ (*it)->handleEvent(); |
+} |
+ |
+void InspectorResourceContentLoader::resourceFinished(ResourceClient* client) |
+{ |
+ m_pendingResourceClients.remove(client); |
+ checkDone(); |
+} |
+ |
+} // namespace WebCore |