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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js

Issue 2439223002: DevTools: Use grey hint text for applied suggestion in TextPrompt (Closed)
Patch Set: Fix bug with completing in the middle of a prompt Created 4 years, 1 month 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
« no previous file with comments | « third_party/WebKit/LayoutTests/http/tests/inspector-unit/text-prompt-hint-expected.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 27 matching lines...) Expand all
38 { 38 {
39 /** 39 /**
40 * @type {!Element|undefined} 40 * @type {!Element|undefined}
41 */ 41 */
42 this._proxyElement; 42 this._proxyElement;
43 this._proxyElementDisplay = "inline-block"; 43 this._proxyElementDisplay = "inline-block";
44 this._loadCompletions = completions; 44 this._loadCompletions = completions;
45 this._completionStopCharacters = stopCharacters || " =:[({;,!+-*/&|^<>."; 45 this._completionStopCharacters = stopCharacters || " =:[({;,!+-*/&|^<>.";
46 this._autocompletionTimeout = WebInspector.TextPrompt.DefaultAutocompletionT imeout; 46 this._autocompletionTimeout = WebInspector.TextPrompt.DefaultAutocompletionT imeout;
47 this._title = ""; 47 this._title = "";
48 this._userEnteredRange = null;
48 this._previousText = ""; 49 this._previousText = "";
49 this._currentHintText = ""; 50 this._currentHintText = "";
50 this._completionRequestId = 0; 51 this._completionRequestId = 0;
52 this._autocompleteElement = createElementWithClass("span", "auto-complete-te xt");
51 } 53 }
52 54
53 WebInspector.TextPrompt.DefaultAutocompletionTimeout = 250; 55 WebInspector.TextPrompt.DefaultAutocompletionTimeout = 250;
54 56
55 /** @enum {symbol} */ 57 /** @enum {symbol} */
56 WebInspector.TextPrompt.Events = { 58 WebInspector.TextPrompt.Events = {
57 ItemApplied: Symbol("text-prompt-item-applied"), 59 ItemApplied: Symbol("text-prompt-item-applied"),
58 ItemAccepted: Symbol("text-prompt-item-accepted") 60 ItemAccepted: Symbol("text-prompt-item-accepted")
59 }; 61 };
60 62
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 this._proxyElement.appendChild(element); 135 this._proxyElement.appendChild(element);
134 this._element.classList.add("text-prompt"); 136 this._element.classList.add("text-prompt");
135 this._element.addEventListener("keydown", this._boundOnKeyDown, false); 137 this._element.addEventListener("keydown", this._boundOnKeyDown, false);
136 this._element.addEventListener("input", this._boundOnInput, false); 138 this._element.addEventListener("input", this._boundOnInput, false);
137 this._element.addEventListener("mousewheel", this._boundOnMouseWheel, fa lse); 139 this._element.addEventListener("mousewheel", this._boundOnMouseWheel, fa lse);
138 this._element.addEventListener("selectstart", this._boundSelectStart, fa lse); 140 this._element.addEventListener("selectstart", this._boundSelectStart, fa lse);
139 this._element.addEventListener("blur", this._boundClearAutocomplete, fal se); 141 this._element.addEventListener("blur", this._boundClearAutocomplete, fal se);
140 this._element.ownerDocument.defaultView.addEventListener("resize", this. _boundClearAutocomplete, false); 142 this._element.ownerDocument.defaultView.addEventListener("resize", this. _boundClearAutocomplete, false);
141 143
142 if (this._suggestBoxEnabled) 144 if (this._suggestBoxEnabled)
143 this._suggestBox = new WebInspector.SuggestBox(this); 145 this._suggestBox = new WebInspector.SuggestBox(this, 20, true);
144 146
145 if (this._title) 147 if (this._title)
146 this._proxyElement.title = this._title; 148 this._proxyElement.title = this._title;
147 149
148 return this._proxyElement; 150 return this._proxyElement;
149 }, 151 },
150 152
151 detach: function() 153 detach: function()
152 { 154 {
153 this._removeFromElement(); 155 this._removeFromElement();
(...skipping 11 matching lines...) Expand all
165 { 167 {
166 return this._element.textContent; 168 return this._element.textContent;
167 }, 169 },
168 170
169 /** 171 /**
170 * @return {string} 172 * @return {string}
171 */ 173 */
172 userEnteredText: function() 174 userEnteredText: function()
173 { 175 {
174 var text = this.text(); 176 var text = this.text();
175 if (this._autocompleteElement) { 177 if (this._autocompleteElement.parentNode) {
176 var addition = this._autocompleteElement.textContent; 178 var addition = this._autocompleteElement.textContent;
177 text = text.substring(0, text.length - addition.length); 179 text = text.substring(0, text.length - addition.length);
178 } 180 }
179 return text; 181 return text;
180 }, 182 },
181 183
182 /** 184 /**
183 * @param {string} x 185 * @param {string} x
184 */ 186 */
185 setText: function(x) 187 setText: function(x)
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 delete this._selectionTimeout; 275 delete this._selectionTimeout;
274 if (!this.isCaretInsidePrompt() && this._element.isComponentSelectio nCollapsed()) { 276 if (!this.isCaretInsidePrompt() && this._element.isComponentSelectio nCollapsed()) {
275 this.moveCaretToEndOfPrompt(); 277 this.moveCaretToEndOfPrompt();
276 this.autoCompleteSoon(); 278 this.autoCompleteSoon();
277 } 279 }
278 } 280 }
279 281
280 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); 282 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
281 }, 283 },
282 284
283
284 /** 285 /**
285 * @param {!Event} event 286 * @param {!Event} event
286 */ 287 */
287 onMouseWheel: function(event) 288 onMouseWheel: function(event)
288 { 289 {
289 // Subclasses can implement. 290 // Subclasses can implement.
290 }, 291 },
291 292
292 /** 293 /**
293 * @param {!Event} event 294 * @param {!Event} event
294 */ 295 */
295 onKeyDown: function(event) 296 onKeyDown: function(event)
296 { 297 {
297 if (isEnterKey(event))
298 return;
299
300 var handled = false; 298 var handled = false;
301 299
302 switch (event.key) { 300 switch (event.key) {
303 case "Tab": 301 case "Tab":
304 handled = this.tabKeyPressed(event); 302 handled = this.tabKeyPressed(event);
305 break; 303 break;
306 case "ArrowLeft": 304 case "ArrowLeft":
307 case "Home": 305 case "Home":
308 this.clearAutocomplete(); 306 this.clearAutocomplete();
309 break; 307 break;
(...skipping 29 matching lines...) Expand all
339 if (handled) 337 if (handled)
340 event.consume(true); 338 event.consume(true);
341 }, 339 },
342 340
343 /** 341 /**
344 * @param {!Event} event 342 * @param {!Event} event
345 */ 343 */
346 onInput: function(event) 344 onInput: function(event)
347 { 345 {
348 var text = this.userEnteredText(); 346 var text = this.userEnteredText();
349 var hasCommonPrefix = text.startsWith(this._previousText) || this._previ ousText.startsWith(text); 347 if (this._userEnteredRange && (text.startsWith(this._previousText) || th is._previousText.startsWith(text))) {
lushnikov 2016/10/22 02:15:10 let's get it back! it was so good!
einbinder 2016/10/22 02:30:05 Done.
350 if (this._autocompleteElement && hasCommonPrefix) 348 this._userEnteredRange.endColumn += text.length - this._previousText .length;
351 this._autocompleteElement.textContent = this._currentHintText.substr ing(text.length); 349 this._setAutocompleteText(this._currentHintText);
352 else 350 }
lushnikov 2016/10/22 02:15:10 nit: "else" on the previous line
einbinder 2016/10/22 02:30:05 Done.
351 else {
353 this._clearAutocompleteElement(); 352 this._clearAutocompleteElement();
353 }
354 this._previousText = text; 354 this._previousText = text;
355 355
356 this.autoCompleteSoon(); 356 this.autoCompleteSoon();
357 }, 357 },
358 358
359 /** 359 /**
360 * @return {boolean} 360 * @return {boolean}
361 */ 361 */
362 acceptAutoComplete: function() 362 acceptAutoComplete: function()
363 { 363 {
(...skipping 10 matching lines...) Expand all
374 { 374 {
375 if (this.isSuggestBoxVisible()) 375 if (this.isSuggestBoxVisible())
376 this._suggestBox.hide(); 376 this._suggestBox.hide();
377 this._clearAutocompleteElement(); 377 this._clearAutocompleteElement();
378 }, 378 },
379 379
380 _clearAutocompleteElement: function() 380 _clearAutocompleteElement: function()
381 { 381 {
382 this._clearAutocompleteTimeout(); 382 this._clearAutocompleteTimeout();
383 383
384 if (!this._autocompleteElement) 384 this._autocompleteElement.remove();
385 return; 385 this._userEnteredRange = null;
386 },
386 387
387 this._autocompleteElement.remove(); 388 /**
388 delete this._autocompleteElement; 389 * @param {string} text
389 delete this._userEnteredRange; 390 */
390 delete this._userEnteredText; 391 _setAutocompleteText: function(text)
392 {
393 if (this.isCaretAtEndOfPrompt() && this._userEnteredRange) {
394 this._autocompleteElement.textContent = text.substring(this._userEnt eredRange.endColumn - this._userEnteredRange.startColumn);
395 this._element.appendChild(this._autocompleteElement);
396 }
397 this._currentHintText = text;
391 }, 398 },
392 399
393 _clearAutocompleteTimeout: function() 400 _clearAutocompleteTimeout: function()
394 { 401 {
395 if (this._completeTimeout) { 402 if (this._completeTimeout) {
396 clearTimeout(this._completeTimeout); 403 clearTimeout(this._completeTimeout);
397 delete this._completeTimeout; 404 delete this._completeTimeout;
398 } 405 }
399 this._completionRequestId++; 406 this._completionRequestId++;
400 }, 407 },
(...skipping 22 matching lines...) Expand all
423 430
424 var shouldExit; 431 var shouldExit;
425 432
426 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( )) 433 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( ))
427 shouldExit = true; 434 shouldExit = true;
428 else if (!selection.isCollapsed) 435 else if (!selection.isCollapsed)
429 shouldExit = true; 436 shouldExit = true;
430 else if (!force) { 437 else if (!force) {
431 // BUG72018: Do not show suggest box if caret is followed by a non-s top character. 438 // BUG72018: Do not show suggest box if caret is followed by a non-s top character.
432 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward"); 439 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward");
433 var autocompleteTextLength = (this._autocompleteElement && this._aut ocompleteElement.parentNode) ? this._autocompleteElement.textContent.length : 0; 440 var autocompleteTextLength = (this._autocompleteElement.parentNode) ? this._autocompleteElement.textContent.length : 0;
lushnikov 2016/10/22 02:15:10 nit: extra ()
einbinder 2016/10/22 02:30:05 Done.
434 if (wordSuffixRange.toString().length !== autocompleteTextLength) 441 if (wordSuffixRange.toString().length !== autocompleteTextLength)
435 shouldExit = true; 442 shouldExit = true;
436 } 443 }
437 if (shouldExit) { 444 if (shouldExit) {
438 this.clearAutocomplete(); 445 this.clearAutocomplete();
439 return; 446 return;
440 } 447 }
441 448
442 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward"); 449 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward");
443 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, ++this._completio nRequestId, selection, wordPrefixRange, !!reverse, !!force)); 450 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, ++this._completio nRequestId, selection, wordPrefixRange, !!reverse, !!force));
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 527
521 var fullWordRange = this._createRange(); 528 var fullWordRange = this._createRange();
522 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset); 529 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset);
523 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et); 530 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et);
524 531
525 if (prefix + selectionRange.toString() !== fullWordRange.toString()) 532 if (prefix + selectionRange.toString() !== fullWordRange.toString())
526 return; 533 return;
527 534
528 selectedIndex = (this._disableDefaultSuggestionForEmptyInput && !this.te xt()) ? -1 : (selectedIndex || 0); 535 selectedIndex = (this._disableDefaultSuggestionForEmptyInput && !this.te xt()) ? -1 : (selectedIndex || 0);
529 536
530 this._userEnteredRange = fullWordRange;
531 this._userEnteredText = fullWordRange.toString();
532
533 if (this._suggestBox) 537 if (this._suggestBox)
534 this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selecti on, fullWordRange), annotatedCompletions, selectedIndex, !this.isCaretAtEndOfPro mpt(), this._userEnteredText); 538 this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selecti on, fullWordRange), annotatedCompletions, selectedIndex, !this.isCaretAtEndOfPro mpt(), this.userEnteredText());
535 539
536 if (selectedIndex === -1) 540 if (selectedIndex === -1)
537 return; 541 return;
538 542 var beforeRange = this._createRange();
lushnikov 2016/10/22 02:15:10 the calculation of the userEnteredRange should be
einbinder 2016/10/22 02:30:05 Done.
539 var wordPrefixLength = originalWordPrefixRange.toString().length; 543 beforeRange.setStart(this._element, 0);
540 544 beforeRange.setEnd(fullWordRange.startContainer, fullWordRange.startOffs et);
541 if (this.isCaretAtEndOfPrompt()) { 545 this._userEnteredRange = new WebInspector.TextRange(0, beforeRange.toStr ing().length, 0, beforeRange.toString().length + fullWordRange.toString().length );
542 var completionText = annotatedCompletions[selectedIndex].title; 546 this.applySuggestion(annotatedCompletions[selectedIndex].title, true);
543 var prefixText = this._userEnteredRange.toString();
544 var suffixText = completionText.substring(wordPrefixLength);
545 this._userEnteredRange.deleteContents();
546 this._element.normalize();
547 var finalSelectionRange = this._createRange();
548
549 var prefixTextNode = createTextNode(prefixText);
550 fullWordRange.insertNode(prefixTextNode);
551
552 if (!this._autocompleteElement)
553 this._autocompleteElement = createElementWithClass("span", "auto -complete-text");
554 this._autocompleteElement.textContent = suffixText;
555 this._currentHintText = completionText;
556
557 prefixTextNode.parentNode.insertBefore(this._autocompleteElement, pr efixTextNode.nextSibling);
558
559 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
560 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
561 selection.removeAllRanges();
562 selection.addRange(finalSelectionRange);
563 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied);
564 }
565 }, 547 },
566 548
567 /** 549 /**
568 * @override 550 * @override
569 * @param {string} completionText 551 * @param {string} completionText
570 * @param {boolean=} isIntermediateSuggestion 552 * @param {boolean=} isIntermediateSuggestion
571 */ 553 */
572 applySuggestion: function(completionText, isIntermediateSuggestion) 554 applySuggestion: function(completionText, isIntermediateSuggestion)
573 { 555 {
574 this._applySuggestion(completionText, isIntermediateSuggestion); 556 if (!this._userEnteredRange)
557 return;
558 this._setAutocompleteText(completionText);
559 if (isIntermediateSuggestion)
560 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied);
575 }, 561 },
576 562
577 /** 563 /**
578 * @param {string} completionText
579 * @param {boolean=} isIntermediateSuggestion
580 */
581 _applySuggestion: function(completionText, isIntermediateSuggestion)
582 {
583 if (!this._userEnteredRange) {
584 // We could have already cleared autocompletion range by the time th is is called. (crbug.com/587683)
585 return;
586 }
587
588 var wordPrefixLength = this._userEnteredText ? this._userEnteredText.len gth : 0;
589
590 this._userEnteredRange.deleteContents();
591 this._element.normalize();
592 var finalSelectionRange = this._createRange();
593 var completionTextNode = createTextNode(completionText);
594 this._userEnteredRange.insertNode(completionTextNode);
595 if (this._autocompleteElement) {
596 this._autocompleteElement.remove();
597 delete this._autocompleteElement;
598 }
599
600 if (isIntermediateSuggestion)
601 finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
602 else
603 finalSelectionRange.setStart(completionTextNode, completionText.leng th);
604
605 finalSelectionRange.setEnd(completionTextNode, completionText.length);
606
607 var selection = this._element.getComponentSelection();
608 selection.removeAllRanges();
609 selection.addRange(finalSelectionRange);
610 if (isIntermediateSuggestion)
611 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied, { itemText: completionText });
612 },
613
614 /**
615 * @override 564 * @override
616 */ 565 */
617 acceptSuggestion: function() 566 acceptSuggestion: function()
618 { 567 {
619 this._acceptSuggestionInternal(); 568 this._acceptSuggestionInternal();
620 }, 569 },
621 570
622 /** 571 /**
623 * @return {boolean} 572 * @return {boolean}
624 */ 573 */
625 _acceptSuggestionInternal: function() 574 _acceptSuggestionInternal: function()
626 { 575 {
627 if (!this._autocompleteElement || !this._autocompleteElement.parentNode) 576 if (!this._userEnteredRange)
628 return false; 577 return false;
629 578
630 var text = this._autocompleteElement.textContent; 579 this._autocompleteElement.remove();
631 var textNode = createTextNode(text); 580 var text = this.userEnteredText();
632 this._autocompleteElement.parentNode.replaceChild(textNode, this._autoco mpleteElement); 581 this._element.textContent = text.substring(0, this._userEnteredRange.sta rtColumn) + this._currentHintText + text.substring(this._userEnteredRange.endCol umn);
633 delete this._autocompleteElement; 582 this._select(this._userEnteredRange.startColumn + this._currentHintText. length, this._userEnteredRange.startColumn + this._currentHintText.length);
634
635 var finalSelectionRange = this._createRange();
636 finalSelectionRange.setStart(textNode, text.length);
637 finalSelectionRange.setEnd(textNode, text.length);
638
639 var selection = this._element.getComponentSelection();
640 selection.removeAllRanges();
641 selection.addRange(finalSelectionRange);
642 583
643 this.clearAutocomplete(); 584 this.clearAutocomplete();
644 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepte d); 585 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepte d);
645 586
646 return true; 587 return true;
647 }, 588 },
648 589
649 /** 590 /**
591 * @param {number} start
lushnikov 2016/10/22 02:15:10 startColumn
einbinder 2016/10/22 02:30:05 Done.
592 * @param {number} end
lushnikov 2016/10/22 02:15:10 endColumn
einbinder 2016/10/22 02:30:05 Done.
593 */
594 _select: function(start, end)
lushnikov 2016/10/22 02:15:10 _setDOMSelection:
einbinder 2016/10/22 02:30:05 Done.
595 {
596 this._element.normalize();
597 var node = this._element.childNodes[0];
598 if (node === this._autocompleteElement)
lushnikov 2016/10/22 02:15:10 !node
einbinder 2016/10/22 02:30:05 Done.
599 return;
600 var range = this._createRange();
601 range.setStart(node, start);
602 range.setEnd(node, end);
603 var selection = this._element.getComponentSelection();
604 selection.removeAllRanges();
605 selection.addRange(range);
606 },
607
608 /**
650 * @return {boolean} 609 * @return {boolean}
651 */ 610 */
652 isSuggestBoxVisible: function() 611 isSuggestBoxVisible: function()
653 { 612 {
654 return this._suggestBox && this._suggestBox.visible(); 613 return this._suggestBox && this._suggestBox.visible();
655 }, 614 },
656 615
657 /** 616 /**
658 * @return {boolean} 617 * @return {boolean}
659 */ 618 */
(...skipping 20 matching lines...) Expand all
680 var node = selectionRange.startContainer; 639 var node = selectionRange.startContainer;
681 if (!node.isSelfOrDescendant(this._element)) 640 if (!node.isSelfOrDescendant(this._element))
682 return false; 641 return false;
683 642
684 if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < nod e.nodeValue.length) 643 if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < nod e.nodeValue.length)
685 return false; 644 return false;
686 645
687 var foundNextText = false; 646 var foundNextText = false;
688 while (node) { 647 while (node) {
689 if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) { 648 if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
690 if (foundNextText && (!this._autocompleteElement || !this._autoc ompleteElement.isAncestor(node))) 649 if (foundNextText && !this._autocompleteElement.isAncestor(node) )
691 return false; 650 return false;
692 foundNextText = true; 651 foundNextText = true;
693 } 652 }
694 653
695 node = node.traverseNextNode(this._element); 654 node = node.traverseNextNode(this._element);
696 } 655 }
697 656
698 return true; 657 return true;
699 }, 658 },
700 659
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 }, 955 },
997 956
998 /** 957 /**
999 * @return {string|undefined} 958 * @return {string|undefined}
1000 */ 959 */
1001 _currentHistoryItem: function() 960 _currentHistoryItem: function()
1002 { 961 {
1003 return this._data[this._data.length - this._historyOffset]; 962 return this._data[this._data.length - this._historyOffset];
1004 } 963 }
1005 }; 964 };
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/http/tests/inspector-unit/text-prompt-hint-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698