Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: chrome_frame/tools/test/reference_build/chrome/resources/inspector/InjectedScript.js

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007 Apple 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 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 var InjectedScript = {};
30
31 // Called from within InspectorController on the 'inspected page' side.
32 InjectedScript.reset = function()
33 {
34 InjectedScript._styles = {};
35 InjectedScript._styleRules = {};
36 InjectedScript._lastStyleId = 0;
37 InjectedScript._lastStyleRuleId = 0;
38 InjectedScript._searchResults = [];
39 InjectedScript._includedInSearchResultsPropertyName = "__includedInInspector SearchResults";
40 }
41
42 InjectedScript.reset();
43
44 InjectedScript.dispatch = function(methodName, args)
45 {
46 var result = InjectedScript[methodName].apply(InjectedScript, JSON.parse(arg s));
47 return JSON.stringify(result);
48 }
49
50 InjectedScript.getStyles = function(nodeId, authorOnly)
51 {
52 var node = InjectedScript._nodeForId(nodeId);
53 if (!node)
54 return false;
55 var matchedRules = InjectedScript._window().getMatchedCSSRules(node, "", aut horOnly);
56 var matchedCSSRules = [];
57 for (var i = 0; matchedRules && i < matchedRules.length; ++i)
58 matchedCSSRules.push(InjectedScript._serializeRule(matchedRules[i]));
59
60 var styleAttributes = {};
61 var attributes = node.attributes;
62 for (var i = 0; attributes && i < attributes.length; ++i) {
63 if (attributes[i].style)
64 styleAttributes[attributes[i].name] = InjectedScript._serializeStyle (attributes[i].style, true);
65 }
66 var result = {};
67 result.inlineStyle = InjectedScript._serializeStyle(node.style, true);
68 result.computedStyle = InjectedScript._serializeStyle(InjectedScript._window ().getComputedStyle(node));
69 result.matchedCSSRules = matchedCSSRules;
70 result.styleAttributes = styleAttributes;
71 return result;
72 }
73
74 InjectedScript.getComputedStyle = function(nodeId)
75 {
76 var node = InjectedScript._nodeForId(nodeId);
77 if (!node)
78 return false;
79 return InjectedScript._serializeStyle(InjectedScript._window().getComputedSt yle(node));
80 }
81
82 InjectedScript.getInlineStyle = function(nodeId)
83 {
84 var node = InjectedScript._nodeForId(nodeId);
85 if (!node)
86 return false;
87 return InjectedScript._serializeStyle(node.style, true);
88 }
89
90 InjectedScript.applyStyleText = function(styleId, styleText, propertyName)
91 {
92 var style = InjectedScript._styles[styleId];
93 if (!style)
94 return false;
95
96 var styleTextLength = styleText.length;
97
98 // Create a new element to parse the user input CSS.
99 var parseElement = document.createElement("span");
100 parseElement.setAttribute("style", styleText);
101
102 var tempStyle = parseElement.style;
103 if (tempStyle.length || !styleTextLength) {
104 // The input was parsable or the user deleted everything, so remove the
105 // original property from the real style declaration. If this represents
106 // a shorthand remove all the longhand properties.
107 if (style.getPropertyShorthand(propertyName)) {
108 var longhandProperties = InjectedScript._getLonghandProperties(style , propertyName);
109 for (var i = 0; i < longhandProperties.length; ++i)
110 style.removeProperty(longhandProperties[i]);
111 } else
112 style.removeProperty(propertyName);
113 }
114
115 // Notify caller that the property was successfully deleted.
116 if (!styleTextLength)
117 return [null, [propertyName]];
118
119 if (!tempStyle.length)
120 return false;
121
122 // Iterate of the properties on the test element's style declaration and
123 // add them to the real style declaration. We take care to move shorthands.
124 var foundShorthands = {};
125 var changedProperties = [];
126 var uniqueProperties = InjectedScript._getUniqueStyleProperties(tempStyle);
127 for (var i = 0; i < uniqueProperties.length; ++i) {
128 var name = uniqueProperties[i];
129 var shorthand = tempStyle.getPropertyShorthand(name);
130
131 if (shorthand && shorthand in foundShorthands)
132 continue;
133
134 if (shorthand) {
135 var value = InjectedScript._getShorthandValue(tempStyle, shorthand);
136 var priority = InjectedScript._getShorthandPriority(tempStyle, short hand);
137 foundShorthands[shorthand] = true;
138 } else {
139 var value = tempStyle.getPropertyValue(name);
140 var priority = tempStyle.getPropertyPriority(name);
141 }
142
143 // Set the property on the real style declaration.
144 style.setProperty((shorthand || name), value, priority);
145 changedProperties.push(shorthand || name);
146 }
147 return [InjectedScript._serializeStyle(style, true), changedProperties];
148 }
149
150 InjectedScript.setStyleText = function(style, cssText)
151 {
152 style.cssText = cssText;
153 }
154
155 InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled)
156 {
157 var style = InjectedScript._styles[styleId];
158 if (!style)
159 return false;
160
161 if (disabled) {
162 if (!style.__disabledPropertyValues || !style.__disabledPropertyPrioriti es) {
163 var inspectedWindow = InjectedScript._window();
164 style.__disabledProperties = new inspectedWindow.Object;
165 style.__disabledPropertyValues = new inspectedWindow.Object;
166 style.__disabledPropertyPriorities = new inspectedWindow.Object;
167 }
168
169 style.__disabledPropertyValues[propertyName] = style.getPropertyValue(pr opertyName);
170 style.__disabledPropertyPriorities[propertyName] = style.getPropertyPrio rity(propertyName);
171
172 if (style.getPropertyShorthand(propertyName)) {
173 var longhandProperties = InjectedScript._getLonghandProperties(style , propertyName);
174 for (var i = 0; i < longhandProperties.length; ++i) {
175 style.__disabledProperties[longhandProperties[i]] = true;
176 style.removeProperty(longhandProperties[i]);
177 }
178 } else {
179 style.__disabledProperties[propertyName] = true;
180 style.removeProperty(propertyName);
181 }
182 } else if (style.__disabledProperties && style.__disabledProperties[property Name]) {
183 var value = style.__disabledPropertyValues[propertyName];
184 var priority = style.__disabledPropertyPriorities[propertyName];
185
186 style.setProperty(propertyName, value, priority);
187 delete style.__disabledProperties[propertyName];
188 delete style.__disabledPropertyValues[propertyName];
189 delete style.__disabledPropertyPriorities[propertyName];
190 }
191 return InjectedScript._serializeStyle(style, true);
192 }
193
194 InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNodeId)
195 {
196 var rule = InjectedScript._styleRules[ruleId];
197 if (!rule)
198 return false;
199
200 var selectedNode = InjectedScript._nodeForId(selectedNodeId);
201
202 try {
203 var stylesheet = rule.parentStyleSheet;
204 stylesheet.addRule(newContent);
205 var newRule = stylesheet.cssRules[stylesheet.cssRules.length - 1];
206 newRule.style.cssText = rule.style.cssText;
207
208 var parentRules = stylesheet.cssRules;
209 for (var i = 0; i < parentRules.length; ++i) {
210 if (parentRules[i] === rule) {
211 rule.parentStyleSheet.removeRule(i);
212 break;
213 }
214 }
215
216 return [InjectedScript._serializeRule(newRule), InjectedScript._doesSele ctorAffectNode(newContent, selectedNode)];
217 } catch(e) {
218 // Report invalid syntax.
219 return false;
220 }
221 }
222
223 InjectedScript.addStyleSelector = function(newContent, selectedNodeId)
224 {
225 var stylesheet = InjectedScript.stylesheet;
226 if (!stylesheet) {
227 var inspectedDocument = InjectedScript._window().document;
228 var head = inspectedDocument.getElementsByTagName("head")[0];
229 var styleElement = inspectedDocument.createElement("style");
230 styleElement.type = "text/css";
231 head.appendChild(styleElement);
232 stylesheet = inspectedDocument.styleSheets[inspectedDocument.styleSheets .length - 1];
233 InjectedScript.stylesheet = stylesheet;
234 }
235
236 try {
237 stylesheet.addRule(newContent);
238 } catch (e) {
239 // Invalid Syntax for a Selector
240 return false;
241 }
242
243 var selectedNode = InjectedScript._nodeForId(selectedNodeId);
244 var rule = stylesheet.cssRules[stylesheet.cssRules.length - 1];
245 rule.__isViaInspector = true;
246
247 return [ InjectedScript._serializeRule(rule), InjectedScript._doesSelectorAf fectNode(newContent, selectedNode) ];
248 }
249
250 InjectedScript._doesSelectorAffectNode = function(selectorText, node)
251 {
252 if (!node)
253 return false;
254 var nodes = node.ownerDocument.querySelectorAll(selectorText);
255 for (var i = 0; i < nodes.length; ++i) {
256 if (nodes[i] === node) {
257 return true;
258 }
259 }
260 return false;
261 }
262
263 InjectedScript.setStyleProperty = function(styleId, name, value)
264 {
265 var style = InjectedScript._styles[styleId];
266 if (!style)
267 return false;
268
269 style.setProperty(name, value, "");
270 return true;
271 }
272
273 InjectedScript._serializeRule = function(rule)
274 {
275 var parentStyleSheet = rule.parentStyleSheet;
276
277 var ruleValue = {};
278 ruleValue.selectorText = rule.selectorText;
279 if (parentStyleSheet) {
280 ruleValue.parentStyleSheet = {};
281 ruleValue.parentStyleSheet.href = parentStyleSheet.href;
282 }
283 ruleValue.isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode && ! parentStyleSheet.href;
284 ruleValue.isUser = parentStyleSheet && parentStyleSheet.ownerNode && parentS tyleSheet.ownerNode.nodeName == "#document";
285 ruleValue.isViaInspector = !!rule.__isViaInspector;
286
287 // Bind editable scripts only.
288 var doBind = !ruleValue.isUserAgent && !ruleValue.isUser;
289 ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind);
290
291 if (doBind) {
292 if (!rule.id) {
293 rule.id = InjectedScript._lastStyleRuleId++;
294 InjectedScript._styleRules[rule.id] = rule;
295 }
296 ruleValue.id = rule.id;
297 }
298 return ruleValue;
299 }
300
301 InjectedScript._serializeStyle = function(style, doBind)
302 {
303 var result = {};
304 result.width = style.width;
305 result.height = style.height;
306 result.__disabledProperties = style.__disabledProperties;
307 result.__disabledPropertyValues = style.__disabledPropertyValues;
308 result.__disabledPropertyPriorities = style.__disabledPropertyPriorities;
309 result.properties = [];
310 result.shorthandValues = {};
311 var foundShorthands = {};
312 for (var i = 0; i < style.length; ++i) {
313 var property = {};
314 var name = style[i];
315 property.name = name;
316 property.priority = style.getPropertyPriority(name);
317 property.implicit = style.isPropertyImplicit(name);
318 var shorthand = style.getPropertyShorthand(name);
319 property.shorthand = shorthand;
320 if (shorthand && !(shorthand in foundShorthands)) {
321 foundShorthands[shorthand] = true;
322 result.shorthandValues[shorthand] = InjectedScript._getShorthandValu e(style, shorthand);
323 }
324 property.value = style.getPropertyValue(name);
325 result.properties.push(property);
326 }
327 result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(styl e);
328
329 if (doBind) {
330 if (!style.id) {
331 style.id = InjectedScript._lastStyleId++;
332 InjectedScript._styles[style.id] = style;
333 }
334 result.id = style.id;
335 }
336 return result;
337 }
338
339 InjectedScript._getUniqueStyleProperties = function(style)
340 {
341 var properties = [];
342 var foundProperties = {};
343
344 for (var i = 0; i < style.length; ++i) {
345 var property = style[i];
346 if (property in foundProperties)
347 continue;
348 foundProperties[property] = true;
349 properties.push(property);
350 }
351
352 return properties;
353 }
354
355
356 InjectedScript._getLonghandProperties = function(style, shorthandProperty)
357 {
358 var properties = [];
359 var foundProperties = {};
360
361 for (var i = 0; i < style.length; ++i) {
362 var individualProperty = style[i];
363 if (individualProperty in foundProperties || style.getPropertyShorthand( individualProperty) !== shorthandProperty)
364 continue;
365 foundProperties[individualProperty] = true;
366 properties.push(individualProperty);
367 }
368
369 return properties;
370 }
371
372 InjectedScript._getShorthandValue = function(style, shorthandProperty)
373 {
374 var value = style.getPropertyValue(shorthandProperty);
375 if (!value) {
376 // Some shorthands (like border) return a null value, so compute a short hand value.
377 // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823 is fixed.
378
379 var foundProperties = {};
380 for (var i = 0; i < style.length; ++i) {
381 var individualProperty = style[i];
382 if (individualProperty in foundProperties || style.getPropertyShorth and(individualProperty) !== shorthandProperty)
383 continue;
384
385 var individualValue = style.getPropertyValue(individualProperty);
386 if (style.isPropertyImplicit(individualProperty) || individualValue === "initial")
387 continue;
388
389 foundProperties[individualProperty] = true;
390
391 if (!value)
392 value = "";
393 else if (value.length)
394 value += " ";
395 value += individualValue;
396 }
397 }
398 return value;
399 }
400
401 InjectedScript._getShorthandPriority = function(style, shorthandProperty)
402 {
403 var priority = style.getPropertyPriority(shorthandProperty);
404 if (!priority) {
405 for (var i = 0; i < style.length; ++i) {
406 var individualProperty = style[i];
407 if (style.getPropertyShorthand(individualProperty) !== shorthandProp erty)
408 continue;
409 priority = style.getPropertyPriority(individualProperty);
410 break;
411 }
412 }
413 return priority;
414 }
415
416 InjectedScript.getPrototypes = function(nodeId)
417 {
418 var node = InjectedScript._nodeForId(nodeId);
419 if (!node)
420 return false;
421
422 var result = [];
423 for (var prototype = node; prototype; prototype = prototype.__proto__) {
424 var title = Object.describe(prototype);
425 if (title.match(/Prototype$/)) {
426 title = title.replace(/Prototype$/, "");
427 }
428 result.push(title);
429 }
430 return result;
431 }
432
433 InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty)
434 {
435 var object = InjectedScript._resolveObject(objectProxy);
436 if (!object)
437 return false;
438
439 var properties = [];
440
441 // Go over properties, prepare results.
442 for (var propertyName in object) {
443 if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOw nProperty(propertyName))
444 continue;
445
446 var property = {};
447 property.name = propertyName;
448 property.parentObjectProxy = objectProxy;
449 var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(pro pertyName);
450 if (!property.isGetter) {
451 var childObject = object[propertyName];
452 var childObjectProxy = new InjectedScript.createProxyObject(childObj ect, objectProxy.objectId, true);
453 childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : [];
454 childObjectProxy.path.push(propertyName);
455 childObjectProxy.protoDepth = objectProxy.protoDepth || 0;
456 property.value = childObjectProxy;
457 } else {
458 // FIXME: this should show something like "getter" (bug 16734).
459 property.value = { description: "\u2014" }; // em dash
460 property.isGetter = true;
461 }
462 properties.push(property);
463 }
464 return properties;
465 }
466
467 InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression )
468 {
469 var object = InjectedScript._resolveObject(objectProxy);
470 if (!object)
471 return false;
472
473 var expressionLength = expression.length;
474 if (!expressionLength) {
475 delete object[propertyName];
476 return !(propertyName in object);
477 }
478
479 try {
480 // Surround the expression in parenthesis so the result of the eval is t he result
481 // of the whole expression not the last potential sub-expression.
482
483 // There is a regression introduced here: eval is now happening against global object,
484 // not call frame while on a breakpoint.
485 // TODO: bring evaluation against call frame back.
486 var result = InjectedScript._window().eval("(" + expression + ")");
487 // Store the result in the property.
488 object[propertyName] = result;
489 return true;
490 } catch(e) {
491 try {
492 var result = InjectedScript._window().eval("\"" + expression.escapeC haracters("\"") + "\"");
493 object[propertyName] = result;
494 return true;
495 } catch(e) {
496 return false;
497 }
498 }
499 }
500
501
502 InjectedScript.getCompletions = function(expression, includeInspectorCommandLine API)
503 {
504 var props = {};
505 try {
506 var expressionResult = InjectedScript._evaluateOn(InjectedScript._window ().eval, InjectedScript._window(), expression);
507 for (var prop in expressionResult)
508 props[prop] = true;
509 if (includeInspectorCommandLineAPI)
510 for (var prop in InjectedScript._window()._inspectorCommandLineAPI)
511 if (prop.charAt(0) !== '_')
512 props[prop] = true;
513 } catch(e) {
514 }
515 return props;
516 }
517
518
519 InjectedScript.evaluate = function(expression)
520 {
521 var result = {};
522 try {
523 var value = InjectedScript._evaluateOn(InjectedScript._window().eval, In jectedScript._window(), expression);
524 if (value === null)
525 return { value: null };
526 if (Object.type(value) === "error") {
527 result.value = Object.describe(value);
528 result.isException = true;
529 return result;
530 }
531
532 var wrapper = InspectorController.wrapObject(value);
533 if (typeof wrapper === "object" && wrapper.exception) {
534 result.value = wrapper.exception;
535 result.isException = true;
536 } else {
537 result.value = wrapper;
538 }
539 } catch (e) {
540 result.value = e.toString();
541 result.isException = true;
542 }
543 return result;
544 }
545
546 InjectedScript._evaluateOn = function(evalFunction, object, expression)
547 {
548 InjectedScript._ensureCommandLineAPIInstalled();
549 // Surround the expression in with statements to inject our command line API so that
550 // the window object properties still take more precedent than our API funct ions.
551 expression = "with (window._inspectorCommandLineAPI) { with (window) { " + e xpression + " } }";
552 return evalFunction.call(object, expression);
553 }
554
555 InjectedScript.addInspectedNode = function(nodeId)
556 {
557 var node = InjectedScript._nodeForId(nodeId);
558 if (!node)
559 return false;
560
561 InjectedScript._ensureCommandLineAPIInstalled();
562 var inspectedNodes = InjectedScript._window()._inspectorCommandLineAPI._insp ectedNodes;
563 inspectedNodes.unshift(node);
564 if (inspectedNodes.length >= 5)
565 inspectedNodes.pop();
566 return true;
567 }
568
569 InjectedScript.performSearch = function(whitespaceTrimmedQuery)
570 {
571 var tagNameQuery = whitespaceTrimmedQuery;
572 var attributeNameQuery = whitespaceTrimmedQuery;
573 var startTagFound = (tagNameQuery.indexOf("<") === 0);
574 var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1));
575
576 if (startTagFound || endTagFound) {
577 var tagNameQueryLength = tagNameQuery.length;
578 tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFo und ? (tagNameQueryLength - 1) : tagNameQueryLength));
579 }
580
581 // Check the tagNameQuery is it is a possibly valid tag name.
582 if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery))
583 tagNameQuery = null;
584
585 // Check the attributeNameQuery is it is a possibly valid tag name.
586 if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery))
587 attributeNameQuery = null;
588
589 const escapedQuery = whitespaceTrimmedQuery.escapeCharacters("'");
590 const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("' ") : null);
591 const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacter s("'");
592 const searchResultsProperty = InjectedScript._includedInSearchResultsPropert yName;
593
594 function addNodesToResults(nodes, length, getItem)
595 {
596 if (!length)
597 return;
598
599 var nodeIds = [];
600 for (var i = 0; i < length; ++i) {
601 var node = getItem.call(nodes, i);
602 // Skip this node if it already has the property.
603 if (searchResultsProperty in node)
604 continue;
605
606 if (!InjectedScript._searchResults.length) {
607 InjectedScript._currentSearchResultIndex = 0;
608 }
609
610 node[searchResultsProperty] = true;
611 InjectedScript._searchResults.push(node);
612 var nodeId = InspectorController.pushNodePathToFrontend(node, false) ;
613 nodeIds.push(nodeId);
614 }
615 InspectorController.addNodesToSearchResult(nodeIds.join(","));
616 }
617
618 function matchExactItems(doc)
619 {
620 matchExactId.call(this, doc);
621 matchExactClassNames.call(this, doc);
622 matchExactTagNames.call(this, doc);
623 matchExactAttributeNames.call(this, doc);
624 }
625
626 function matchExactId(doc)
627 {
628 const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQ uery);
629 addNodesToResults.call(this, result, (result ? 1 : 0), function() { retu rn this });
630 }
631
632 function matchExactClassNames(doc)
633 {
634 const result = doc.__proto__.getElementsByClassName.call(doc, whitespace TrimmedQuery);
635 addNodesToResults.call(this, result, result.length, result.item);
636 }
637
638 function matchExactTagNames(doc)
639 {
640 if (!tagNameQuery)
641 return;
642 const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery );
643 addNodesToResults.call(this, result, result.length, result.item);
644 }
645
646 function matchExactAttributeNames(doc)
647 {
648 if (!attributeNameQuery)
649 return;
650 const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeN ameQuery + "]");
651 addNodesToResults.call(this, result, result.length, result.item);
652 }
653
654 function matchPartialTagNames(doc)
655 {
656 if (!tagNameQuery)
657 return;
658 const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYP E);
659 addNodesToResults.call(this, result, result.snapshotLength, result.snaps hotItem);
660 }
661
662 function matchStartOfTagNames(doc)
663 {
664 if (!tagNameQuery)
665 return;
666 const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_ TYPE);
667 addNodesToResults.call(this, result, result.snapshotLength, result.snaps hotItem);
668 }
669
670 function matchPartialTagNamesAndAttributeValues(doc)
671 {
672 if (!tagNameQuery) {
673 matchPartialAttributeValues.call(this, doc);
674 return;
675 }
676
677 const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, nul l, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
678 addNodesToResults.call(this, result, result.snapshotLength, result.snaps hotItem);
679 }
680
681 function matchPartialAttributeValues(doc)
682 {
683 const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + e scapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
684 addNodesToResults.call(this, result, result.snapshotLength, result.snaps hotItem);
685 }
686
687 function matchStyleSelector(doc)
688 {
689 const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimme dQuery);
690 addNodesToResults.call(this, result, result.length, result.item);
691 }
692
693 function matchPlainText(doc)
694 {
695 const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
696 addNodesToResults.call(this, result, result.snapshotLength, result.snaps hotItem);
697 }
698
699 function matchXPathQuery(doc)
700 {
701 const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
702 addNodesToResults.call(this, result, result.snapshotLength, result.snaps hotItem);
703 }
704
705 function finishedSearching()
706 {
707 // Remove the searchResultsProperty now that the search is finished.
708 for (var i = 0; i < InjectedScript._searchResults.length; ++i)
709 delete InjectedScript._searchResults[i][searchResultsProperty];
710 }
711
712 const mainFrameDocument = InjectedScript._window().document;
713 const searchDocuments = [mainFrameDocument];
714 var searchFunctions;
715 if (tagNameQuery && startTagFound && endTagFound)
716 searchFunctions = [matchExactTagNames, matchPlainText];
717 else if (tagNameQuery && startTagFound)
718 searchFunctions = [matchStartOfTagNames, matchPlainText];
719 else if (tagNameQuery && endTagFound) {
720 // FIXME: we should have a matchEndOfTagNames search function if endTagF ound is true but not startTagFound.
721 // This requires ends-with() support in XPath, WebKit only supports star ts-with() and contains().
722 searchFunctions = [matchPartialTagNames, matchPlainText];
723 } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "* ") {
724 // These queries will match every node. Matching everything isn't useful and can be slow for large pages,
725 // so limit the search functions list to plain text and attribute matchi ng.
726 searchFunctions = [matchPartialAttributeValues, matchPlainText];
727 } else
728 searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagN amesAndAttributeValues, matchPlainText, matchXPathQuery];
729
730 // Find all frames, iframes and object elements to search their documents.
731 const querySelectorAllFunction = InjectedScript._window().Document.prototype .querySelectorAll;
732 const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, " iframe, frame, object");
733
734 for (var i = 0; i < subdocumentResult.length; ++i) {
735 var element = subdocumentResult.item(i);
736 if (element.contentDocument)
737 searchDocuments.push(element.contentDocument);
738 }
739
740 const panel = InjectedScript;
741 var documentIndex = 0;
742 var searchFunctionIndex = 0;
743 var chunkIntervalIdentifier = null;
744
745 // Split up the work into chunks so we don't block the UI thread while proce ssing.
746
747 function processChunk()
748 {
749 var searchDocument = searchDocuments[documentIndex];
750 var searchFunction = searchFunctions[searchFunctionIndex];
751
752 if (++searchFunctionIndex > searchFunctions.length) {
753 searchFunction = searchFunctions[0];
754 searchFunctionIndex = 0;
755
756 if (++documentIndex > searchDocuments.length) {
757 if (panel._currentSearchChunkIntervalIdentifier === chunkInterva lIdentifier)
758 delete panel._currentSearchChunkIntervalIdentifier;
759 clearInterval(chunkIntervalIdentifier);
760 finishedSearching.call(panel);
761 return;
762 }
763
764 searchDocument = searchDocuments[documentIndex];
765 }
766
767 if (!searchDocument || !searchFunction)
768 return;
769
770 try {
771 searchFunction.call(panel, searchDocument);
772 } catch(err) {
773 // ignore any exceptions. the query might be malformed, but we allow that.
774 }
775 }
776
777 processChunk();
778
779 chunkIntervalIdentifier = setInterval(processChunk, 25);
780 InjectedScript._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifi er;
781 return true;
782 }
783
784 InjectedScript.searchCanceled = function()
785 {
786 if (InjectedScript._searchResults) {
787 const searchResultsProperty = InjectedScript._includedInSearchResultsPro pertyName;
788 for (var i = 0; i < this._searchResults.length; ++i) {
789 var node = this._searchResults[i];
790
791 // Remove the searchResultsProperty since there might be an unfinish ed search.
792 delete node[searchResultsProperty];
793 }
794 }
795
796 if (InjectedScript._currentSearchChunkIntervalIdentifier) {
797 clearInterval(InjectedScript._currentSearchChunkIntervalIdentifier);
798 delete InjectedScript._currentSearchChunkIntervalIdentifier;
799 }
800 InjectedScript._searchResults = [];
801 return true;
802 }
803
804 InjectedScript.openInInspectedWindow = function(url)
805 {
806 InjectedScript._window().open(url);
807 }
808
809 InjectedScript.getCallFrames = function()
810 {
811 var callFrame = InspectorController.currentCallFrame();
812 if (!callFrame)
813 return false;
814
815 var result = [];
816 var depth = 0;
817 do {
818 result.push(new InjectedScript.CallFrameProxy(depth++, callFrame));
819 callFrame = callFrame.caller;
820 } while (callFrame);
821 return result;
822 }
823
824 InjectedScript.evaluateInCallFrame = function(callFrameId, code)
825 {
826 var callFrame = InjectedScript._callFrameForId(callFrameId);
827 if (!callFrame)
828 return false;
829 return InjectedScript._evaluateOn(callFrame.evaluate, callFrame, code);
830 }
831
832 InjectedScript._callFrameForId = function(id)
833 {
834 var callFrame = InspectorController.currentCallFrame();
835 while (--id >= 0 && callFrame)
836 callFrame = callFrame.caller;
837 return callFrame;
838 }
839
840 InjectedScript._clearConsoleMessages = function()
841 {
842 InspectorController.clearMessages(true);
843 }
844
845 InjectedScript._inspectObject = function(o)
846 {
847 if (arguments.length === 0)
848 return;
849
850 var inspectedWindow = InjectedScript._window();
851 inspectedWindow.console.log(o);
852 if (Object.type(o) === "node") {
853 InspectorController.pushNodePathToFrontend(o, true);
854 } else {
855 switch (Object.describe(o)) {
856 case "Database":
857 InspectorController.selectDatabase(o);
858 break;
859 case "Storage":
860 InspectorController.selectDOMStorage(o);
861 break;
862 }
863 }
864 }
865
866 InjectedScript._ensureCommandLineAPIInstalled = function(inspectedWindow)
867 {
868 var inspectedWindow = InjectedScript._window();
869 if (inspectedWindow._inspectorCommandLineAPI)
870 return;
871
872 inspectedWindow.eval("window._inspectorCommandLineAPI = { \
873 $: function() { return document.getElementById.apply(document, arguments ) }, \
874 $$: function() { return document.querySelectorAll.apply(document, argume nts) }, \
875 $x: function(xpath, context) { \
876 var nodes = []; \
877 try { \
878 var doc = context || document; \
879 var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYP E, null); \
880 var node; \
881 while (node = results.iterateNext()) nodes.push(node); \
882 } catch (e) {} \
883 return nodes; \
884 }, \
885 dir: function() { return console.dir.apply(console, arguments) }, \
886 dirxml: function() { return console.dirxml.apply(console, arguments) }, \
887 keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \
888 values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \
889 profile: function() { return console.profile.apply(console, arguments) } , \
890 profileEnd: function() { return console.profileEnd.apply(console, argume nts) }, \
891 _inspectedNodes: [], \
892 get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \
893 get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \
894 get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \
895 get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \
896 get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \
897 };");
898
899 inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCal lback(InjectedScript._clearConsoleMessages);
900 inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapC allback(InjectedScript._inspectObject);
901 }
902
903 InjectedScript._resolveObject = function(objectProxy)
904 {
905 var object = InjectedScript._objectForId(objectProxy.objectId);
906 var path = objectProxy.path;
907 var protoDepth = objectProxy.protoDepth;
908
909 // Follow the property path.
910 for (var i = 0; object && path && i < path.length; ++i)
911 object = object[path[i]];
912
913 // Get to the necessary proto layer.
914 for (var i = 0; object && protoDepth && i < protoDepth; ++i)
915 object = object.__proto__;
916
917 return object;
918 }
919
920 InjectedScript._window = function()
921 {
922 // TODO: replace with 'return window;' once this script is injected into
923 // the page's context.
924 return InspectorController.inspectedWindow();
925 }
926
927 InjectedScript._nodeForId = function(nodeId)
928 {
929 if (!nodeId)
930 return null;
931 return InspectorController.nodeForId(nodeId);
932 }
933
934 InjectedScript._objectForId = function(objectId)
935 {
936 // There are three types of object ids used:
937 // - numbers point to DOM Node via the InspectorDOMAgent mapping
938 // - strings point to console objects cached in InspectorController for lazy evaluation upon them
939 // - objects contain complex ids and are currently used for scoped objects
940 if (typeof objectId === "number") {
941 return InjectedScript._nodeForId(objectId);
942 } else if (typeof objectId === "string") {
943 return InspectorController.unwrapObject(objectId);
944 } else if (typeof objectId === "object") {
945 var callFrame = InjectedScript._callFrameForId(objectId.callFrame);
946 if (objectId.thisObject)
947 return callFrame.thisObject;
948 else
949 return callFrame.scopeChain[objectId.chainIndex];
950 }
951 return objectId;
952 }
953
954 InjectedScript.pushNodeToFrontend = function(objectProxy)
955 {
956 var object = InjectedScript._resolveObject(objectProxy);
957 if (!object || Object.type(object) !== "node")
958 return false;
959 return InspectorController.pushNodePathToFrontend(object, false);
960 }
961
962 // Called from within InspectorController on the 'inspected page' side.
963 InjectedScript.createProxyObject = function(object, objectId, abbreviate)
964 {
965 var result = {};
966 result.objectId = objectId;
967 result.type = Object.type(object);
968
969 var type = typeof object;
970 if ((type === "object" && object !== null) || type === "function") {
971 for (var subPropertyName in object) {
972 result.hasChildren = true;
973 break;
974 }
975 }
976 try {
977 result.description = Object.describe(object, abbreviate);
978 } catch (e) {
979 result.exception = e.toString();
980 }
981 return result;
982 }
983
984 InjectedScript.CallFrameProxy = function(id, callFrame)
985 {
986 this.id = id;
987 this.type = callFrame.type;
988 this.functionName = (this.type === "function" ? callFrame.functionName : "") ;
989 this.sourceID = callFrame.sourceID;
990 this.line = callFrame.line;
991 this.scopeChain = this._wrapScopeChain(callFrame);
992 }
993
994 InjectedScript.CallFrameProxy.prototype = {
995 _wrapScopeChain: function(callFrame)
996 {
997 var foundLocalScope = false;
998 var scopeChain = callFrame.scopeChain;
999 var scopeChainProxy = [];
1000 for (var i = 0; i < scopeChain.length; ++i) {
1001 var scopeObject = scopeChain[i];
1002 var scopeObjectProxy = InjectedScript.createProxyObject(scopeObject, { callFrame: this.id, chainIndex: i });
1003
1004 if (Object.prototype.toString.call(scopeObject) === "[object JSActiv ation]") {
1005 if (!foundLocalScope)
1006 scopeObjectProxy.thisObject = InjectedScript.createProxyObje ct(callFrame.thisObject, { callFrame: this.id, thisObject: true });
1007 else
1008 scopeObjectProxy.isClosure = true;
1009 foundLocalScope = true;
1010 scopeObjectProxy.isLocal = true;
1011 } else if (foundLocalScope && scopeObject instanceof InjectedScript. _window().Element)
1012 scopeObjectProxy.isElement = true;
1013 else if (foundLocalScope && scopeObject instanceof InjectedScript._w indow().Document)
1014 scopeObjectProxy.isDocument = true;
1015 else if (!foundLocalScope)
1016 scopeObjectProxy.isWithBlock = true;
1017 scopeObjectProxy.properties = [];
1018 try {
1019 for (var propertyName in scopeObject)
1020 scopeObjectProxy.properties.push(propertyName);
1021 } catch (e) {
1022 }
1023 scopeChainProxy.push(scopeObjectProxy);
1024 }
1025 return scopeChainProxy;
1026 }
1027 }
1028
1029 Object.type = function(obj)
1030 {
1031 if (obj === null)
1032 return "null";
1033
1034 var type = typeof obj;
1035 if (type !== "object" && type !== "function")
1036 return type;
1037
1038 var win = InjectedScript._window();
1039
1040 if (obj instanceof win.Node)
1041 return (obj.nodeType === undefined ? type : "node");
1042 if (obj instanceof win.String)
1043 return "string";
1044 if (obj instanceof win.Array)
1045 return "array";
1046 if (obj instanceof win.Boolean)
1047 return "boolean";
1048 if (obj instanceof win.Number)
1049 return "number";
1050 if (obj instanceof win.Date)
1051 return "date";
1052 if (obj instanceof win.RegExp)
1053 return "regexp";
1054 if (obj instanceof win.Error)
1055 return "error";
1056 return type;
1057 }
1058
1059 Object.hasProperties = function(obj)
1060 {
1061 if (typeof obj === "undefined" || typeof obj === "null")
1062 return false;
1063 for (var name in obj)
1064 return true;
1065 return false;
1066 }
1067
1068 Object.describe = function(obj, abbreviated)
1069 {
1070 var type1 = Object.type(obj);
1071 var type2 = Object.className(obj);
1072
1073 switch (type1) {
1074 case "object":
1075 case "node":
1076 return type2;
1077 case "array":
1078 return "[" + obj.toString() + "]";
1079 case "string":
1080 if (obj.length > 100)
1081 return "\"" + obj.substring(0, 100) + "\u2026\"";
1082 return "\"" + obj + "\"";
1083 case "function":
1084 var objectText = String(obj);
1085 if (!/^function /.test(objectText))
1086 objectText = (type2 == "object") ? type1 : type2;
1087 else if (abbreviated)
1088 objectText = /.*/.exec(obj)[0].replace(/ +$/g, "");
1089 return objectText;
1090 case "regexp":
1091 return String(obj).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
1092 default:
1093 return String(obj);
1094 }
1095 }
1096
1097 Object.className = function(obj)
1098 {
1099 return Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1 ")
1100 }
1101
1102 // Although Function.prototype.bind and String.prototype.escapeCharacters are de fined in utilities.js they will soon become
1103 // unavailable in the InjectedScript context. So we define them here for the loc al use.
1104 // TODO: remove this comment once InjectedScript runs in a separate context.
1105 Function.prototype.bind = function(thisObject)
1106 {
1107 var func = this;
1108 var args = Array.prototype.slice.call(arguments, 1);
1109 return function() { return func.apply(thisObject, args.concat(Array.prototyp e.slice.call(arguments, 0))) };
1110 }
1111
1112 String.prototype.escapeCharacters = function(chars)
1113 {
1114 var foundChar = false;
1115 for (var i = 0; i < chars.length; ++i) {
1116 if (this.indexOf(chars.charAt(i)) !== -1) {
1117 foundChar = true;
1118 break;
1119 }
1120 }
1121
1122 if (!foundChar)
1123 return this;
1124
1125 var result = "";
1126 for (var i = 0; i < this.length; ++i) {
1127 if (chars.indexOf(this.charAt(i)) !== -1)
1128 result += "\\";
1129 result += this.charAt(i);
1130 }
1131
1132 return result;
1133 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698