Commit a1f4ee2e authored by vsevik@chromium.org's avatar vsevik@chromium.org

DevTools: Extract CSS resources preloading from css agent to page agent controlled loader.

R=pfeldman
BUG=354447

Review URL: https://codereview.chromium.org/347543002

git-svn-id: svn://svn.chromium.org/blink/trunk@176443 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 2708c5a6
......@@ -1247,6 +1247,7 @@
'inspector/InspectorConsoleAgent.h',
'inspector/InspectorConsoleInstrumentation.h',
'inspector/InspectorController.cpp',
'inspector/InspectorController.h',
'inspector/InspectorCounters.cpp',
'inspector/InspectorCounters.h',
'inspector/InspectorDOMAgent.cpp',
......@@ -1285,6 +1286,8 @@
'inspector/InspectorProfilerAgent.h',
'inspector/InspectorResourceAgent.cpp',
'inspector/InspectorResourceAgent.h',
'inspector/InspectorResourceContentLoader.cpp',
'inspector/InspectorResourceContentLoader.h',
'inspector/InspectorRuntimeAgent.cpp',
'inspector/InspectorRuntimeAgent.h',
'inspector/InspectorState.cpp',
......
......@@ -28,7 +28,6 @@
#include "bindings/v8/ExceptionState.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/CSSPropertyNames.h"
#include "core/FetchInitiatorTypeNames.h"
#include "core/InspectorTypeBuilder.h"
#include "core/StylePropertyShorthand.h"
#include "core/css/CSSComputedStyleDeclaration.h"
......@@ -48,15 +47,13 @@
#include "core/css/StyleSheetList.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Node.h"
#include "core/fetch/CSSStyleSheetResource.h"
#include "core/fetch/ResourceClient.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/fetch/StyleSheetResourceClient.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLHeadElement.h"
#include "core/html/VoidCallback.h"
#include "core/inspector/InspectorHistory.h"
#include "core/inspector/InspectorPageAgent.h"
#include "core/inspector/InspectorResourceAgent.h"
#include "core/inspector/InspectorResourceContentLoader.h"
#include "core/inspector/InspectorState.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/loader/DocumentLoader.h"
......@@ -127,45 +124,30 @@ public:
}
};
class InspectorCSSAgent::EnableResourceClient FINAL : public StyleSheetResourceClient {
class InspectorCSSAgent::InspectorResourceContentLoaderCallback FINAL : public VoidCallback {
public:
EnableResourceClient(InspectorCSSAgent*, const Vector<InspectorStyleSheet*>&, PassRefPtr<EnableCallback>);
virtual void setCSSStyleSheet(const String&, const KURL&, const String&, const CSSStyleSheetResource*) OVERRIDE;
InspectorResourceContentLoaderCallback(InspectorCSSAgent*, PassRefPtr<EnableCallback>);
virtual void handleEvent() OVERRIDE;
private:
RefPtr<EnableCallback> m_callback;
InspectorCSSAgent* m_cssAgent;
int m_pendingResources;
Vector<InspectorStyleSheet*> m_styleSheets;
RefPtr<EnableCallback> m_callback;
};
InspectorCSSAgent::EnableResourceClient::EnableResourceClient(InspectorCSSAgent* cssAgent, const Vector<InspectorStyleSheet*>& styleSheets, PassRefPtr<EnableCallback> callback)
: m_callback(callback)
, m_cssAgent(cssAgent)
, m_pendingResources(styleSheets.size())
, m_styleSheets(styleSheets)
InspectorCSSAgent::InspectorResourceContentLoaderCallback::InspectorResourceContentLoaderCallback(InspectorCSSAgent* cssAgent, PassRefPtr<EnableCallback> callback)
: m_cssAgent(cssAgent)
, m_callback(callback)
{
for (size_t i = 0; i < styleSheets.size(); ++i) {
InspectorStyleSheet* styleSheet = styleSheets.at(i);
Document* document = styleSheet->ownerDocument();
FetchRequest request(ResourceRequest(styleSheet->finalURL()), FetchInitiatorTypeNames::internal);
ResourcePtr<Resource> resource = document->fetcher()->fetchCSSStyleSheet(request);
resource->addClient(this);
}
}
void InspectorCSSAgent::EnableResourceClient::setCSSStyleSheet(const String&, const KURL& url, const String&, const CSSStyleSheetResource* resource)
void InspectorCSSAgent::InspectorResourceContentLoaderCallback::handleEvent()
{
const_cast<CSSStyleSheetResource*>(resource)->removeClient(this);
--m_pendingResources;
if (m_pendingResources)
// enable always succeeds.
if (!m_callback->isActive())
return;
// enable always succeeds.
if (m_callback->isActive())
m_cssAgent->wasEnabled(m_callback.release());
delete this;
m_cssAgent->wasEnabled();
m_callback->sendSuccess();
}
class InspectorCSSAgent::SetStyleSheetTextAction FINAL : public InspectorCSSAgent::StyleSheetAction {
......@@ -400,7 +382,7 @@ void InspectorCSSAgent::discardAgent()
void InspectorCSSAgent::restore()
{
if (m_state->getBoolean(CSSAgentState::cssAgentEnabled))
wasEnabled(nullptr);
wasEnabled();
}
void InspectorCSSAgent::flushPendingFrontendMessages()
......@@ -433,39 +415,15 @@ void InspectorCSSAgent::resetNonPersistentData()
void InspectorCSSAgent::enable(ErrorString*, PassRefPtr<EnableCallback> prpCallback)
{
m_state->setBoolean(CSSAgentState::cssAgentEnabled, true);
Vector<InspectorStyleSheet*> styleSheets;
collectAllStyleSheets(styleSheets);
// Re-issue stylesheet requets for resources that are no longer in memory cache.
Vector<InspectorStyleSheet*> styleSheetsToFetch;
HashSet<String> urlsToFetch;
for (size_t i = 0; i < styleSheets.size(); ++i) {
InspectorStyleSheet* styleSheet = styleSheets.at(i);
String url = styleSheet->finalURL();
if (urlsToFetch.contains(url))
continue;
CSSStyleSheet* pageStyleSheet = styleSheet->pageStyleSheet();
if (pageStyleSheet->isInline() || !pageStyleSheet->contents()->loadCompleted())
continue;
Document* document = styleSheet->ownerDocument();
if (!document)
continue;
Resource* cachedResource = document->fetcher()->cachedResource(document->completeURL(url));
if (cachedResource)
continue;
urlsToFetch.add(styleSheet->finalURL());
styleSheetsToFetch.append(styleSheet);
}
if (styleSheetsToFetch.isEmpty()) {
wasEnabled(prpCallback);
if (!m_pageAgent->resourceContentLoader()) {
wasEnabled();
prpCallback->sendSuccess();
return;
}
new EnableResourceClient(this, styleSheetsToFetch, prpCallback);
m_pageAgent->resourceContentLoader()->addListener(adoptPtr(new InspectorCSSAgent::InspectorResourceContentLoaderCallback(this, prpCallback)));
}
void InspectorCSSAgent::wasEnabled(PassRefPtr<EnableCallback> callback)
void InspectorCSSAgent::wasEnabled()
{
if (!m_state->getBoolean(CSSAgentState::cssAgentEnabled)) {
// We were disabled while fetching resources.
......@@ -476,9 +434,6 @@ void InspectorCSSAgent::wasEnabled(PassRefPtr<EnableCallback> callback)
Vector<Document*> documents = m_domAgent->documents();
for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it)
updateActiveStyleSheets(*it, InitialFrontendLoad);
if (callback)
callback->sendSuccess();
}
void InspectorCSSAgent::disable(ErrorString*)
......@@ -545,7 +500,7 @@ void InspectorCSSAgent::activeStyleSheetsUpdated(Document* document)
void InspectorCSSAgent::updateActiveStyleSheets(Document* document, StyleSheetsUpdateType styleSheetsUpdateType)
{
Vector<CSSStyleSheet*> newSheetsVector;
collectAllDocumentStyleSheets(document, newSheetsVector);
InspectorCSSAgent::collectAllDocumentStyleSheets(document, newSheetsVector);
setActiveStyleSheets(document, newSheetsVector, styleSheetsUpdateType);
}
......@@ -1167,25 +1122,17 @@ Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId)
return toElement(node);
}
void InspectorCSSAgent::collectAllStyleSheets(Vector<InspectorStyleSheet*>& result)
{
Vector<CSSStyleSheet*> cssStyleSheets;
Vector<Document*> documents = m_domAgent->documents();
for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it)
collectAllDocumentStyleSheets(*it, cssStyleSheets);
for (Vector<CSSStyleSheet*>::iterator it = cssStyleSheets.begin(); it != cssStyleSheets.end(); ++it)
result.append(bindStyleSheet(*it));
}
// static
void InspectorCSSAgent::collectAllDocumentStyleSheets(Document* document, Vector<CSSStyleSheet*>& result)
{
const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > activeStyleSheets = document->styleEngine()->activeStyleSheetsForInspector();
for (WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >::const_iterator it = activeStyleSheets.begin(); it != activeStyleSheets.end(); ++it) {
CSSStyleSheet* styleSheet = it->get();
collectStyleSheets(styleSheet, result);
InspectorCSSAgent::collectStyleSheets(styleSheet, result);
}
}
// static
void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, Vector<CSSStyleSheet*>& result)
{
result.append(styleSheet);
......@@ -1194,7 +1141,7 @@ void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, Vector<CSS
if (rule->type() == CSSRule::IMPORT_RULE) {
CSSStyleSheet* importedStyleSheet = toCSSImportRule(rule)->styleSheet();
if (importedStyleSheet)
collectStyleSheets(importedStyleSheet, result);
InspectorCSSAgent::collectStyleSheets(importedStyleSheet, result);
}
}
}
......
......@@ -100,6 +100,9 @@ public:
{
return adoptPtr(new InspectorCSSAgent(domAgent, pageAgent, resourceAgent));
}
static void collectAllDocumentStyleSheets(Document*, Vector<CSSStyleSheet*>&);
virtual ~InspectorCSSAgent();
bool forcePseudoState(Element*, CSSSelector::PseudoType);
......@@ -147,7 +150,9 @@ private:
class SetPropertyTextAction;
class SetRuleSelectorAction;
class AddRuleAction;
class EnableResourceClient;
class InspectorResourceContentLoaderCallback;
static void collectStyleSheets(CSSStyleSheet*, Vector<CSSStyleSheet*>&);
InspectorCSSAgent(InspectorDOMAgent*, InspectorPageAgent*, InspectorResourceAgent*);
......@@ -156,13 +161,10 @@ private:
typedef HashMap<Node*, RefPtr<InspectorStyleSheetForInlineStyle> > NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline styles
typedef HashMap<int, unsigned> NodeIdToForcedPseudoState;
void wasEnabled(PassRefPtr<EnableCallback>);
void wasEnabled();
void resetNonPersistentData();
InspectorStyleSheetForInlineStyle* asInspectorStyleSheet(Element* element);
Element* elementForId(ErrorString*, int nodeId);
void collectAllStyleSheets(Vector<InspectorStyleSheet*>&);
void collectAllDocumentStyleSheets(Document*, Vector<CSSStyleSheet*>&);
void collectStyleSheets(CSSStyleSheet*, Vector<CSSStyleSheet*>&);
void updateActiveStyleSheets(Document*, StyleSheetsUpdateType);
void setActiveStyleSheets(Document*, const Vector<CSSStyleSheet*>&, StyleSheetsUpdateType);
......@@ -217,7 +219,7 @@ private:
bool m_creatingViaInspectorStyleSheet;
bool m_isSettingStyleSheetText;
friend class EnableResourceClient;
friend class InspectorResourceContentLoaderCallback;
friend class StyleSheetBinder;
};
......
......@@ -62,6 +62,7 @@
#include "core/inspector/InspectorClient.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorOverlay.h"
#include "core/inspector/InspectorResourceContentLoader.h"
#include "core/inspector/InspectorState.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/loader/CookieJar.h"
......@@ -403,6 +404,7 @@ void InspectorPageAgent::enable(ErrorString*)
m_enabled = true;
m_state->setBoolean(PageAgentState::pageAgentEnabled, true);
m_instrumentingAgents->setInspectorPageAgent(this);
m_inspectorResourceContentLoader = adoptPtr(new InspectorResourceContentLoader(m_page));
}
void InspectorPageAgent::disable(ErrorString*)
......@@ -412,6 +414,7 @@ void InspectorPageAgent::disable(ErrorString*)
m_state->remove(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
m_overlay->hide();
m_instrumentingAgents->setInspectorPageAgent(0);
m_inspectorResourceContentLoader.clear();
m_deviceMetricsOverridden = false;
setShowPaintRects(0, false);
......@@ -538,7 +541,8 @@ static void cachedResourcesForDocument(Document* document, Vector<Resource*>& re
}
}
static Vector<Document*> importsForFrame(LocalFrame* frame)
// static
Vector<Document*> InspectorPageAgent::importsForFrame(LocalFrame* frame)
{
Vector<Document*> result;
Document* rootDocument = frame->document();
......@@ -557,7 +561,7 @@ static Vector<Resource*> cachedResourcesForFrame(LocalFrame* frame)
{
Vector<Resource*> result;
Document* rootDocument = frame->document();
Vector<Document*> loaders = importsForFrame(frame);
Vector<Document*> loaders = InspectorPageAgent::importsForFrame(frame);
cachedResourcesForDocument(rootDocument, result);
for (size_t i = 0; i < loaders.size(); ++i)
......@@ -857,7 +861,7 @@ void InspectorPageAgent::loadEventFired(LocalFrame* frame)
void InspectorPageAgent::didCommitLoad(LocalFrame*, DocumentLoader* loader)
{
// FIXME: If "frame" is always guarenteed to be in the same Page as loader->frame()
// FIXME: If "frame" is always guaranteed to be in the same Page as loader->frame()
// then all we need to check here is loader->frame()->isMainFrame()
// and we don't need "frame" at all.
if (loader->frame() == m_page->mainFrame()) {
......@@ -865,6 +869,8 @@ void InspectorPageAgent::didCommitLoad(LocalFrame*, DocumentLoader* loader)
m_scriptPreprocessorSource = m_pendingScriptPreprocessor;
m_pendingScriptToEvaluateOnLoadOnce = String();
m_pendingScriptPreprocessor = String();
if (m_inspectorResourceContentLoader)
m_inspectorResourceContentLoader->stop();
}
m_frontend->frameNavigated(buildObjectForFrame(loader->frame()));
}
......@@ -1117,7 +1123,7 @@ PassRefPtr<TypeBuilder::Page::FrameResourceTree> InspectorPageAgent::buildObject
subresources->addItem(resourceObject);
}
Vector<Document*> allImports = importsForFrame(frame);
Vector<Document*> allImports = InspectorPageAgent::importsForFrame(frame);
for (Vector<Document*>::const_iterator it = allImports.begin(); it != allImports.end(); ++it) {
Document* import = *it;
RefPtr<TypeBuilder::Page::FrameResourceTree::Resources> resourceObject = TypeBuilder::Page::FrameResourceTree::Resources::create()
......
......@@ -34,6 +34,7 @@
#include "core/InspectorFrontend.h"
#include "core/inspector/InspectorBaseAgent.h"
#include "core/inspector/InspectorResourceContentLoader.h"
#include "wtf/HashMap.h"
#include "wtf/text/WTFString.h"
......@@ -49,6 +50,7 @@ class GraphicsLayer;
class InjectedScriptManager;
class InspectorClient;
class InspectorOverlay;
class InspectorResourceContentLoader;
class InstrumentingAgents;
class IntSize;
class KURL;
......@@ -82,6 +84,7 @@ public:
void setTextAutosizingEnabled(bool);
void setDeviceScaleAdjustment(float);
static Vector<Document*> importsForFrame(LocalFrame*);
static bool cachedResourceContent(Resource*, String* result, bool* base64Encoded);
static bool sharedBufferContent(PassRefPtr<SharedBuffer>, const String& textEncodingName, bool withBase64Encode, String* result);
......@@ -160,6 +163,7 @@ public:
const AtomicString& resourceSourceMapURL(const String& url);
bool deviceMetricsOverrideEnabled();
static DocumentLoader* assertDocumentLoader(ErrorString*, LocalFrame*);
InspectorResourceContentLoader* resourceContentLoader() { return m_inspectorResourceContentLoader.get(); }
private:
static void resourceContent(ErrorString*, LocalFrame*, const KURL&, String* result, bool* base64Encoded);
......@@ -200,6 +204,8 @@ private:
bool m_embedderTextAutosizingEnabled;
double m_embedderFontScaleFactor;
OwnPtr<InspectorResourceContentLoader> m_inspectorResourceContentLoader;
};
......
// 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
// 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.
#ifndef InspectorResourceContentLoader_h
#define InspectorResourceContentLoader_h
#include "core/fetch/ResourcePtr.h"
#include "wtf/HashSet.h"
#include "wtf/Noncopyable.h"
#include "wtf/Vector.h"
namespace WebCore {
class CSSStyleSheetResource;
class Page;
class Resource;
class VoidCallback;
class InspectorResourceContentLoader FINAL {
WTF_MAKE_NONCOPYABLE(InspectorResourceContentLoader);
WTF_MAKE_FAST_ALLOCATED;
public:
InspectorResourceContentLoader(Page*);
void addListener(PassOwnPtr<VoidCallback>);
~InspectorResourceContentLoader();
bool hasFinished();
void stop();
private:
class ResourceClient;
void resourceFinished(ResourceClient*);
void checkDone();
Vector<OwnPtr<VoidCallback> > m_callbacks;
bool m_allRequestsStarted;
HashSet<ResourceClient*> m_pendingResourceClients;
Vector<ResourcePtr<Resource> > m_resources;
friend class ResourceClient;
};
} // namespace WebCore
#endif // !defined(InspectorResourceContentLoader_h)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment