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#include "InspectorCSSAgent.h" 27 28#if ENABLE(INSPECTOR) 29 30#include "CSSComputedStyleDeclaration.h" 31#include "CSSMutableStyleDeclaration.h" 32#include "CSSPropertyNames.h" 33#include "CSSPropertySourceData.h" 34#include "CSSRule.h" 35#include "CSSRuleList.h" 36#include "CSSStyleRule.h" 37#include "CSSStyleSelector.h" 38#include "CSSStyleSheet.h" 39#include "DOMWindow.h" 40#include "HTMLHeadElement.h" 41#include "InspectorDOMAgent.h" 42#include "InspectorValues.h" 43#include "InstrumentingAgents.h" 44#include "Node.h" 45#include "NodeList.h" 46#include "StyleSheetList.h" 47 48#include <wtf/HashSet.h> 49#include <wtf/Vector.h> 50#include <wtf/text/CString.h> 51 52// Currently implemented model: 53// 54// cssProperty = { 55// name : <string>, 56// value : <string>, 57// priority : <string>, // "" for non-parsedOk properties 58// implicit : <boolean>, 59// parsedOk : <boolean>, // whether property is understood by WebCore 60// status : <string>, // "disabled" | "active" | "inactive" | "style" 61// shorthandName : <string>, 62// startOffset : <number>, // Optional - property text start offset in enclosing style declaration. Absent for computed styles and such. 63// endOffset : <number>, // Optional - property text end offset in enclosing style declaration. Absent for computed styles and such. 64// } 65// 66// name + value + priority : present when the property is enabled 67// text : present when the property is disabled 68// 69// For disabled properties, startOffset === endOffset === insertion point for the property. 70// 71// status: 72// "disabled" == property disabled by user 73// "active" == property participates in the computed style calculation 74// "inactive" == property does no participate in the computed style calculation (i.e. overridden by a subsequent property with the same name) 75// "style" == property is active and originates from the WebCore CSSStyleDeclaration rather than CSS source code (e.g. implicit longhand properties) 76// 77// cssStyle = { 78// styleId : <string>, // Optional 79// cssProperties : [ 80// #cssProperty, 81// ... 82// #cssProperty 83// ], 84// shorthandEntries : [ 85// #shorthandEntry, 86// ... 87// #shorthandEntry 88// ], 89// cssText : <string>, // Optional - declaration text 90// properties : { 91// width, 92// height, 93// startOffset, // Optional - for source-based styles only 94// endOffset, // Optional - for source-based styles only 95// } 96// } 97// 98// shorthandEntry = { 99// name: <string>, 100// value: <string> 101// } 102// 103// cssRule = { 104// ruleId : <string>, // Optional 105// selectorText : <string>, 106// sourceURL : <string>, 107// sourceLine : <string>, 108// origin : <string>, // "" || "user-agent" || "user" || "inspector" 109// style : #cssStyle, 110// selectorRange: { start: <number>, end: <number> } // Optional - for source-based rules only 111// } 112// 113// cssStyleSheetInfo = { 114// styleSheetId : <number> 115// sourceURL : <string> 116// title : <string> 117// disabled : <boolean> 118// } 119// 120// cssStyleSheet = { 121// styleSheetId : <number> 122// rules : [ 123// #cssRule, 124// ... 125// #cssRule 126// ] 127// text : <string> // Optional - whenever the text is available for a text-based stylesheet 128// } 129 130namespace WebCore { 131 132// static 133CSSStyleSheet* InspectorCSSAgent::parentStyleSheet(StyleBase* styleBase) 134{ 135 if (!styleBase) 136 return 0; 137 138 StyleSheet* styleSheet = styleBase->stylesheet(); 139 if (styleSheet && styleSheet->isCSSStyleSheet()) 140 return static_cast<CSSStyleSheet*>(styleSheet); 141 142 return 0; 143} 144 145// static 146CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(StyleBase* styleBase) 147{ 148 if (!styleBase->isStyleRule()) 149 return 0; 150 CSSRule* rule = static_cast<CSSRule*>(styleBase); 151 if (rule->type() != CSSRule::STYLE_RULE) 152 return 0; 153 return static_cast<CSSStyleRule*>(rule); 154} 155 156InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorDOMAgent* domAgent) 157 : m_instrumentingAgents(instrumentingAgents) 158 , m_domAgent(domAgent) 159 , m_lastStyleSheetId(1) 160 , m_lastRuleId(1) 161 , m_lastStyleId(1) 162{ 163 m_domAgent->setDOMListener(this); 164 m_instrumentingAgents->setInspectorCSSAgent(this); 165} 166 167InspectorCSSAgent::~InspectorCSSAgent() 168{ 169 m_instrumentingAgents->setInspectorCSSAgent(0); 170 // DOM agent should be destroyed after CSS agent. 171 m_domAgent->setDOMListener(0); 172 m_domAgent = 0; 173 reset(); 174} 175 176void InspectorCSSAgent::reset() 177{ 178 m_idToInspectorStyleSheet.clear(); 179 m_cssStyleSheetToInspectorStyleSheet.clear(); 180 m_nodeToInspectorStyleSheet.clear(); 181 m_documentToInspectorStyleSheet.clear(); 182} 183 184void InspectorCSSAgent::getStylesForNode(ErrorString* errorString, int nodeId, RefPtr<InspectorObject>* result) 185{ 186 Element* element = elementForId(errorString, nodeId); 187 if (!element) 188 return; 189 190 RefPtr<InspectorObject> resultObject = InspectorObject::create(); 191 192 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element); 193 if (styleSheet) 194 resultObject->setObject("inlineStyle", styleSheet->buildObjectForStyle(element->style())); 195 196 RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = computedStyle(element, true); // Support the viewing of :visited information in computed style. 197 RefPtr<InspectorStyle> computedInspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0); 198 resultObject->setObject("computedStyle", computedInspectorStyle->buildObjectForStyle()); 199 200 CSSStyleSelector* selector = element->ownerDocument()->styleSelector(); 201 RefPtr<CSSRuleList> matchedRules = selector->styleRulesForElement(element, false, true); 202 resultObject->setArray("matchedCSSRules", buildArrayForRuleList(matchedRules.get())); 203 204 resultObject->setArray("styleAttributes", buildArrayForAttributeStyles(element)); 205 206 RefPtr<InspectorArray> pseudoElements = InspectorArray::create(); 207 for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) { 208 RefPtr<CSSRuleList> matchedRules = selector->pseudoStyleRulesForElement(element, pseudoId, false, true); 209 if (matchedRules && matchedRules->length()) { 210 RefPtr<InspectorObject> pseudoStyles = InspectorObject::create(); 211 pseudoStyles->setNumber("pseudoId", static_cast<int>(pseudoId)); 212 pseudoStyles->setArray("rules", buildArrayForRuleList(matchedRules.get())); 213 pseudoElements->pushObject(pseudoStyles.release()); 214 } 215 } 216 resultObject->setArray("pseudoElements", pseudoElements.release()); 217 218 RefPtr<InspectorArray> inheritedStyles = InspectorArray::create(); 219 Element* parentElement = element->parentElement(); 220 while (parentElement) { 221 RefPtr<InspectorObject> parentStyle = InspectorObject::create(); 222 if (parentElement->style() && parentElement->style()->length()) { 223 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement); 224 if (styleSheet) 225 parentStyle->setObject("inlineStyle", styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0)))); 226 } 227 228 CSSStyleSelector* parentSelector = parentElement->ownerDocument()->styleSelector(); 229 RefPtr<CSSRuleList> parentMatchedRules = parentSelector->styleRulesForElement(parentElement, false, true); 230 parentStyle->setArray("matchedCSSRules", buildArrayForRuleList(parentMatchedRules.get())); 231 inheritedStyles->pushObject(parentStyle.release()); 232 parentElement = parentElement->parentElement(); 233 } 234 resultObject->setArray("inherited", inheritedStyles.release()); 235 236 *result = resultObject.release(); 237} 238 239void InspectorCSSAgent::getInlineStyleForNode(ErrorString* errorString, int nodeId, RefPtr<InspectorObject>* style) 240{ 241 Element* element = elementForId(errorString, nodeId); 242 if (!element) 243 return; 244 245 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element); 246 if (!styleSheet) 247 return; 248 249 *style = styleSheet->buildObjectForStyle(element->style()); 250} 251 252void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, RefPtr<InspectorObject>* style) 253{ 254 Element* element = elementForId(errorString, nodeId); 255 if (!element) 256 return; 257 258 RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = computedStyle(element, true); 259 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0); 260 *style = inspectorStyle->buildObjectForStyle(); 261} 262 263void InspectorCSSAgent::getAllStyleSheets(ErrorString*, RefPtr<InspectorArray>* styleInfos) 264{ 265 Vector<Document*> documents = m_domAgent->documents(); 266 for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) { 267 StyleSheetList* list = (*it)->styleSheets(); 268 for (unsigned i = 0; i < list->length(); ++i) { 269 StyleSheet* styleSheet = list->item(i); 270 if (styleSheet->isCSSStyleSheet()) { 271 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet)); 272 (*styleInfos)->pushObject(inspectorStyleSheet->buildObjectForStyleSheetInfo()); 273 } 274 } 275 } 276} 277 278void InspectorCSSAgent::getStyleSheet(ErrorString* errorString, const String& styleSheetId, RefPtr<InspectorObject>* styleSheetObject) 279{ 280 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); 281 if (!inspectorStyleSheet) 282 return; 283 284 *styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet(); 285} 286 287void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result) 288{ 289 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); 290 if (!inspectorStyleSheet) 291 return; 292 293 inspectorStyleSheet->text(result); 294} 295 296void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text) 297{ 298 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); 299 if (!inspectorStyleSheet) 300 return; 301 302 if (inspectorStyleSheet->setText(text)) 303 inspectorStyleSheet->reparseStyleSheet(text); 304 else 305 *errorString = "Internal error setting style sheet text"; 306} 307 308void InspectorCSSAgent::setPropertyText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, const String& text, bool overwrite, RefPtr<InspectorObject>* result) 309{ 310 InspectorCSSId compoundId(fullStyleId); 311 ASSERT(!compoundId.isEmpty()); 312 313 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId()); 314 if (!inspectorStyleSheet) 315 return; 316 317 bool success = inspectorStyleSheet->setPropertyText(errorString, compoundId, propertyIndex, text, overwrite); 318 if (success) 319 *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId)); 320} 321 322void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, bool disable, RefPtr<InspectorObject>* result) 323{ 324 InspectorCSSId compoundId(fullStyleId); 325 ASSERT(!compoundId.isEmpty()); 326 327 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId()); 328 if (!inspectorStyleSheet) 329 return; 330 331 bool success = inspectorStyleSheet->toggleProperty(errorString, compoundId, propertyIndex, disable); 332 if (success) 333 *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId)); 334} 335 336void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<InspectorObject>* result) 337{ 338 InspectorCSSId compoundId(fullRuleId); 339 ASSERT(!compoundId.isEmpty()); 340 341 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId()); 342 if (!inspectorStyleSheet) 343 return; 344 345 bool success = inspectorStyleSheet->setRuleSelector(compoundId, selector); 346 if (!success) 347 return; 348 349 *result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId)); 350} 351 352void InspectorCSSAgent::addRule(ErrorString*, const int contextNodeId, const String& selector, RefPtr<InspectorObject>* result) 353{ 354 Node* node = m_domAgent->nodeForId(contextNodeId); 355 if (!node) 356 return; 357 358 InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(node->document(), true); 359 if (!inspectorStyleSheet) 360 return; 361 CSSStyleRule* newRule = inspectorStyleSheet->addRule(selector); 362 if (!newRule) 363 return; 364 365 *result = inspectorStyleSheet->buildObjectForRule(newRule); 366} 367 368void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<InspectorArray>* cssProperties) 369{ 370 RefPtr<InspectorArray> properties = InspectorArray::create(); 371 for (int i = 0; i < numCSSProperties; ++i) 372 properties->pushString(propertyNameStrings[i]); 373 374 *cssProperties = properties.release(); 375} 376 377// static 378Element* InspectorCSSAgent::inlineStyleElement(CSSStyleDeclaration* style) 379{ 380 if (!style || !style->isMutableStyleDeclaration()) 381 return 0; 382 Node* node = static_cast<CSSMutableStyleDeclaration*>(style)->node(); 383 if (!node || !node->isStyledElement() || static_cast<StyledElement*>(node)->getInlineStyleDecl() != style) 384 return 0; 385 return static_cast<Element*>(node); 386} 387 388InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element) 389{ 390 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element); 391 if (it == m_nodeToInspectorStyleSheet.end()) { 392 CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : 0; 393 if (!style) 394 return 0; 395 396 String newStyleSheetId = String::number(m_lastStyleSheetId++); 397 RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(newStyleSheetId, element, ""); 398 m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet); 399 m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet); 400 return inspectorStyleSheet.get(); 401 } 402 403 return it->second.get(); 404} 405 406Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId) 407{ 408 Node* node = m_domAgent->nodeForId(nodeId); 409 if (!node) { 410 *errorString = "No node with given id found"; 411 return 0; 412 } 413 if (node->nodeType() != Node::ELEMENT_NODE) { 414 *errorString = "Not an element node"; 415 return 0; 416 } 417 return static_cast<Element*>(node); 418} 419 420InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet) 421{ 422 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet); 423 if (!inspectorStyleSheet) { 424 String id = String::number(m_lastStyleSheetId++); 425 inspectorStyleSheet = InspectorStyleSheet::create(id, styleSheet, detectOrigin(styleSheet, styleSheet->document()), m_domAgent->documentURLString(styleSheet->document())); 426 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet); 427 m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet); 428 } 429 return inspectorStyleSheet.get(); 430} 431 432InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent) 433{ 434 if (!document) { 435 ASSERT(!createIfAbsent); 436 return 0; 437 } 438 439 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document); 440 if (inspectorStyleSheet || !createIfAbsent) 441 return inspectorStyleSheet.get(); 442 443 ExceptionCode ec = 0; 444 RefPtr<Element> styleElement = document->createElement("style", ec); 445 if (!ec) 446 styleElement->setAttribute("type", "text/css", ec); 447 if (!ec) { 448 ContainerNode* targetNode; 449 // HEAD is absent in ImageDocuments, for example. 450 if (document->head()) 451 targetNode = document->head(); 452 else if (document->body()) 453 targetNode = document->body(); 454 else 455 return 0; 456 targetNode->appendChild(styleElement, ec); 457 } 458 if (ec) 459 return 0; 460 StyleSheetList* styleSheets = document->styleSheets(); 461 StyleSheet* styleSheet = styleSheets->item(styleSheets->length() - 1); 462 if (!styleSheet->isCSSStyleSheet()) 463 return 0; 464 CSSStyleSheet* cssStyleSheet = static_cast<CSSStyleSheet*>(styleSheet); 465 String id = String::number(m_lastStyleSheetId++); 466 inspectorStyleSheet = InspectorStyleSheet::create(id, cssStyleSheet, "inspector", m_domAgent->documentURLString(document)); 467 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet); 468 m_cssStyleSheetToInspectorStyleSheet.set(cssStyleSheet, inspectorStyleSheet); 469 m_documentToInspectorStyleSheet.set(document, inspectorStyleSheet); 470 return inspectorStyleSheet.get(); 471} 472 473InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId) 474{ 475 IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId); 476 if (it == m_idToInspectorStyleSheet.end()) { 477 *errorString = "No style sheet with given id found"; 478 return 0; 479 } 480 return it->second.get(); 481} 482 483String InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument) 484{ 485 DEFINE_STATIC_LOCAL(String, userAgent, ("user-agent")); 486 DEFINE_STATIC_LOCAL(String, user, ("user")); 487 DEFINE_STATIC_LOCAL(String, inspector, ("inspector")); 488 489 String origin(""); 490 if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty()) 491 origin = userAgent; 492 else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document") 493 origin = user; 494 else { 495 InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false); 496 if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet()) 497 origin = inspector; 498 } 499 return origin; 500} 501 502PassRefPtr<InspectorArray> InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList) 503{ 504 RefPtr<InspectorArray> result = InspectorArray::create(); 505 if (!ruleList) 506 return result.release(); 507 508 for (unsigned i = 0, size = ruleList->length(); i < size; ++i) { 509 CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i)); 510 if (!rule) 511 continue; 512 513 InspectorStyleSheet* styleSheet = bindStyleSheet(parentStyleSheet(rule)); 514 if (styleSheet) 515 result->pushObject(styleSheet->buildObjectForRule(rule)); 516 } 517 return result.release(); 518} 519 520PassRefPtr<InspectorArray> InspectorCSSAgent::buildArrayForAttributeStyles(Element* element) 521{ 522 RefPtr<InspectorArray> attrStyles = InspectorArray::create(); 523 NamedNodeMap* attributes = element->attributes(); 524 for (unsigned i = 0; attributes && i < attributes->length(); ++i) { 525 Attribute* attribute = attributes->attributeItem(i); 526 if (attribute->style()) { 527 RefPtr<InspectorObject> attrStyleObject = InspectorObject::create(); 528 String attributeName = attribute->localName(); 529 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), attribute->style(), 0); 530 attrStyleObject->setString("name", attributeName.utf8().data()); 531 attrStyleObject->setObject("style", inspectorStyle->buildObjectForStyle()); 532 attrStyles->pushObject(attrStyleObject.release()); 533 } 534 } 535 536 return attrStyles.release(); 537} 538 539void InspectorCSSAgent::didRemoveDocument(Document* document) 540{ 541 if (document) 542 m_documentToInspectorStyleSheet.remove(document); 543} 544 545void InspectorCSSAgent::didRemoveDOMNode(Node* node) 546{ 547 if (!node) 548 return; 549 550 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node); 551 if (it == m_nodeToInspectorStyleSheet.end()) 552 return; 553 554 m_idToInspectorStyleSheet.remove(it->second->id()); 555 m_nodeToInspectorStyleSheet.remove(node); 556} 557 558void InspectorCSSAgent::didModifyDOMAttr(Element* element) 559{ 560 if (!element) 561 return; 562 563 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element); 564 if (it == m_nodeToInspectorStyleSheet.end()) 565 return; 566 567 it->second->didModifyElementAttribute(); 568} 569 570} // namespace WebCore 571 572#endif // ENABLE(INSPECTOR) 573