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 130 namespace WebCore { 131 132 // static 133 CSSStyleSheet* 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 146 CSSStyleRule* 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 156 InspectorCSSAgent::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 167 InspectorCSSAgent::~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 176 void InspectorCSSAgent::reset() 177 { 178 m_idToInspectorStyleSheet.clear(); 179 m_cssStyleSheetToInspectorStyleSheet.clear(); 180 m_nodeToInspectorStyleSheet.clear(); 181 m_documentToInspectorStyleSheet.clear(); 182 } 183 184 void 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 239 void 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 252 void 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 263 void 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 278 void 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 287 void 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 296 void 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 308 void 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 322 void 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 336 void 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 352 void 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 368 void 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 378 Element* 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 388 InspectorStyleSheetForInlineStyle* 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 406 Element* 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 420 InspectorStyleSheet* 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 432 InspectorStyleSheet* 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 473 InspectorStyleSheet* 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 483 String 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 502 PassRefPtr<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 520 PassRefPtr<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 539 void InspectorCSSAgent::didRemoveDocument(Document* document) 540 { 541 if (document) 542 m_documentToInspectorStyleSheet.remove(document); 543 } 544 545 void 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 558 void 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