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

Side by Side Diff: resources/inspector/InjectedScript.js

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

Powered by Google App Engine
This is Rietveld 408576698