source: trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp @ 174190

Revision 174140, 55.0 KB checked in by burg@cs.washington.edu, 20 hours ago (diff)

Web Inspector: ErrorString should be passed by reference
https://bugs.webkit.org/show_bug.cgi?id=137257

Reviewed by Joseph Pecoraro.

Pass the leading ErrorString argument by reference, since it is always an out parameter.
Clean up callsites where the error message is written.

Source/JavaScriptCore:

  • inspector/InjectedScript.cpp:

(Inspector::InjectedScript::evaluate):
(Inspector::InjectedScript::callFunctionOn):
(Inspector::InjectedScript::evaluateOnCallFrame):
(Inspector::InjectedScript::getFunctionDetails):
(Inspector::InjectedScript::getProperties):
(Inspector::InjectedScript::getInternalProperties):

  • inspector/InjectedScript.h:
  • inspector/InjectedScriptBase.cpp:

(Inspector::InjectedScriptBase::makeEvalCall):

  • inspector/InjectedScriptBase.h:
  • inspector/agents/InspectorAgent.cpp:

(Inspector::InspectorAgent::willDestroyFrontendAndBackend):
(Inspector::InspectorAgent::enable):
(Inspector::InspectorAgent::disable):
(Inspector::InspectorAgent::initialized):

  • inspector/agents/InspectorAgent.h:
  • inspector/agents/InspectorConsoleAgent.cpp:

(Inspector::InspectorConsoleAgent::willDestroyFrontendAndBackend):
(Inspector::InspectorConsoleAgent::enable):
(Inspector::InspectorConsoleAgent::disable):
(Inspector::InspectorConsoleAgent::clearMessages):
(Inspector::InspectorConsoleAgent::reset):
(Inspector::InspectorConsoleAgent::addMessageToConsole):

  • inspector/agents/InspectorConsoleAgent.h:
  • inspector/agents/InspectorDebuggerAgent.cpp:

(Inspector::InspectorDebuggerAgent::enable):
(Inspector::InspectorDebuggerAgent::disable):
(Inspector::InspectorDebuggerAgent::setBreakpointsActive):
(Inspector::InspectorDebuggerAgent::breakpointActionsFromProtocol):
(Inspector::InspectorDebuggerAgent::setBreakpointByUrl):
(Inspector::parseLocation):
(Inspector::InspectorDebuggerAgent::setBreakpoint):
(Inspector::InspectorDebuggerAgent::removeBreakpoint):
(Inspector::InspectorDebuggerAgent::continueToLocation):
(Inspector::InspectorDebuggerAgent::searchInContent):
(Inspector::InspectorDebuggerAgent::getScriptSource):
(Inspector::InspectorDebuggerAgent::getFunctionDetails):
(Inspector::InspectorDebuggerAgent::pause):
(Inspector::InspectorDebuggerAgent::resume):
(Inspector::InspectorDebuggerAgent::stepOver):
(Inspector::InspectorDebuggerAgent::stepInto):
(Inspector::InspectorDebuggerAgent::stepOut):
(Inspector::InspectorDebuggerAgent::setPauseOnExceptions):
(Inspector::InspectorDebuggerAgent::evaluateOnCallFrame):
(Inspector::InspectorDebuggerAgent::setOverlayMessage):
(Inspector::InspectorDebuggerAgent::didParseSource):
(Inspector::InspectorDebuggerAgent::clearInspectorBreakpointState):
(Inspector::InspectorDebuggerAgent::assertPaused):

  • inspector/agents/InspectorDebuggerAgent.h:
  • inspector/agents/InspectorRuntimeAgent.cpp:

(Inspector::InspectorRuntimeAgent::parse):
(Inspector::InspectorRuntimeAgent::evaluate):
(Inspector::InspectorRuntimeAgent::callFunctionOn):
(Inspector::InspectorRuntimeAgent::getProperties):
(Inspector::InspectorRuntimeAgent::releaseObject):
(Inspector::InspectorRuntimeAgent::releaseObjectGroup):
(Inspector::InspectorRuntimeAgent::run):
(Inspector::InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets):
(Inspector::InspectorRuntimeAgent::enableTypeProfiler):
(Inspector::InspectorRuntimeAgent::disableTypeProfiler):

  • inspector/agents/InspectorRuntimeAgent.h:
  • inspector/agents/JSGlobalObjectConsoleAgent.cpp:

(Inspector::JSGlobalObjectConsoleAgent::setMonitoringXHREnabled):
(Inspector::JSGlobalObjectConsoleAgent::addInspectedNode):

  • inspector/agents/JSGlobalObjectConsoleAgent.h:
  • inspector/agents/JSGlobalObjectDebuggerAgent.cpp:

(Inspector::JSGlobalObjectDebuggerAgent::injectedScriptForEval):

  • inspector/agents/JSGlobalObjectDebuggerAgent.h:
  • inspector/agents/JSGlobalObjectRuntimeAgent.cpp:

(Inspector::JSGlobalObjectRuntimeAgent::injectedScriptForEval):

  • inspector/agents/JSGlobalObjectRuntimeAgent.h:
  • inspector/scripts/codegen/generate_backend_dispatcher_header.py:

(BackendDispatcherHeaderGenerator._generate_handler_declaration_for_command):
(BackendDispatcherHeaderGenerator._generate_async_handler_declaration_for_command):

  • inspector/scripts/codegen/generate_backend_dispatcher_implementation.py:

(BackendDispatcherImplementationGenerator._generate_dispatcher_implementation_for_command):

  • inspector/scripts/tests/expected/commands-with-async-attribute.json-result:
  • inspector/scripts/tests/expected/commands-with-optional-call-return-parameters.json-result:
  • inspector/scripts/tests/expected/domains-with-varying-command-sizes.json-result:
  • inspector/scripts/tests/expected/generate-domains-with-feature-guards.json-result:

Source/WebCore:

No new tests, no behavior changed.

  • inspector/CommandLineAPIHost.cpp:

(WebCore::CommandLineAPIHost::clearConsoleMessages):

  • inspector/DOMEditor.cpp:

(WebCore::populateErrorString):
(WebCore::DOMEditor::insertBefore):
(WebCore::DOMEditor::removeChild):
(WebCore::DOMEditor::setAttribute):
(WebCore::DOMEditor::removeAttribute):
(WebCore::DOMEditor::setOuterHTML):
(WebCore::DOMEditor::replaceWholeText):

  • inspector/DOMEditor.h:
  • inspector/InspectorApplicationCacheAgent.cpp:

(WebCore::InspectorApplicationCacheAgent::enable):
(WebCore::InspectorApplicationCacheAgent::getFramesWithManifests):
(WebCore::InspectorApplicationCacheAgent::assertFrameWithDocumentLoader):
(WebCore::InspectorApplicationCacheAgent::getManifestForFrame):
(WebCore::InspectorApplicationCacheAgent::getApplicationCacheForFrame):

  • inspector/InspectorApplicationCacheAgent.h:
  • inspector/InspectorCSSAgent.cpp:

(WebCore::InspectorCSSAgent::enable):
(WebCore::InspectorCSSAgent::disable):
(WebCore::InspectorCSSAgent::didCreateNamedFlow):
(WebCore::InspectorCSSAgent::regionOversetChanged):
(WebCore::InspectorCSSAgent::didRegisterNamedFlowContentElement):
(WebCore::InspectorCSSAgent::didUnregisterNamedFlowContentElement):
(WebCore::InspectorCSSAgent::getMatchedStylesForNode):
(WebCore::InspectorCSSAgent::getInlineStylesForNode):
(WebCore::InspectorCSSAgent::getComputedStyleForNode):
(WebCore::InspectorCSSAgent::getAllStyleSheets):
(WebCore::InspectorCSSAgent::getStyleSheet):
(WebCore::InspectorCSSAgent::getStyleSheetText):
(WebCore::InspectorCSSAgent::setStyleSheetText):
(WebCore::InspectorCSSAgent::setStyleText):
(WebCore::InspectorCSSAgent::setPropertyText):
(WebCore::InspectorCSSAgent::toggleProperty):
(WebCore::InspectorCSSAgent::setRuleSelector):
(WebCore::InspectorCSSAgent::addRule):
(WebCore::InspectorCSSAgent::getSupportedCSSProperties):
(WebCore::InspectorCSSAgent::forcePseudoState):
(WebCore::InspectorCSSAgent::getNamedFlowCollection):
(WebCore::InspectorCSSAgent::elementForId):
(WebCore::InspectorCSSAgent::assertStyleSheetForId):
(WebCore::InspectorCSSAgent::buildArrayForRegions):
(WebCore::InspectorCSSAgent::buildObjectForNamedFlow):

  • inspector/InspectorCSSAgent.h:
  • inspector/InspectorController.cpp:

(WebCore::InspectorController::hideHighlight):
(WebCore::InspectorController::setProfilerEnabled):
(WebCore::InspectorController::resume):

  • inspector/InspectorDOMAgent.cpp:

(WebCore::InspectorDOMAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorDOMAgent::assertNode):
(WebCore::InspectorDOMAgent::assertDocument):
(WebCore::InspectorDOMAgent::assertElement):
(WebCore::InspectorDOMAgent::assertEditableNode):
(WebCore::InspectorDOMAgent::assertEditableElement):
(WebCore::InspectorDOMAgent::getDocument):
(WebCore::InspectorDOMAgent::pushNodeToFrontend):
(WebCore::InspectorDOMAgent::requestChildNodes):
(WebCore::InspectorDOMAgent::querySelector):
(WebCore::InspectorDOMAgent::querySelectorAll):
(WebCore::InspectorDOMAgent::releaseBackendNodeIds):
(WebCore::InspectorDOMAgent::setAttributeValue):
(WebCore::InspectorDOMAgent::setAttributesAsText):
(WebCore::InspectorDOMAgent::removeAttribute):
(WebCore::InspectorDOMAgent::removeNode):
(WebCore::InspectorDOMAgent::setNodeName):
(WebCore::InspectorDOMAgent::getOuterHTML):
(WebCore::InspectorDOMAgent::setOuterHTML):
(WebCore::InspectorDOMAgent::setNodeValue):
(WebCore::InspectorDOMAgent::getEventListenersForNode):
(WebCore::InspectorDOMAgent::getAccessibilityPropertiesForNode):
(WebCore::InspectorDOMAgent::performSearch):
(WebCore::InspectorDOMAgent::getSearchResults):
(WebCore::InspectorDOMAgent::discardSearchResults):
(WebCore::InspectorDOMAgent::inspect):
(WebCore::InspectorDOMAgent::setSearchingForNode):
(WebCore::InspectorDOMAgent::highlightConfigFromInspectorObject):
(WebCore::InspectorDOMAgent::setInspectModeEnabled):
(WebCore::InspectorDOMAgent::highlightRect):
(WebCore::InspectorDOMAgent::highlightQuad):
(WebCore::InspectorDOMAgent::highlightNode):
(WebCore::InspectorDOMAgent::highlightFrame):
(WebCore::InspectorDOMAgent::hideHighlight):
(WebCore::InspectorDOMAgent::moveTo):
(WebCore::InspectorDOMAgent::undo):
(WebCore::InspectorDOMAgent::redo):
(WebCore::InspectorDOMAgent::markUndoableState):
(WebCore::InspectorDOMAgent::focus):
(WebCore::InspectorDOMAgent::resolveNode):
(WebCore::InspectorDOMAgent::getAttributes):
(WebCore::InspectorDOMAgent::requestNode):
(WebCore::InspectorDOMAgent::pushNodeByPathToFrontend):
(WebCore::InspectorDOMAgent::pushNodeByBackendIdToFrontend):

  • inspector/InspectorDOMAgent.h:
  • inspector/InspectorDOMDebuggerAgent.cpp:

(WebCore::InspectorDOMDebuggerAgent::setEventListenerBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::setInstrumentationBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::setBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::removeEventListenerBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::removeBreakpoint):
(WebCore::domTypeForName):
(WebCore::InspectorDOMDebuggerAgent::setDOMBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::removeDOMBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::setXHRBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::removeXHRBreakpoint):
(WebCore::InspectorDOMDebuggerAgent::willSendXMLHttpRequest):

  • inspector/InspectorDOMDebuggerAgent.h:
  • inspector/InspectorDOMStorageAgent.cpp:

(WebCore::InspectorDOMStorageAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorDOMStorageAgent::enable):
(WebCore::InspectorDOMStorageAgent::disable):
(WebCore::InspectorDOMStorageAgent::getDOMStorageItems):
(WebCore::InspectorDOMStorageAgent::setDOMStorageItem):
(WebCore::InspectorDOMStorageAgent::removeDOMStorageItem):
(WebCore::InspectorDOMStorageAgent::findStorageArea):

  • inspector/InspectorDOMStorageAgent.h:
  • inspector/InspectorDatabaseAgent.cpp:

(WebCore::InspectorDatabaseAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorDatabaseAgent::enable):
(WebCore::InspectorDatabaseAgent::disable):
(WebCore::InspectorDatabaseAgent::getDatabaseTableNames):
(WebCore::InspectorDatabaseAgent::executeSQL):

  • inspector/InspectorDatabaseAgent.h:
  • inspector/InspectorIndexedDBAgent.cpp:

(WebCore::InspectorIndexedDBAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorIndexedDBAgent::enable):
(WebCore::InspectorIndexedDBAgent::disable):
(WebCore::assertDocument):
(WebCore::assertIDBFactory):
(WebCore::InspectorIndexedDBAgent::requestDatabaseNames):
(WebCore::InspectorIndexedDBAgent::requestDatabase):
(WebCore::InspectorIndexedDBAgent::requestData):
(WebCore::InspectorIndexedDBAgent::clearObjectStore):

  • inspector/InspectorIndexedDBAgent.h:
  • inspector/InspectorLayerTreeAgent.cpp:

(WebCore::InspectorLayerTreeAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorLayerTreeAgent::enable):
(WebCore::InspectorLayerTreeAgent::disable):
(WebCore::InspectorLayerTreeAgent::layersForNode):
(WebCore::InspectorLayerTreeAgent::gatherLayersUsingRenderObjectHierarchy):
(WebCore::InspectorLayerTreeAgent::gatherLayersUsingRenderLayerHierarchy):
(WebCore::InspectorLayerTreeAgent::buildObjectForLayer):
(WebCore::InspectorLayerTreeAgent::idForNode):
(WebCore::InspectorLayerTreeAgent::reasonsForCompositingLayer):

  • inspector/InspectorLayerTreeAgent.h:
  • inspector/InspectorPageAgent.cpp:

(WebCore::InspectorPageAgent::cachedResourceContent):
(WebCore::InspectorPageAgent::resourceContent):
(WebCore::InspectorPageAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorPageAgent::enable):
(WebCore::InspectorPageAgent::disable):
(WebCore::InspectorPageAgent::addScriptToEvaluateOnLoad):
(WebCore::InspectorPageAgent::removeScriptToEvaluateOnLoad):
(WebCore::InspectorPageAgent::reload):
(WebCore::InspectorPageAgent::navigate):
(WebCore::InspectorPageAgent::getCookies):
(WebCore::InspectorPageAgent::deleteCookie):
(WebCore::InspectorPageAgent::getResourceTree):
(WebCore::InspectorPageAgent::getResourceContent):
(WebCore::InspectorPageAgent::searchInResource):
(WebCore::InspectorPageAgent::searchInResources):
(WebCore::InspectorPageAgent::setDocumentContent):
(WebCore::InspectorPageAgent::setShowPaintRects):
(WebCore::InspectorPageAgent::canShowDebugBorders):
(WebCore::InspectorPageAgent::setShowDebugBorders):
(WebCore::InspectorPageAgent::canShowFPSCounter):
(WebCore::InspectorPageAgent::setShowFPSCounter):
(WebCore::InspectorPageAgent::canContinuouslyPaint):
(WebCore::InspectorPageAgent::setContinuousPaintingEnabled):
(WebCore::InspectorPageAgent::getScriptExecutionStatus):
(WebCore::InspectorPageAgent::setScriptExecutionDisabled):
(WebCore::InspectorPageAgent::assertFrame):
(WebCore::InspectorPageAgent::assertDocumentLoader):
(WebCore::InspectorPageAgent::setTouchEmulationEnabled):
(WebCore::InspectorPageAgent::setEmulatedMedia):
(WebCore::InspectorPageAgent::getCompositingBordersVisible):
(WebCore::InspectorPageAgent::setCompositingBordersVisible):
(WebCore::InspectorPageAgent::snapshotNode):
(WebCore::InspectorPageAgent::snapshotRect):
(WebCore::InspectorPageAgent::handleJavaScriptDialog):
(WebCore::InspectorPageAgent::archive):

  • inspector/InspectorPageAgent.h:
  • inspector/InspectorReplayAgent.cpp:

(WebCore::InspectorReplayAgent::startCapturing):
(WebCore::InspectorReplayAgent::stopCapturing):
(WebCore::InspectorReplayAgent::replayToPosition):
(WebCore::InspectorReplayAgent::replayToCompletion):
(WebCore::InspectorReplayAgent::pausePlayback):
(WebCore::InspectorReplayAgent::cancelPlayback):
(WebCore::InspectorReplayAgent::switchSession):
(WebCore::InspectorReplayAgent::insertSessionSegment):
(WebCore::InspectorReplayAgent::removeSessionSegment):
(WebCore::InspectorReplayAgent::findSession):
(WebCore::InspectorReplayAgent::findSegment):
(WebCore::InspectorReplayAgent::currentReplayState):
(WebCore::InspectorReplayAgent::getAvailableSessions):
(WebCore::InspectorReplayAgent::getSessionData):
(WebCore::InspectorReplayAgent::getSegmentData):

  • inspector/InspectorReplayAgent.h:
  • inspector/InspectorResourceAgent.cpp:

(WebCore::InspectorResourceAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorResourceAgent::~InspectorResourceAgent):
(WebCore::InspectorResourceAgent::enable):
(WebCore::InspectorResourceAgent::disable):
(WebCore::InspectorResourceAgent::setExtraHTTPHeaders):
(WebCore::InspectorResourceAgent::getResponseBody):
(WebCore::InspectorResourceAgent::replayXHR):
(WebCore::InspectorResourceAgent::canClearBrowserCache):
(WebCore::InspectorResourceAgent::clearBrowserCache):
(WebCore::InspectorResourceAgent::canClearBrowserCookies):
(WebCore::InspectorResourceAgent::clearBrowserCookies):
(WebCore::InspectorResourceAgent::setCacheDisabled):
(WebCore::InspectorResourceAgent::loadResource):

  • inspector/InspectorResourceAgent.h:
  • inspector/InspectorStyleSheet.cpp:

(WebCore::InspectorStyleSheet::resourceStyleSheetText):

  • inspector/InspectorTimelineAgent.cpp:

(WebCore::InspectorTimelineAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorTimelineAgent::start):
(WebCore::InspectorTimelineAgent::stop):

  • inspector/InspectorTimelineAgent.h:
  • inspector/InspectorWorkerAgent.cpp:

(WebCore::InspectorWorkerAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorWorkerAgent::enable):
(WebCore::InspectorWorkerAgent::disable):
(WebCore::InspectorWorkerAgent::canInspectWorkers):
(WebCore::InspectorWorkerAgent::connectToWorker):
(WebCore::InspectorWorkerAgent::disconnectFromWorker):
(WebCore::InspectorWorkerAgent::sendMessageToWorker):
(WebCore::InspectorWorkerAgent::setAutoconnectToWorkers):

  • inspector/InspectorWorkerAgent.h:
  • inspector/PageConsoleAgent.cpp:

(WebCore::PageConsoleAgent::clearMessages):
(WebCore::PageConsoleAgent::addInspectedNode):

  • inspector/PageConsoleAgent.h:
  • inspector/PageDebuggerAgent.cpp:

(WebCore::PageDebuggerAgent::injectedScriptForEval):
(WebCore::PageDebuggerAgent::setOverlayMessage):

  • inspector/PageDebuggerAgent.h:
  • inspector/PageRuntimeAgent.cpp:

(WebCore::PageRuntimeAgent::willDestroyFrontendAndBackend):
(WebCore::PageRuntimeAgent::enable):
(WebCore::PageRuntimeAgent::disable):
(WebCore::PageRuntimeAgent::injectedScriptForEval):

  • inspector/PageRuntimeAgent.h:
  • inspector/WebConsoleAgent.cpp:

(WebCore::WebConsoleAgent::setMonitoringXHREnabled):

  • inspector/WebConsoleAgent.h:
  • inspector/WorkerConsoleAgent.cpp:

(WebCore::WorkerConsoleAgent::addInspectedNode):

  • inspector/WorkerConsoleAgent.h:
  • inspector/WorkerDebuggerAgent.cpp:

(WebCore::WorkerDebuggerAgent::injectedScriptForEval):

  • inspector/WorkerDebuggerAgent.h:
  • inspector/WorkerInspectorController.cpp:

(WebCore::WorkerInspectorController::resume):

  • inspector/WorkerRuntimeAgent.cpp:

(WebCore::WorkerRuntimeAgent::injectedScriptForEval):
(WebCore::WorkerRuntimeAgent::run):

  • inspector/WorkerRuntimeAgent.h:
  • Property svn:eol-style set to native
Line 
1/*
2 * Copyright (C) 2010, Google Inc. 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
6 * are met:
7 * 1.  Redistributions of source code must retain the above copyright
8 *     notice, this list of conditions and the following disclaimer.
9 * 2.  Redistributions in binary form must reproduce the above copyright
10 *     notice, this list of conditions and the following disclaimer in the
11 *     documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "config.h"
26
27#if ENABLE(INSPECTOR)
28
29#include "InspectorStyleSheet.h"
30
31#include "CSSImportRule.h"
32#include "CSSMediaRule.h"
33#include "CSSParser.h"
34#include "CSSPropertyNames.h"
35#include "CSSPropertySourceData.h"
36#include "CSSRule.h"
37#include "CSSRuleList.h"
38#include "CSSStyleRule.h"
39#include "CSSStyleSheet.h"
40#include "CSSSupportsRule.h"
41#include "ContentSecurityPolicy.h"
42#include "Document.h"
43#include "Element.h"
44#include "HTMLHeadElement.h"
45#include "HTMLNames.h"
46#include "HTMLParserIdioms.h"
47#include "HTMLStyleElement.h"
48#include "InspectorCSSAgent.h"
49#include "InspectorPageAgent.h"
50#include "Node.h"
51#include "SVGElement.h"
52#include "SVGNames.h"
53#include "StyleProperties.h"
54#include "StyleResolver.h"
55#include "StyleRule.h"
56#include "StyleRuleImport.h"
57#include "StyleSheetContents.h"
58#include "StyleSheetList.h"
59#include "WebKitCSSKeyframesRule.h"
60#include <inspector/ContentSearchUtilities.h>
61#include <inspector/InspectorValues.h>
62#include <wtf/Vector.h>
63#include <wtf/text/StringBuilder.h>
64#include <yarr/RegularExpression.h>
65
66using Inspector::Protocol::Array;
67using WebCore::RuleSourceDataList;
68using WebCore::CSSRuleSourceData;
69
70class ParsedStyleSheet {
71    WTF_MAKE_FAST_ALLOCATED;
72public:
73    ParsedStyleSheet();
74
75    const String& text() const { ASSERT(m_hasText); return m_text; }
76    void setText(const String& text);
77    bool hasText() const { return m_hasText; }
78    RuleSourceDataList* sourceData() const { return m_sourceData.get(); }
79    void setSourceData(std::unique_ptr<RuleSourceDataList>);
80    bool hasSourceData() const { return m_sourceData != nullptr; }
81    PassRefPtr<WebCore::CSSRuleSourceData> ruleSourceDataAt(unsigned) const;
82
83private:
84
85    String m_text;
86    bool m_hasText;
87    std::unique_ptr<RuleSourceDataList> m_sourceData;
88};
89
90ParsedStyleSheet::ParsedStyleSheet()
91    : m_hasText(false)
92{
93}
94
95void ParsedStyleSheet::setText(const String& text)
96{
97    m_hasText = true;
98    m_text = text;
99    setSourceData(nullptr);
100}
101
102static void flattenSourceData(RuleSourceDataList* dataList, RuleSourceDataList* target)
103{
104    for (size_t i = 0; i < dataList->size(); ++i) {
105        RefPtr<CSSRuleSourceData>& data = dataList->at(i);
106        if (data->type == CSSRuleSourceData::STYLE_RULE)
107            target->append(data);
108        else if (data->type == CSSRuleSourceData::MEDIA_RULE)
109            flattenSourceData(&data->childRules, target);
110#if ENABLE(CSS3_CONDITIONAL_RULES)
111        else if (data->type == CSSRuleSourceData::SUPPORTS_RULE)
112            flattenSourceData(&data->childRules, target);
113#endif
114    }
115}
116
117void ParsedStyleSheet::setSourceData(std::unique_ptr<RuleSourceDataList> sourceData)
118{
119    if (!sourceData) {
120        m_sourceData.reset();
121        return;
122    }
123
124    m_sourceData = std::make_unique<RuleSourceDataList>();
125
126    // FIXME: This is a temporary solution to retain the original flat sourceData structure
127    // containing only style rules, even though CSSParser now provides the full rule source data tree.
128    // Normally, we should just assign m_sourceData = sourceData;
129    flattenSourceData(sourceData.get(), m_sourceData.get());
130}
131
132PassRefPtr<WebCore::CSSRuleSourceData> ParsedStyleSheet::ruleSourceDataAt(unsigned index) const
133{
134    if (!hasSourceData() || index >= m_sourceData->size())
135        return nullptr;
136
137    return m_sourceData->at(index);
138}
139
140using namespace Inspector;
141
142namespace WebCore {
143
144enum MediaListSource {
145    MediaListSourceLinkedSheet,
146    MediaListSourceInlineSheet,
147    MediaListSourceMediaRule,
148    MediaListSourceImportRule
149};
150
151static PassRefPtr<Inspector::Protocol::CSS::SourceRange> buildSourceRangeObject(const SourceRange& range, Vector<size_t>* lineEndings)
152{
153    if (!lineEndings)
154        return nullptr;
155    TextPosition start = ContentSearchUtilities::textPositionFromOffset(range.start, *lineEndings);
156    TextPosition end = ContentSearchUtilities::textPositionFromOffset(range.end, *lineEndings);
157
158    RefPtr<Inspector::Protocol::CSS::SourceRange> result = Inspector::Protocol::CSS::SourceRange::create()
159        .setStartLine(start.m_line.zeroBasedInt())
160        .setStartColumn(start.m_column.zeroBasedInt())
161        .setEndLine(end.m_line.zeroBasedInt())
162        .setEndColumn(end.m_column.zeroBasedInt());
163    return result.release();
164}
165
166static PassRefPtr<Inspector::Protocol::CSS::CSSMedia> buildMediaObject(const MediaList* media, MediaListSource mediaListSource, const String& sourceURL)
167{
168    // Make certain compilers happy by initializing |source| up-front.
169    Inspector::Protocol::CSS::CSSMedia::Source source = Inspector::Protocol::CSS::CSSMedia::Source::InlineSheet;
170    switch (mediaListSource) {
171    case MediaListSourceMediaRule:
172        source = Inspector::Protocol::CSS::CSSMedia::Source::MediaRule;
173        break;
174    case MediaListSourceImportRule:
175        source = Inspector::Protocol::CSS::CSSMedia::Source::ImportRule;
176        break;
177    case MediaListSourceLinkedSheet:
178        source = Inspector::Protocol::CSS::CSSMedia::Source::LinkedSheet;
179        break;
180    case MediaListSourceInlineSheet:
181        source = Inspector::Protocol::CSS::CSSMedia::Source::InlineSheet;
182        break;
183    }
184
185    RefPtr<Inspector::Protocol::CSS::CSSMedia> mediaObject = Inspector::Protocol::CSS::CSSMedia::create()
186        .setText(media->mediaText())
187        .setSource(source);
188
189    if (!sourceURL.isEmpty()) {
190        mediaObject->setSourceURL(sourceURL);
191        mediaObject->setSourceLine(media->queries()->lastLine());
192    }
193    return mediaObject.release();
194}
195
196static PassRefPtr<CSSRuleList> asCSSRuleList(CSSStyleSheet* styleSheet)
197{
198    if (!styleSheet)
199        return nullptr;
200
201    RefPtr<StaticCSSRuleList> list = StaticCSSRuleList::create();
202    Vector<RefPtr<CSSRule>>& listRules = list->rules();
203    for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
204        CSSRule* item = styleSheet->item(i);
205        if (item->type() == CSSRule::CHARSET_RULE)
206            continue;
207        listRules.append(item);
208    }
209    return list.release();
210}
211
212static PassRefPtr<CSSRuleList> asCSSRuleList(CSSRule* rule)
213{
214    if (!rule)
215        return nullptr;
216
217    if (rule->type() == CSSRule::MEDIA_RULE)
218        return &toCSSMediaRule(rule)->cssRules();
219
220    if (rule->type() == CSSRule::WEBKIT_KEYFRAMES_RULE)
221        return &static_cast<WebKitCSSKeyframesRule*>(rule)->cssRules();
222
223#if ENABLE(CSS3_CONDITIONAL_RULES)
224    if (rule->type() == CSSRule::SUPPORTS_RULE)
225        return &toCSSSupportsRule(rule)->cssRules();
226#endif
227
228    return nullptr;
229}
230
231static void fillMediaListChain(CSSRule* rule, Array<Inspector::Protocol::CSS::CSSMedia>* mediaArray)
232{
233    MediaList* mediaList;
234    CSSRule* parentRule = rule;
235    String sourceURL;
236    while (parentRule) {
237        CSSStyleSheet* parentStyleSheet = nullptr;
238        bool isMediaRule = true;
239        if (parentRule->type() == CSSRule::MEDIA_RULE) {
240            CSSMediaRule* mediaRule = toCSSMediaRule(parentRule);
241            mediaList = mediaRule->media();
242            parentStyleSheet = mediaRule->parentStyleSheet();
243        } else if (parentRule->type() == CSSRule::IMPORT_RULE) {
244            CSSImportRule* importRule = toCSSImportRule(parentRule);
245            mediaList = &importRule->media();
246            parentStyleSheet = importRule->parentStyleSheet();
247            isMediaRule = false;
248        } else
249            mediaList = nullptr;
250
251        if (parentStyleSheet) {
252            sourceURL = parentStyleSheet->contents().baseURL();
253            if (sourceURL.isEmpty())
254                sourceURL = InspectorDOMAgent::documentURLString(parentStyleSheet->ownerDocument());
255        } else
256            sourceURL = "";
257
258        if (mediaList && mediaList->length())
259            mediaArray->addItem(buildMediaObject(mediaList, isMediaRule ? MediaListSourceMediaRule : MediaListSourceImportRule, sourceURL));
260
261        if (parentRule->parentRule())
262            parentRule = parentRule->parentRule();
263        else {
264            CSSStyleSheet* styleSheet = parentRule->parentStyleSheet();
265            while (styleSheet) {
266                mediaList = styleSheet->media();
267                if (mediaList && mediaList->length()) {
268                    Document* doc = styleSheet->ownerDocument();
269                    if (doc)
270                        sourceURL = doc->url();
271                    else if (!styleSheet->contents().baseURL().isEmpty())
272                        sourceURL = styleSheet->contents().baseURL();
273                    else
274                        sourceURL = "";
275                    mediaArray->addItem(buildMediaObject(mediaList, styleSheet->ownerNode() ? MediaListSourceLinkedSheet : MediaListSourceInlineSheet, sourceURL));
276                }
277                parentRule = styleSheet->ownerRule();
278                if (parentRule)
279                    break;
280                styleSheet = styleSheet->parentStyleSheet();
281            }
282        }
283    }
284}
285
286static std::unique_ptr<CSSParser> createCSSParser(Document* document)
287{
288    return std::make_unique<CSSParser>(document ? CSSParserContext(*document) : strictCSSParserContext());
289}
290
291PassRefPtr<InspectorStyle> InspectorStyle::create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet)
292{
293    return adoptRef(new InspectorStyle(styleId, style, parentStyleSheet));
294}
295
296InspectorStyle::InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet)
297    : m_styleId(styleId)
298    , m_style(style)
299    , m_parentStyleSheet(parentStyleSheet)
300    , m_formatAcquired(false)
301{
302    ASSERT(m_style);
303}
304
305InspectorStyle::~InspectorStyle()
306{
307}
308
309PassRefPtr<Inspector::Protocol::CSS::CSSStyle> InspectorStyle::buildObjectForStyle() const
310{
311    RefPtr<Inspector::Protocol::CSS::CSSStyle> result = styleWithProperties();
312    if (!m_styleId.isEmpty())
313        result->setStyleId(m_styleId.asProtocolValue<Inspector::Protocol::CSS::CSSStyleId>());
314
315    result->setWidth(m_style->getPropertyValue("width"));
316    result->setHeight(m_style->getPropertyValue("height"));
317
318    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
319    if (sourceData)
320        result->setRange(buildSourceRangeObject(sourceData->ruleBodyRange, m_parentStyleSheet->lineEndings().get()));
321
322    return result.release();
323}
324
325PassRefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSComputedStyleProperty>> InspectorStyle::buildArrayForComputedStyle() const
326{
327    RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSComputedStyleProperty>> result = Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSComputedStyleProperty>::create();
328    Vector<InspectorStyleProperty> properties;
329    populateAllProperties(&properties);
330
331    for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) {
332        const CSSPropertySourceData& propertyEntry = it->sourceData;
333        RefPtr<Inspector::Protocol::CSS::CSSComputedStyleProperty> entry = Inspector::Protocol::CSS::CSSComputedStyleProperty::create()
334            .setName(propertyEntry.name)
335            .setValue(propertyEntry.value);
336        result->addItem(entry);
337    }
338
339    return result.release();
340}
341
342// This method does the following preprocessing of |propertyText| with |overwrite| == false and |index| past the last active property:
343// - If the last property (if present) has no closing ";", the ";" is prepended to the current |propertyText| value.
344// - A heuristic formatting is attempted to retain the style structure.
345//
346// The propertyText (if not empty) is checked to be a valid style declaration (containing at least one property). If not,
347// the method returns false (denoting an error).
348bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, bool overwrite, String* oldText, ExceptionCode& ec)
349{
350    ASSERT(m_parentStyleSheet);
351    DEPRECATED_DEFINE_STATIC_LOCAL(String, bogusPropertyName, (ASCIILiteral("-webkit-boguz-propertee")));
352
353    if (!m_parentStyleSheet->ensureParsedDataReady()) {
354        ec = NOT_FOUND_ERR;
355        return false;
356    }
357
358    if (propertyText.stripWhiteSpace().length()) {
359        RefPtr<MutableStyleProperties> tempMutableStyle = MutableStyleProperties::create();
360        RefPtr<CSSRuleSourceData> sourceData = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE);
361        Document* ownerDocument = m_parentStyleSheet->pageStyleSheet() ? m_parentStyleSheet->pageStyleSheet()->ownerDocument() : nullptr;
362        createCSSParser(ownerDocument)->parseDeclaration(tempMutableStyle.get(), propertyText + " " + bogusPropertyName + ": none", sourceData, &m_style->parentStyleSheet()->contents());
363        Vector<CSSPropertySourceData>& propertyData = sourceData->styleSourceData->propertyData;
364        unsigned propertyCount = propertyData.size();
365
366        // At least one property + the bogus property added just above should be present.
367        if (propertyCount < 2) {
368            ec = SYNTAX_ERR;
369            return false;
370        }
371
372        // Check for a proper propertyText termination (the parser could at least restore to the PROPERTY_NAME state).
373        if (propertyData.at(propertyCount - 1).name != bogusPropertyName) {
374            ec = SYNTAX_ERR;
375            return false;
376        }
377    }
378
379    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
380    if (!sourceData) {
381        ec = NOT_FOUND_ERR;
382        return false;
383    }
384
385    String text;
386    bool success = styleText(&text);
387    if (!success) {
388        ec = NOT_FOUND_ERR;
389        return false;
390    }
391
392    Vector<InspectorStyleProperty> allProperties;
393    populateAllProperties(&allProperties);
394
395    InspectorStyleTextEditor editor(&allProperties, &m_disabledProperties, text, newLineAndWhitespaceDelimiters());
396    if (overwrite) {
397        if (index >= allProperties.size()) {
398            ec = INDEX_SIZE_ERR;
399            return false;
400        }
401        *oldText = allProperties.at(index).rawText;
402        editor.replaceProperty(index, propertyText);
403    } else
404        editor.insertProperty(index, propertyText, sourceData->ruleBodyRange.length());
405
406    return applyStyleText(editor.styleText());
407}
408
409bool InspectorStyle::toggleProperty(unsigned index, bool disable, ExceptionCode& ec)
410{
411    ASSERT(m_parentStyleSheet);
412    if (!m_parentStyleSheet->ensureParsedDataReady()) {
413        ec = NO_MODIFICATION_ALLOWED_ERR;
414        return false;
415    }
416
417    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
418    if (!sourceData) {
419        ec = NOT_FOUND_ERR;
420        return false;
421    }
422
423    String text;
424    bool success = styleText(&text);
425    if (!success) {
426        ec = NOT_FOUND_ERR;
427        return false;
428    }
429
430    Vector<InspectorStyleProperty> allProperties;
431    populateAllProperties(&allProperties);
432    if (index >= allProperties.size()) {
433        ec = INDEX_SIZE_ERR;
434        return false;
435    }
436
437    InspectorStyleProperty& property = allProperties.at(index);
438    if (property.disabled == disable)
439        return true; // Idempotent operation.
440
441    InspectorStyleTextEditor editor(&allProperties, &m_disabledProperties, text, newLineAndWhitespaceDelimiters());
442    if (disable)
443        editor.disableProperty(index);
444    else
445        editor.enableProperty(index);
446
447    return applyStyleText(editor.styleText());
448}
449
450bool InspectorStyle::getText(String* result) const
451{
452    // Precondition: m_parentStyleSheet->ensureParsedDataReady() has been called successfully.
453    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
454    if (!sourceData)
455        return false;
456
457    String styleSheetText;
458    bool success = m_parentStyleSheet->getText(&styleSheetText);
459    if (!success)
460        return false;
461
462    SourceRange& bodyRange = sourceData->ruleBodyRange;
463    *result = styleSheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start);
464    return true;
465}
466
467bool InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>* result) const
468{
469    HashSet<String> sourcePropertyNames;
470    unsigned disabledIndex = 0;
471    unsigned disabledLength = m_disabledProperties.size();
472    InspectorStyleProperty disabledProperty;
473    if (disabledIndex < disabledLength)
474        disabledProperty = m_disabledProperties.at(disabledIndex);
475
476    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
477    Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : nullptr;
478    if (sourcePropertyData) {
479        String styleDeclaration;
480        bool isStyleTextKnown = styleText(&styleDeclaration);
481        ASSERT_UNUSED(isStyleTextKnown, isStyleTextKnown);
482        for (Vector<CSSPropertySourceData>::const_iterator it = sourcePropertyData->begin(); it != sourcePropertyData->end(); ++it) {
483            while (disabledIndex < disabledLength && disabledProperty.sourceData.range.start <= it->range.start) {
484                result->append(disabledProperty);
485                if (++disabledIndex < disabledLength)
486                    disabledProperty = m_disabledProperties.at(disabledIndex);
487            }
488            InspectorStyleProperty p(*it, true, false);
489            p.setRawTextFromStyleDeclaration(styleDeclaration);
490            result->append(p);
491            sourcePropertyNames.add(it->name.lower());
492        }
493    }
494
495    while (disabledIndex < disabledLength) {
496        disabledProperty = m_disabledProperties.at(disabledIndex++);
497        result->append(disabledProperty);
498    }
499
500    for (int i = 0, size = m_style->length(); i < size; ++i) {
501        String name = m_style->item(i);
502        if (sourcePropertyNames.contains(name.lower()))
503            continue;
504
505        sourcePropertyNames.add(name.lower());
506        result->append(InspectorStyleProperty(CSSPropertySourceData(name, m_style->getPropertyValue(name), !m_style->getPropertyPriority(name).isEmpty(), true, SourceRange()), false, false));
507    }
508
509    return true;
510}
511
512PassRefPtr<Inspector::Protocol::CSS::CSSStyle> InspectorStyle::styleWithProperties() const
513{
514    Vector<InspectorStyleProperty> properties;
515    populateAllProperties(&properties);
516
517    RefPtr<Array<Inspector::Protocol::CSS::CSSProperty>> propertiesObject = Array<Inspector::Protocol::CSS::CSSProperty>::create();
518    RefPtr<Array<Inspector::Protocol::CSS::ShorthandEntry>> shorthandEntries = Array<Inspector::Protocol::CSS::ShorthandEntry>::create();
519    HashMap<String, RefPtr<Inspector::Protocol::CSS::CSSProperty>> propertyNameToPreviousActiveProperty;
520    HashSet<String> foundShorthands;
521    String previousPriority;
522    String previousStatus;
523    std::unique_ptr<Vector<size_t>> lineEndings(m_parentStyleSheet ? m_parentStyleSheet->lineEndings() : nullptr);
524    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
525    unsigned ruleBodyRangeStart = sourceData ? sourceData->ruleBodyRange.start : 0;
526
527    for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) {
528        const CSSPropertySourceData& propertyEntry = it->sourceData;
529        const String& name = propertyEntry.name;
530
531        // Visual Studio disagrees with other compilers as to whether 'class' is needed here.
532#if COMPILER(MSVC)
533        enum class Inspector::Protocol::CSS::CSSPropertyStatus status;
534#else
535        enum Inspector::Protocol::CSS::CSSPropertyStatus status;
536#endif
537        status = it->disabled ? Inspector::Protocol::CSS::CSSPropertyStatus::Disabled : Inspector::Protocol::CSS::CSSPropertyStatus::Active;
538
539        RefPtr<Inspector::Protocol::CSS::CSSProperty> property = Inspector::Protocol::CSS::CSSProperty::create()
540            .setName(name.lower())
541            .setValue(propertyEntry.value);
542
543        propertiesObject->addItem(property);
544
545        // Default "parsedOk" == true.
546        if (!propertyEntry.parsedOk)
547            property->setParsedOk(false);
548        if (it->hasRawText())
549            property->setText(it->rawText);
550
551        // Default "priority" == "".
552        if (propertyEntry.important)
553            property->setPriority("important");
554        if (!it->disabled) {
555            if (it->hasSource) {
556                ASSERT(sourceData);
557                property->setImplicit(false);
558                // The property range is relative to the style body start.
559                // Should be converted into an absolute range (relative to the stylesheet start)
560                // for the proper conversion into line:column.
561                SourceRange absolutePropertyRange = propertyEntry.range;
562                absolutePropertyRange.start += ruleBodyRangeStart;
563                absolutePropertyRange.end += ruleBodyRangeStart;
564                property->setRange(buildSourceRangeObject(absolutePropertyRange, lineEndings.get()));
565
566                // Parsed property overrides any property with the same name. Non-parsed property overrides
567                // previous non-parsed property with the same name (if any).
568                bool shouldInactivate = false;
569                CSSPropertyID propertyId = cssPropertyID(name);
570                // Canonicalize property names to treat non-prefixed and vendor-prefixed property names the same (opacity vs. -webkit-opacity).
571                String canonicalPropertyName = propertyId ? getPropertyNameString(propertyId) : name;
572                HashMap<String, RefPtr<Inspector::Protocol::CSS::CSSProperty>>::iterator activeIt = propertyNameToPreviousActiveProperty.find(canonicalPropertyName);
573                if (activeIt != propertyNameToPreviousActiveProperty.end()) {
574                    if (propertyEntry.parsedOk) {
575                        bool successPriority = activeIt->value->getString(Inspector::Protocol::CSS::CSSProperty::Priority, previousPriority);
576                        bool successStatus = activeIt->value->getString(Inspector::Protocol::CSS::CSSProperty::Status, previousStatus);
577                        if (successStatus && previousStatus != "inactive") {
578                            if (propertyEntry.important || !successPriority) // Priority not set == "not important".
579                                shouldInactivate = true;
580                            else if (status == Inspector::Protocol::CSS::CSSPropertyStatus::Active) {
581                                // Inactivate a non-important property following the same-named important property.
582                                status = Inspector::Protocol::CSS::CSSPropertyStatus::Inactive;
583                            }
584                        }
585                    } else {
586                        bool previousParsedOk;
587                        bool success = activeIt->value->getBoolean(Inspector::Protocol::CSS::CSSProperty::ParsedOk, previousParsedOk);
588                        if (success && !previousParsedOk)
589                            shouldInactivate = true;
590                    }
591                } else
592                    propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property);
593
594                if (shouldInactivate) {
595                    activeIt->value->setStatus(Inspector::Protocol::CSS::CSSPropertyStatus::Inactive);
596                    propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property);
597                }
598            } else {
599                bool implicit = m_style->isPropertyImplicit(name);
600                // Default "implicit" == false.
601                if (implicit)
602                    property->setImplicit(true);
603                status = Inspector::Protocol::CSS::CSSPropertyStatus::Style;
604
605                String shorthand = m_style->getPropertyShorthand(name);
606                if (!shorthand.isEmpty()) {
607                    if (!foundShorthands.contains(shorthand)) {
608                        foundShorthands.add(shorthand);
609                        RefPtr<Inspector::Protocol::CSS::ShorthandEntry> entry = Inspector::Protocol::CSS::ShorthandEntry::create()
610                            .setName(shorthand)
611                            .setValue(shorthandValue(shorthand));
612                        shorthandEntries->addItem(entry);
613                    }
614                }
615            }
616        }
617
618        // Default "status" == "style".
619        if (status != Inspector::Protocol::CSS::CSSPropertyStatus::Style)
620            property->setStatus(status);
621    }
622
623    RefPtr<Inspector::Protocol::CSS::CSSStyle> result = Inspector::Protocol::CSS::CSSStyle::create()
624        .setCssProperties(propertiesObject)
625        .setShorthandEntries(shorthandEntries);
626    return result.release();
627}
628
629PassRefPtr<CSSRuleSourceData> InspectorStyle::extractSourceData() const
630{
631    if (!m_parentStyleSheet || !m_parentStyleSheet->ensureParsedDataReady())
632        return nullptr;
633    return m_parentStyleSheet->ruleSourceDataFor(m_style.get());
634}
635
636bool InspectorStyle::setText(const String& text, ExceptionCode& ec)
637{
638    return m_parentStyleSheet->setStyleText(m_style.get(), text, ec);
639}
640
641String InspectorStyle::shorthandValue(const String& shorthandProperty) const
642{
643    String value = m_style->getPropertyValue(shorthandProperty);
644    if (!value.isEmpty())
645        return value;
646    StringBuilder builder;
647    for (unsigned i = 0; i < m_style->length(); ++i) {
648        String individualProperty = m_style->item(i);
649        if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
650            continue;
651        if (m_style->isPropertyImplicit(individualProperty))
652            continue;
653        String individualValue = m_style->getPropertyValue(individualProperty);
654        if (individualValue == "initial")
655            continue;
656        if (!builder.isEmpty())
657            builder.append(' ');
658        builder.append(individualValue);
659    }
660    return builder.toString();
661}
662
663String InspectorStyle::shorthandPriority(const String& shorthandProperty) const
664{
665    String priority = m_style->getPropertyPriority(shorthandProperty);
666    if (priority.isEmpty()) {
667        for (unsigned i = 0; i < m_style->length(); ++i) {
668            String individualProperty = m_style->item(i);
669            if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
670                continue;
671            priority = m_style->getPropertyPriority(individualProperty);
672            break;
673        }
674    }
675    return priority;
676}
677
678Vector<String> InspectorStyle::longhandProperties(const String& shorthandProperty) const
679{
680    Vector<String> properties;
681    HashSet<String> foundProperties;
682    for (unsigned i = 0; i < m_style->length(); ++i) {
683        String individualProperty = m_style->item(i);
684        if (foundProperties.contains(individualProperty) || m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
685            continue;
686
687        foundProperties.add(individualProperty);
688        properties.append(individualProperty);
689    }
690    return properties;
691}
692
693NewLineAndWhitespace& InspectorStyle::newLineAndWhitespaceDelimiters() const
694{
695    DEPRECATED_DEFINE_STATIC_LOCAL(String, defaultPrefix, (ASCIILiteral("    ")));
696
697    if (m_formatAcquired)
698        return m_format;
699
700    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
701    Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : nullptr;
702    int propertyCount;
703    if (!sourcePropertyData || !(propertyCount = sourcePropertyData->size())) {
704        m_format.first = "\n";
705        m_format.second = defaultPrefix;
706        return m_format; // Do not remember the default formatting and attempt to acquire it later.
707    }
708
709    String text;
710    bool success = styleText(&text);
711    ASSERT_UNUSED(success, success);
712
713    m_formatAcquired = true;
714
715    String candidatePrefix = defaultPrefix;
716    StringBuilder formatLineFeed;
717    StringBuilder prefix;
718    int scanStart = 0;
719    int propertyIndex = 0;
720    bool isFullPrefixScanned = false;
721    bool lineFeedTerminated = false;
722    while (propertyIndex < propertyCount) {
723        const WebCore::CSSPropertySourceData& currentProperty = sourcePropertyData->at(propertyIndex++);
724
725        bool processNextProperty = false;
726        int scanEnd = currentProperty.range.start;
727        for (int i = scanStart; i < scanEnd; ++i) {
728            UChar ch = text[i];
729            bool isLineFeed = isHTMLLineBreak(ch);
730            if (isLineFeed) {
731                if (!lineFeedTerminated)
732                    formatLineFeed.append(ch);
733                prefix.clear();
734            } else if (isHTMLSpace(ch))
735                prefix.append(ch);
736            else {
737                candidatePrefix = prefix.toString();
738                prefix.clear();
739                scanStart = currentProperty.range.end;
740                ++propertyIndex;
741                processNextProperty = true;
742                break;
743            }
744            if (!isLineFeed && formatLineFeed.length())
745                lineFeedTerminated = true;
746        }
747        if (!processNextProperty) {
748            isFullPrefixScanned = true;
749            break;
750        }
751    }
752
753    m_format.first = formatLineFeed.toString();
754    m_format.second = isFullPrefixScanned ? prefix.toString() : candidatePrefix;
755    return m_format;
756}
757
758PassRefPtr<InspectorStyleSheet> InspectorStyleSheet::create(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, Inspector::Protocol::CSS::StyleSheetOrigin origin, const String& documentURL, Listener* listener)
759{
760    return adoptRef(new InspectorStyleSheet(pageAgent, id, pageStyleSheet, origin, documentURL, listener));
761}
762
763// static
764String InspectorStyleSheet::styleSheetURL(CSSStyleSheet* pageStyleSheet)
765{
766    if (pageStyleSheet && !pageStyleSheet->contents().baseURL().isEmpty())
767        return pageStyleSheet->contents().baseURL().string();
768    return emptyString();
769}
770
771InspectorStyleSheet::InspectorStyleSheet(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, Inspector::Protocol::CSS::StyleSheetOrigin origin, const String& documentURL, Listener* listener)
772    : m_pageAgent(pageAgent)
773    , m_id(id)
774    , m_pageStyleSheet(pageStyleSheet)
775    , m_origin(origin)
776    , m_documentURL(documentURL)
777    , m_isRevalidating(false)
778    , m_listener(listener)
779{
780    m_parsedStyleSheet = new ParsedStyleSheet();
781}
782
783InspectorStyleSheet::~InspectorStyleSheet()
784{
785    delete m_parsedStyleSheet;
786}
787
788String InspectorStyleSheet::finalURL() const
789{
790    String url = styleSheetURL(m_pageStyleSheet.get());
791    return url.isEmpty() ? m_documentURL : url;
792}
793
794void InspectorStyleSheet::reparseStyleSheet(const String& text)
795{
796    {
797        // Have a separate scope for clearRules() (bug 95324).
798        CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get());
799        m_pageStyleSheet->contents().clearRules();
800    }
801    {
802        CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get());
803        m_pageStyleSheet->contents().parseString(text);
804        m_pageStyleSheet->clearChildRuleCSSOMWrappers();
805        m_inspectorStyles.clear();
806        fireStyleSheetChanged();
807    }
808}
809
810bool InspectorStyleSheet::setText(const String& text, ExceptionCode& ec)
811{
812    if (!checkPageStyleSheet(ec))
813        return false;
814    if (!m_parsedStyleSheet)
815        return false;
816
817    m_parsedStyleSheet->setText(text);
818    m_flatRules.clear();
819
820    return true;
821}
822
823String InspectorStyleSheet::ruleSelector(const InspectorCSSId& id, ExceptionCode& ec)
824{
825    CSSStyleRule* rule = ruleForId(id);
826    if (!rule) {
827        ec = NOT_FOUND_ERR;
828        return "";
829    }
830    return rule->selectorText();
831}
832
833bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String& selector, ExceptionCode& ec)
834{
835    if (!checkPageStyleSheet(ec))
836        return false;
837    CSSStyleRule* rule = ruleForId(id);
838    if (!rule) {
839        ec = NOT_FOUND_ERR;
840        return false;
841    }
842    CSSStyleSheet* styleSheet = rule->parentStyleSheet();
843    if (!styleSheet || !ensureParsedDataReady()) {
844        ec = NOT_FOUND_ERR;
845        return false;
846    }
847
848    rule->setSelectorText(selector);
849    RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(&rule->style());
850    if (!sourceData) {
851        ec = NOT_FOUND_ERR;
852        return false;
853    }
854
855    String sheetText = m_parsedStyleSheet->text();
856    sheetText.replace(sourceData->ruleHeaderRange.start, sourceData->ruleHeaderRange.length(), selector);
857    m_parsedStyleSheet->setText(sheetText);
858    fireStyleSheetChanged();
859    return true;
860}
861
862static bool checkStyleRuleSelector(Document* document, const String& selector)
863{
864    CSSSelectorList selectorList;
865    createCSSParser(document)->parseSelector(selector, selectorList);
866    return selectorList.isValid();
867}
868
869CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionCode& ec)
870{
871    if (!checkPageStyleSheet(ec))
872        return nullptr;
873    if (!checkStyleRuleSelector(m_pageStyleSheet->ownerDocument(), selector)) {
874        ec = SYNTAX_ERR;
875        return nullptr;
876    }
877
878    String text;
879    bool success = getText(&text);
880    if (!success) {
881        ec = NOT_FOUND_ERR;
882        return nullptr;
883    }
884    StringBuilder styleSheetText;
885    styleSheetText.append(text);
886
887    m_pageStyleSheet->addRule(selector, "", ec);
888    if (ec)
889        return nullptr;
890    ASSERT(m_pageStyleSheet->length());
891    unsigned lastRuleIndex = m_pageStyleSheet->length() - 1;
892    CSSRule* rule = m_pageStyleSheet->item(lastRuleIndex);
893    ASSERT(rule);
894
895    CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
896    if (!styleRule) {
897        // What we just added has to be a CSSStyleRule - we cannot handle other types of rules yet.
898        // If it is not a style rule, pretend we never touched the stylesheet.
899        m_pageStyleSheet->deleteRule(lastRuleIndex, ASSERT_NO_EXCEPTION);
900        ec = SYNTAX_ERR;
901        return nullptr;
902    }
903
904    if (!styleSheetText.isEmpty())
905        styleSheetText.append('\n');
906
907    styleSheetText.append(selector);
908    styleSheetText.appendLiteral(" {}");
909    // Using setText() as this operation changes the style sheet rule set.
910    setText(styleSheetText.toString(), ASSERT_NO_EXCEPTION);
911
912    fireStyleSheetChanged();
913
914    return styleRule;
915}
916
917bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, ExceptionCode& ec)
918{
919    if (!checkPageStyleSheet(ec))
920        return false;
921    RefPtr<CSSStyleRule> rule = ruleForId(id);
922    if (!rule) {
923        ec = NOT_FOUND_ERR;
924        return false;
925    }
926    CSSStyleSheet* styleSheet = rule->parentStyleSheet();
927    if (!styleSheet || !ensureParsedDataReady()) {
928        ec = NOT_FOUND_ERR;
929        return false;
930    }
931
932    RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(&rule->style());
933    if (!sourceData) {
934        ec = NOT_FOUND_ERR;
935        return false;
936    }
937
938    styleSheet->deleteRule(id.ordinal(), ec);
939    // |rule| MAY NOT be addressed after this line!
940
941    if (ec)
942        return false;
943
944    String sheetText = m_parsedStyleSheet->text();
945    sheetText.remove(sourceData->ruleHeaderRange.start, sourceData->ruleBodyRange.end - sourceData->ruleHeaderRange.start + 1);
946    setText(sheetText, ASSERT_NO_EXCEPTION);
947    fireStyleSheetChanged();
948    return true;
949}
950
951CSSStyleRule* InspectorStyleSheet::ruleForId(const InspectorCSSId& id) const
952{
953    if (!m_pageStyleSheet)
954        return nullptr;
955
956    ASSERT(!id.isEmpty());
957    ensureFlatRules();
958    return id.ordinal() >= m_flatRules.size() ? nullptr : m_flatRules.at(id.ordinal()).get();
959
960}
961
962PassRefPtr<Inspector::Protocol::CSS::CSSStyleSheetBody> InspectorStyleSheet::buildObjectForStyleSheet()
963{
964    CSSStyleSheet* styleSheet = pageStyleSheet();
965    if (!styleSheet)
966        return nullptr;
967
968    RefPtr<CSSRuleList> cssRuleList = asCSSRuleList(styleSheet);
969
970    RefPtr<Inspector::Protocol::CSS::CSSStyleSheetBody> result = Inspector::Protocol::CSS::CSSStyleSheetBody::create()
971        .setStyleSheetId(id())
972        .setRules(buildArrayForRuleList(cssRuleList.get()));
973
974    String styleSheetText;
975    bool success = getText(&styleSheetText);
976    if (success)
977        result->setText(styleSheetText);
978
979    return result.release();
980}
981
982PassRefPtr<Inspector::Protocol::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObjectForStyleSheetInfo()
983{
984    CSSStyleSheet* styleSheet = pageStyleSheet();
985    if (!styleSheet)
986        return nullptr;
987
988    Document* document = styleSheet->ownerDocument();
989    Frame* frame = document ? document->frame() : nullptr;
990    RefPtr<Inspector::Protocol::CSS::CSSStyleSheetHeader> result = Inspector::Protocol::CSS::CSSStyleSheetHeader::create()
991        .setStyleSheetId(id())
992        .setOrigin(m_origin)
993        .setDisabled(styleSheet->disabled())
994        .setSourceURL(finalURL())
995        .setTitle(styleSheet->title())
996        .setFrameId(m_pageAgent->frameId(frame));
997
998    return result.release();
999}
1000
1001static PassRefPtr<Inspector::Protocol::Array<String>> selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText)
1002{
1003    DEPRECATED_DEFINE_STATIC_LOCAL(JSC::Yarr::RegularExpression, comment, ("/\\*[^]*?\\*/", TextCaseSensitive, JSC::Yarr::MultilineEnabled));
1004    RefPtr<Inspector::Protocol::Array<String>> result = Inspector::Protocol::Array<String>::create();
1005    const SelectorRangeList& ranges = sourceData->selectorRanges;
1006    for (size_t i = 0, size = ranges.size(); i < size; ++i) {
1007        const SourceRange& range = ranges.at(i);
1008        String selector = sheetText.substring(range.start, range.length());
1009
1010        // We don't want to see any comments in the selector components, only the meaningful parts.
1011        replace(selector, comment, "");
1012        result->addItem(selector.stripWhiteSpace());
1013    }
1014    return result.release();
1015}
1016
1017PassRefPtr<Inspector::Protocol::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule)
1018{
1019    RefPtr<CSSRuleSourceData> sourceData;
1020    if (ensureParsedDataReady())
1021        sourceData = ruleSourceDataFor(&rule->style());
1022    RefPtr<Inspector::Protocol::Array<String>> selectors;
1023
1024    // This intentionally does not rely on the source data to avoid catching the trailing comments (before the declaration starting '{').
1025    String selectorText = rule->selectorText();
1026
1027    if (sourceData)
1028        selectors = selectorsFromSource(sourceData.get(), m_parsedStyleSheet->text());
1029    else {
1030        selectors = Inspector::Protocol::Array<String>::create();
1031        const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
1032        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
1033            selectors->addItem(selector->selectorText());
1034    }
1035    RefPtr<Inspector::Protocol::CSS::SelectorList> result = Inspector::Protocol::CSS::SelectorList::create()
1036        .setSelectors(selectors)
1037        .setText(selectorText)
1038        .release();
1039    if (sourceData)
1040        result->setRange(buildSourceRangeObject(sourceData->ruleHeaderRange, lineEndings().get()));
1041    return result.release();
1042}
1043
1044PassRefPtr<Inspector::Protocol::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule)
1045{
1046    CSSStyleSheet* styleSheet = pageStyleSheet();
1047    if (!styleSheet)
1048        return nullptr;
1049
1050    RefPtr<Inspector::Protocol::CSS::CSSRule> result = Inspector::Protocol::CSS::CSSRule::create()
1051        .setSelectorList(buildObjectForSelectorList(rule))
1052        .setSourceLine(rule->styleRule()->sourceLine())
1053        .setOrigin(m_origin)
1054        .setStyle(buildObjectForStyle(&rule->style()));
1055
1056    // "sourceURL" is present only for regular rules, otherwise "origin" should be used in the frontend.
1057    if (m_origin == Inspector::Protocol::CSS::StyleSheetOrigin::Regular)
1058        result->setSourceURL(finalURL());
1059
1060    if (canBind()) {
1061        InspectorCSSId id(ruleId(rule));
1062        if (!id.isEmpty())
1063            result->setRuleId(id.asProtocolValue<Inspector::Protocol::CSS::CSSRuleId>());
1064    }
1065
1066    RefPtr<Array<Inspector::Protocol::CSS::CSSMedia>> mediaArray = Array<Inspector::Protocol::CSS::CSSMedia>::create();
1067
1068    fillMediaListChain(rule, mediaArray.get());
1069    if (mediaArray->length())
1070        result->setMedia(mediaArray.release());
1071
1072    return result.release();
1073}
1074
1075PassRefPtr<Inspector::Protocol::CSS::CSSStyle> InspectorStyleSheet::buildObjectForStyle(CSSStyleDeclaration* style)
1076{
1077    RefPtr<CSSRuleSourceData> sourceData;
1078    if (ensureParsedDataReady())
1079        sourceData = ruleSourceDataFor(style);
1080
1081    InspectorCSSId id = ruleOrStyleId(style);
1082    if (id.isEmpty()) {
1083        RefPtr<Inspector::Protocol::CSS::CSSStyle> bogusStyle = Inspector::Protocol::CSS::CSSStyle::create()
1084            .setCssProperties(Array<Inspector::Protocol::CSS::CSSProperty>::create())
1085            .setShorthandEntries(Array<Inspector::Protocol::CSS::ShorthandEntry>::create());
1086        return bogusStyle.release();
1087    }
1088    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
1089    RefPtr<Inspector::Protocol::CSS::CSSStyle> result = inspectorStyle->buildObjectForStyle();
1090
1091    // Style text cannot be retrieved without stylesheet, so set cssText here.
1092    if (sourceData) {
1093        String sheetText;
1094        bool success = getText(&sheetText);
1095        if (success) {
1096            const SourceRange& bodyRange = sourceData->ruleBodyRange;
1097            result->setCssText(sheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start));
1098        }
1099    }
1100
1101    return result.release();
1102}
1103
1104bool InspectorStyleSheet::setStyleText(const InspectorCSSId& id, const String& text, String* oldText, ExceptionCode& ec)
1105{
1106    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
1107    if (!inspectorStyle) {
1108        ec = NOT_FOUND_ERR;
1109        return false;
1110    }
1111
1112    if (oldText && !inspectorStyle->getText(oldText))
1113        return false;
1114
1115    bool success = inspectorStyle->setText(text, ec);
1116    if (success)
1117        fireStyleSheetChanged();
1118    return success;
1119}
1120
1121bool InspectorStyleSheet::setPropertyText(const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite, String* oldText, ExceptionCode& ec)
1122{
1123    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
1124    if (!inspectorStyle) {
1125        ec = NOT_FOUND_ERR;
1126        return false;
1127    }
1128
1129    bool success = inspectorStyle->setPropertyText(propertyIndex, text, overwrite, oldText, ec);
1130    if (success)
1131        fireStyleSheetChanged();
1132    return success;
1133}
1134
1135bool InspectorStyleSheet::toggleProperty(const InspectorCSSId& id, unsigned propertyIndex, bool disable, ExceptionCode& ec)
1136{
1137    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
1138    if (!inspectorStyle) {
1139        ec = NOT_FOUND_ERR;
1140        return false;
1141    }
1142
1143    bool success = inspectorStyle->toggleProperty(propertyIndex, disable, ec);
1144    if (success) {
1145        if (disable)
1146            rememberInspectorStyle(inspectorStyle);
1147        else if (!inspectorStyle->hasDisabledProperties())
1148            forgetInspectorStyle(inspectorStyle->cssStyle());
1149        fireStyleSheetChanged();
1150    }
1151    return success;
1152}
1153
1154bool InspectorStyleSheet::getText(String* result) const
1155{
1156    if (!ensureText())
1157        return false;
1158    *result = m_parsedStyleSheet->text();
1159    return true;
1160}
1161
1162CSSStyleDeclaration* InspectorStyleSheet::styleForId(const InspectorCSSId& id) const
1163{
1164    CSSStyleRule* rule = ruleForId(id);
1165    if (!rule)
1166        return nullptr;
1167
1168    return &rule->style();
1169}
1170
1171void InspectorStyleSheet::fireStyleSheetChanged()
1172{
1173    if (m_listener)
1174        m_listener->styleSheetChanged(this);
1175}
1176
1177PassRefPtr<InspectorStyle> InspectorStyleSheet::inspectorStyleForId(const InspectorCSSId& id)
1178{
1179    CSSStyleDeclaration* style = styleForId(id);
1180    if (!style)
1181        return nullptr;
1182
1183    InspectorStyleMap::iterator it = m_inspectorStyles.find(style);
1184    if (it == m_inspectorStyles.end()) {
1185        RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(id, style, this);
1186        return inspectorStyle.release();
1187    }
1188    return it->value;
1189}
1190
1191void InspectorStyleSheet::rememberInspectorStyle(RefPtr<InspectorStyle> inspectorStyle)
1192{
1193    m_inspectorStyles.set(inspectorStyle->cssStyle(), inspectorStyle);
1194}
1195
1196void InspectorStyleSheet::forgetInspectorStyle(CSSStyleDeclaration* style)
1197{
1198    m_inspectorStyles.remove(style);
1199}
1200
1201InspectorCSSId InspectorStyleSheet::ruleOrStyleId(CSSStyleDeclaration* style) const
1202{
1203    unsigned index = ruleIndexByStyle(style);
1204    if (index != UINT_MAX)
1205        return InspectorCSSId(id(), index);
1206    return InspectorCSSId();
1207}
1208
1209Document* InspectorStyleSheet::ownerDocument() const
1210{
1211    return m_pageStyleSheet->ownerDocument();
1212}
1213
1214RefPtr<CSSRuleSourceData> InspectorStyleSheet::ruleSourceDataFor(CSSStyleDeclaration* style) const
1215{
1216    return m_parsedStyleSheet->ruleSourceDataAt(ruleIndexByStyle(style));
1217}
1218
1219std::unique_ptr<Vector<size_t>> InspectorStyleSheet::lineEndings() const
1220{
1221    if (!m_parsedStyleSheet->hasText())
1222        return nullptr;
1223    return ContentSearchUtilities::lineEndings(m_parsedStyleSheet->text());
1224}
1225
1226unsigned InspectorStyleSheet::ruleIndexByStyle(CSSStyleDeclaration* pageStyle) const
1227{
1228    ensureFlatRules();
1229    unsigned index = 0;
1230    for (unsigned i = 0, size = m_flatRules.size(); i < size; ++i) {
1231        if (&m_flatRules.at(i)->style() == pageStyle)
1232            return index;
1233
1234        ++index;
1235    }
1236    return UINT_MAX;
1237}
1238
1239bool InspectorStyleSheet::checkPageStyleSheet(ExceptionCode& ec) const
1240{
1241    if (!m_pageStyleSheet) {
1242        ec = NOT_SUPPORTED_ERR;
1243        return false;
1244    }
1245    return true;
1246}
1247
1248bool InspectorStyleSheet::ensureParsedDataReady()
1249{
1250    return ensureText() && ensureSourceData();
1251}
1252
1253bool InspectorStyleSheet::ensureText() const
1254{
1255    if (!m_parsedStyleSheet)
1256        return false;
1257    if (m_parsedStyleSheet->hasText())
1258        return true;
1259
1260    String text;
1261    bool success = originalStyleSheetText(&text);
1262    if (success)
1263        m_parsedStyleSheet->setText(text);
1264    // No need to clear m_flatRules here - it's empty.
1265
1266    return success;
1267}
1268
1269bool InspectorStyleSheet::ensureSourceData()
1270{
1271    if (m_parsedStyleSheet->hasSourceData())
1272        return true;
1273
1274    if (!m_parsedStyleSheet->hasText())
1275        return false;
1276
1277    RefPtr<StyleSheetContents> newStyleSheet = StyleSheetContents::create();
1278    auto ruleSourceDataResult = std::make_unique<RuleSourceDataList>();
1279    createCSSParser(m_pageStyleSheet->ownerDocument())->parseSheet(newStyleSheet.get(), m_parsedStyleSheet->text(), 0, ruleSourceDataResult.get());
1280    m_parsedStyleSheet->setSourceData(WTF::move(ruleSourceDataResult));
1281    return m_parsedStyleSheet->hasSourceData();
1282}
1283
1284void InspectorStyleSheet::ensureFlatRules() const
1285{
1286    // We are fine with redoing this for empty stylesheets as this will run fast.
1287    if (m_flatRules.isEmpty())
1288        collectFlatRules(asCSSRuleList(pageStyleSheet()), &m_flatRules);
1289}
1290
1291bool InspectorStyleSheet::setStyleText(CSSStyleDeclaration* style, const String& text, ExceptionCode& ec)
1292{
1293    if (!m_pageStyleSheet)
1294        return false;
1295    if (!ensureParsedDataReady())
1296        return false;
1297
1298    String patchedStyleSheetText;
1299    bool success = styleSheetTextWithChangedStyle(style, text, &patchedStyleSheetText);
1300    if (!success)
1301        return false;
1302
1303    InspectorCSSId id = ruleOrStyleId(style);
1304    if (id.isEmpty())
1305        return false;
1306
1307    style->setCssText(text, ec);
1308    if (!ec)
1309        m_parsedStyleSheet->setText(patchedStyleSheetText);
1310
1311    return !ec;
1312}
1313
1314bool InspectorStyleSheet::styleSheetTextWithChangedStyle(CSSStyleDeclaration* style, const String& newStyleText, String* result)
1315{
1316    if (!style)
1317        return false;
1318
1319    if (!ensureParsedDataReady())
1320        return false;
1321
1322    RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(style);
1323    unsigned bodyStart = sourceData->ruleBodyRange.start;
1324    unsigned bodyEnd = sourceData->ruleBodyRange.end;
1325    ASSERT(bodyStart <= bodyEnd);
1326
1327    String text = m_parsedStyleSheet->text();
1328    ASSERT_WITH_SECURITY_IMPLICATION(bodyEnd <= text.length()); // bodyEnd is exclusive
1329
1330    text.replace(bodyStart, bodyEnd - bodyStart, newStyleText);
1331    *result = text;
1332    return true;
1333}
1334
1335InspectorCSSId InspectorStyleSheet::ruleId(CSSStyleRule* rule) const
1336{
1337    return ruleOrStyleId(&rule->style());
1338}
1339
1340void InspectorStyleSheet::revalidateStyle(CSSStyleDeclaration* pageStyle)
1341{
1342    if (m_isRevalidating)
1343        return;
1344
1345    m_isRevalidating = true;
1346    ensureFlatRules();
1347    for (unsigned i = 0, size = m_flatRules.size(); i < size; ++i) {
1348        CSSStyleRule* parsedRule = m_flatRules.at(i).get();
1349        if (&parsedRule->style() == pageStyle) {
1350            if (parsedRule->styleRule()->properties().asText() != pageStyle->cssText()) {
1351                // Clear the disabled properties for the invalid style here.
1352                m_inspectorStyles.remove(pageStyle);
1353
1354                ExceptionCode ec = 0;
1355                setStyleText(pageStyle, pageStyle->cssText(), ec);
1356            }
1357            break;
1358        }
1359    }
1360    m_isRevalidating = false;
1361}
1362
1363bool InspectorStyleSheet::originalStyleSheetText(String* result) const
1364{
1365    bool success = inlineStyleSheetText(result);
1366    if (!success)
1367        success = resourceStyleSheetText(result);
1368    return success;
1369}
1370
1371bool InspectorStyleSheet::resourceStyleSheetText(String* result) const
1372{
1373    if (m_origin == Inspector::Protocol::CSS::StyleSheetOrigin::User || m_origin == Inspector::Protocol::CSS::StyleSheetOrigin::UserAgent)
1374        return false;
1375
1376    if (!m_pageStyleSheet || !ownerDocument() || !ownerDocument()->frame())
1377        return false;
1378
1379    String error;
1380    bool base64Encoded;
1381    InspectorPageAgent::resourceContent(error, ownerDocument()->frame(), URL(ParsedURLString, m_pageStyleSheet->href()), result, &base64Encoded);
1382    return error.isEmpty() && !base64Encoded;
1383}
1384
1385bool InspectorStyleSheet::inlineStyleSheetText(String* result) const
1386{
1387    if (!m_pageStyleSheet)
1388        return false;
1389
1390    Node* ownerNode = m_pageStyleSheet->ownerNode();
1391    if (!ownerNode || !is<Element>(ownerNode))
1392        return false;
1393    Element& ownerElement = downcast<Element>(*ownerNode);
1394
1395    if (!is<HTMLStyleElement>(ownerElement) && !is<SVGStyleElement>(ownerElement))
1396        return false;
1397    *result = ownerElement.textContent();
1398    return true;
1399}
1400
1401PassRefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSRule>> InspectorStyleSheet::buildArrayForRuleList(CSSRuleList* ruleList)
1402{
1403    RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSRule>> result = Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSRule>::create();
1404    if (!ruleList)
1405        return result.release();
1406
1407    RefPtr<CSSRuleList> refRuleList = ruleList;
1408    CSSStyleRuleVector rules;
1409    collectFlatRules(refRuleList, &rules);
1410
1411    for (unsigned i = 0, size = rules.size(); i < size; ++i)
1412        result->addItem(buildObjectForRule(rules.at(i).get()));
1413
1414    return result.release();
1415}
1416
1417void InspectorStyleSheet::collectFlatRules(PassRefPtr<CSSRuleList> ruleList, CSSStyleRuleVector* result)
1418{
1419    if (!ruleList)
1420        return;
1421
1422    for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
1423        CSSRule* rule = ruleList->item(i);
1424        CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
1425        if (styleRule)
1426            result->append(styleRule);
1427        else {
1428            RefPtr<CSSRuleList> childRuleList = asCSSRuleList(rule);
1429            if (childRuleList)
1430                collectFlatRules(childRuleList, result);
1431        }
1432    }
1433}
1434
1435PassRefPtr<InspectorStyleSheetForInlineStyle> InspectorStyleSheetForInlineStyle::create(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<Element> element, Inspector::Protocol::CSS::StyleSheetOrigin origin, Listener* listener)
1436{
1437    return adoptRef(new InspectorStyleSheetForInlineStyle(pageAgent, id, element, origin, listener));
1438}
1439
1440InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<Element> element, Inspector::Protocol::CSS::StyleSheetOrigin origin, Listener* listener)
1441    : InspectorStyleSheet(pageAgent, id, nullptr, origin, "", listener)
1442    , m_element(element)
1443    , m_ruleSourceData(nullptr)
1444    , m_isStyleTextValid(false)
1445{
1446    ASSERT(m_element);
1447    m_inspectorStyle = InspectorStyle::create(InspectorCSSId(id, 0), inlineStyle(), this);
1448    m_styleText = m_element->isStyledElement() ? m_element->getAttribute("style").string() : String();
1449}
1450
1451void InspectorStyleSheetForInlineStyle::didModifyElementAttribute()
1452{
1453    m_isStyleTextValid = false;
1454    if (m_element->isStyledElement() && m_element->style() != m_inspectorStyle->cssStyle())
1455        m_inspectorStyle = InspectorStyle::create(InspectorCSSId(id(), 0), inlineStyle(), this);
1456    m_ruleSourceData.clear();
1457}
1458
1459bool InspectorStyleSheetForInlineStyle::getText(String* result) const
1460{
1461    if (!m_isStyleTextValid) {
1462        m_styleText = elementStyleText();
1463        m_isStyleTextValid = true;
1464    }
1465    *result = m_styleText;
1466    return true;
1467}
1468
1469bool InspectorStyleSheetForInlineStyle::setStyleText(CSSStyleDeclaration* style, const String& text, ExceptionCode& ec)
1470{
1471    ASSERT_UNUSED(style, style == inlineStyle());
1472
1473    {
1474        InspectorCSSAgent::InlineStyleOverrideScope overrideScope(&m_element->document());
1475        m_element->setAttribute("style", text, ec);
1476    }
1477
1478    m_styleText = text;
1479    m_isStyleTextValid = true;
1480    m_ruleSourceData.clear();
1481    return !ec;
1482}
1483
1484std::unique_ptr<Vector<size_t>> InspectorStyleSheetForInlineStyle::lineEndings() const
1485{
1486    return ContentSearchUtilities::lineEndings(elementStyleText());
1487}
1488
1489Document* InspectorStyleSheetForInlineStyle::ownerDocument() const
1490{
1491    return &m_element->document();
1492}
1493
1494bool InspectorStyleSheetForInlineStyle::ensureParsedDataReady()
1495{
1496    // The "style" property value can get changed indirectly, e.g. via element.style.borderWidth = "2px".
1497    const String& currentStyleText = elementStyleText();
1498    if (m_styleText != currentStyleText) {
1499        m_ruleSourceData.clear();
1500        m_styleText = currentStyleText;
1501        m_isStyleTextValid = true;
1502    }
1503
1504    if (m_ruleSourceData)
1505        return true;
1506
1507    m_ruleSourceData = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE);
1508    bool success = getStyleAttributeRanges(m_ruleSourceData.get());
1509    if (!success)
1510        return false;
1511
1512    return true;
1513}
1514
1515PassRefPtr<InspectorStyle> InspectorStyleSheetForInlineStyle::inspectorStyleForId(const InspectorCSSId& id)
1516{
1517    ASSERT_UNUSED(id, !id.ordinal());
1518    return m_inspectorStyle;
1519}
1520
1521CSSStyleDeclaration* InspectorStyleSheetForInlineStyle::inlineStyle() const
1522{
1523    return m_element->style();
1524}
1525
1526const String& InspectorStyleSheetForInlineStyle::elementStyleText() const
1527{
1528    return m_element->getAttribute("style").string();
1529}
1530
1531bool InspectorStyleSheetForInlineStyle::getStyleAttributeRanges(CSSRuleSourceData* result) const
1532{
1533    if (!m_element->isStyledElement())
1534        return false;
1535
1536    if (m_styleText.isEmpty()) {
1537        result->ruleBodyRange.start = 0;
1538        result->ruleBodyRange.end = 0;
1539        return true;
1540    }
1541
1542    RefPtr<MutableStyleProperties> tempDeclaration = MutableStyleProperties::create();
1543    createCSSParser(&m_element->document())->parseDeclaration(tempDeclaration.get(), m_styleText, result, &m_element->document().elementSheet().contents());
1544    return true;
1545}
1546
1547} // namespace WebCore
1548
1549#endif // ENABLE(INSPECTOR)
Note: See TracBrowser for help on using the repository browser.