| OLD | NEW |
| 1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 * | 4 * |
| 5 * Helper javascript injected whenever a DomMutationEventObserver is created. | 5 * Helper javascript injected whenever a DomMutationEventObserver is created. |
| 6 * | 6 * |
| 7 * This script uses MutationObservers to watch for changes to the DOM, then | 7 * This script uses MutationObservers to watch for changes to the DOM, then |
| 8 * reports the event to the observer using the DomAutomationController. An | 8 * reports the event to the observer using the DomAutomationController. An |
| 9 * anonymous namespace is used to prevent conflict with other Javascript. | 9 * anonymous namespace is used to prevent conflict with other Javascript. |
| 10 * | 10 * |
| 11 * Args: | 11 * Args: |
| 12 * automation_id: Automation id used to route DomAutomationController messages. | 12 * automation_id: Automation id used to route DomAutomationController messages. |
| 13 * observer_id: Id of the observer who will be receiving the messages. | 13 * observer_id: Id of the observer who will be receiving the messages. |
| 14 * observer_type: One of 'add', 'remove', or 'change'. | 14 * observer_type: One of 'add', 'remove', 'change', or 'exists'. |
| 15 * pattern: Pattern used to select the DOM node of interest. | 15 * pattern: Pattern used to select the DOM node of interest. |
| 16 * ptype: Type of |pattern|, either 'xpath' or 'css'. | 16 * ptype: Type of |pattern|, either 'xpath' or 'css'. |
| 17 * expected_value: If not null, regular expression matching text contents | 17 * expected_value: If not null, regular expression matching text contents |
| 18 * expected after the mutation. | 18 * expected after the mutation. |
| 19 */ | 19 */ |
| 20 | 20 |
| 21 function(automation_id, observer_id, observer_type, pattern, ptype, | 21 function(automation_id, observer_id, observer_type, pattern, ptype, |
| 22 expected_value) { | 22 expected_value) { |
| 23 | 23 |
| 24 /* Raise an event for the DomMutationEventObserver. | 24 /* Raise an event for the DomMutationEventObserver. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 for (var j=0; j<mutations.length; j++) { | 95 for (var j=0; j<mutations.length; j++) { |
| 96 if (nodeValueTextEquals(mutations[j].target, expected_value)) { | 96 if (nodeValueTextEquals(mutations[j].target, expected_value)) { |
| 97 raiseEvent(); | 97 raiseEvent(); |
| 98 observer.disconnect(); | 98 observer.disconnect(); |
| 99 delete observer; | 99 delete observer; |
| 100 return; | 100 return; |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 | 104 |
| 105 /* Calls raiseEvent if the expected node exists in the DOM. |
| 106 * |
| 107 * Args: |
| 108 * mutations: A list of mutation objects. |
| 109 * observer: The mutation observer object associated with this callback. |
| 110 */ |
| 111 function existsNodeCallback(mutations, observer) { |
| 112 var node = firstMatchingNode(pattern, ptype); |
| 113 if (node && nodeValueTextEquals(node, expected_value)) { |
| 114 raiseEvent(); |
| 115 observer.disconnect(); |
| 116 delete observer; |
| 117 return; |
| 118 } |
| 119 } |
| 120 |
| 105 /* Return true if the xpath matches the given node. | 121 /* Return true if the xpath matches the given node. |
| 106 * | 122 * |
| 107 * Args: | 123 * Args: |
| 108 * node: A node object from the DOM. | 124 * node: A node object from the DOM. |
| 109 * xpath: A string in the format of an xpath. | 125 * xpath: A string in the format of an xpath. |
| 110 */ | 126 */ |
| 111 function XPathMatchesNode(node, xpath) { | 127 function XPathMatchesNode(node, xpath) { |
| 112 var con = document.evaluate(xpath, document, null, | 128 var con = document.evaluate(xpath, document, null, |
| 113 XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); | 129 XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); |
| 114 var thisNode = con.iterateNext(); | 130 var thisNode = con.iterateNext(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 } | 193 } |
| 178 | 194 |
| 179 /* Watch for a node matching pattern to be added to the DOM. | 195 /* Watch for a node matching pattern to be added to the DOM. |
| 180 * | 196 * |
| 181 * Args: | 197 * Args: |
| 182 * pattern: A string in the format of either an XPath or CSS Selector. | 198 * pattern: A string in the format of either an XPath or CSS Selector. |
| 183 * ptype: Either 'xpath' or 'css'. | 199 * ptype: Either 'xpath' or 'css'. |
| 184 */ | 200 */ |
| 185 function observeAdd(pattern, ptype) { | 201 function observeAdd(pattern, ptype) { |
| 186 window.domAutomationController.send("success"); | 202 window.domAutomationController.send("success"); |
| 187 if (firstMatchingNode(pattern, ptype)) { | 203 var node = firstMatchingNode(pattern, ptype); |
| 204 if (node && nodeValueTextEquals(node, expected_value)) { |
| 188 raiseEvent(); | 205 raiseEvent(); |
| 189 console.log("Matching node in DOM, assuming it was previously added."); | 206 console.log("Matching node in DOM, assuming it was previously added."); |
| 190 return; | 207 return; |
| 191 } | 208 } |
| 192 | 209 |
| 193 var obs = new WebKitMutationObserver(addNodeCallback); | 210 var obs = new WebKitMutationObserver(addNodeCallback); |
| 194 obs.observe(document, | 211 obs.observe(document, |
| 195 { childList: true, | 212 { childList: true, |
| 196 attributes: true, | 213 attributes: true, |
| 197 subtree: true}); | 214 subtree: true}); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 window.domAutomationController.send("success"); | 253 window.domAutomationController.send("success"); |
| 237 | 254 |
| 238 var obs = new WebKitMutationObserver(changeNodeCallback); | 255 var obs = new WebKitMutationObserver(changeNodeCallback); |
| 239 obs.observe(node, | 256 obs.observe(node, |
| 240 { childList: true, | 257 { childList: true, |
| 241 attributes: true, | 258 attributes: true, |
| 242 characterData: true, | 259 characterData: true, |
| 243 subtree: true}); | 260 subtree: true}); |
| 244 } | 261 } |
| 245 | 262 |
| 263 /* Watch for a node matching pattern to exist in the DOM. |
| 264 * |
| 265 * Args: |
| 266 * pattern: A string in the format of either an XPath or CSS Selector. |
| 267 * ptype: Either 'xpath' or 'css'. |
| 268 */ |
| 269 function observeExists(pattern, ptype) { |
| 270 window.domAutomationController.send("success"); |
| 271 var node = firstMatchingNode(pattern, ptype); |
| 272 if (node && nodeValueTextEquals(node, expected_value)) { |
| 273 raiseEvent(); |
| 274 console.log("Node already exists in DOM."); |
| 275 return; |
| 276 } |
| 277 |
| 278 var obs = new WebKitMutationObserver(existsNodeCallback); |
| 279 obs.observe(document, |
| 280 { childList: true, |
| 281 attributes: true, |
| 282 subtree: true}); |
| 283 } |
| 246 | 284 |
| 247 /* Interpret arguments and launch the requested observer function. */ | 285 /* Interpret arguments and launch the requested observer function. */ |
| 248 var observer; | 286 var observer; |
| 249 switch (observer_type) { | 287 switch (observer_type) { |
| 250 case "add": | 288 case "add": |
| 251 observeAdd(pattern, ptype); | 289 observeAdd(pattern, ptype); |
| 252 break; | 290 break; |
| 253 case "remove": | 291 case "remove": |
| 254 observeRemove(pattern, ptype); | 292 observeRemove(pattern, ptype); |
| 255 break; | 293 break; |
| 256 case "change": | 294 case "change": |
| 257 observeChange(pattern, ptype); | 295 observeChange(pattern, ptype); |
| 258 break; | 296 break; |
| 297 case "exists": |
| 298 observeExists(pattern, ptype); |
| 299 break; |
| 259 } | 300 } |
| 260 | 301 |
| 261 console.log("MutationObserver javscript injection completed.") | 302 console.log("MutationObserver javscript injection completed.") |
| 262 | 303 |
| 263 } | 304 } |
| OLD | NEW |