Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** @typedef {{id: number, rawQuery: ?string, regExp: ?RegExp}} */ | 5 /** @typedef {{id: number, rawQuery: ?string, regExp: ?RegExp}} */ |
| 6 var SearchContext; | 6 var SearchContext; |
| 7 | 7 |
| 8 /** @typedef {{onSearchStatusChanged: function(boolean)}} */ | |
| 9 var SearchObserver; | |
| 10 | |
| 8 cr.define('settings', function() { | 11 cr.define('settings', function() { |
| 9 /** @const {string} */ | 12 /** @const {string} */ |
| 10 var WRAPPER_CSS_CLASS = 'search-highlight-wrapper'; | 13 var WRAPPER_CSS_CLASS = 'search-highlight-wrapper'; |
| 11 | 14 |
| 12 /** @const {string} */ | 15 /** @const {string} */ |
| 13 var HIT_CSS_CLASS = 'search-highlight-hit'; | 16 var HIT_CSS_CLASS = 'search-highlight-hit'; |
| 14 | 17 |
| 15 /** | 18 /** |
| 16 * List of elements types that should not be searched at all. | 19 * List of elements types that should not be searched at all. |
| 17 * The only DOM-MODULE node is in <body> which is not searched, therefore | 20 * The only DOM-MODULE node is in <body> which is not searched, therefore |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 351 | 354 |
| 352 /** @private */ | 355 /** @private */ |
| 353 consumePending_: function() { | 356 consumePending_: function() { |
| 354 if (this.running_) | 357 if (this.running_) |
| 355 return; | 358 return; |
| 356 | 359 |
| 357 while (1) { | 360 while (1) { |
| 358 var task = this.popNextTask_(); | 361 var task = this.popNextTask_(); |
| 359 if (!task) { | 362 if (!task) { |
| 360 this.running_ = false; | 363 this.running_ = false; |
| 364 SearchManager.getInstance().observer_.onSearchStatusChanged(false); | |
|
Dan Beam
2016/07/15 19:23:01
do you need to null-check here? (note: I know I s
dpapad
2016/07/15 19:41:04
Done.
| |
| 361 return; | 365 return; |
| 362 } | 366 } |
| 363 | 367 |
| 368 this.running_ = true; | |
| 364 window.requestIdleCallback(function() { | 369 window.requestIdleCallback(function() { |
| 365 function startNextTask() { | 370 function startNextTask() { |
| 366 this.running_ = false; | 371 this.running_ = false; |
| 367 this.consumePending_(); | 372 this.consumePending_(); |
| 368 } | 373 } |
| 369 if (task.context.id == | 374 if (task.context.id == |
| 370 SearchManager.getInstance().activeContext_.id) { | 375 SearchManager.getInstance().activeContext_.id) { |
| 371 task.exec().then(startNextTask.bind(this)); | 376 task.exec().then(startNextTask.bind(this)); |
| 372 } else { | 377 } else { |
| 373 // Dropping this task without ever executing it, since a new search | 378 // Dropping this task without ever executing it, since a new search |
| 374 // has been issued since this task was queued. | 379 // has been issued since this task was queued. |
| 375 startNextTask.call(this); | 380 startNextTask.call(this); |
| 376 } | 381 } |
| 377 }.bind(this)); | 382 }.bind(this)); |
| 378 return; | 383 return; |
| 379 } | 384 } |
| 380 }, | 385 }, |
| 381 }; | 386 }; |
| 382 | 387 |
| 383 /** | 388 /** |
| 384 * @constructor | 389 * @constructor |
| 385 */ | 390 */ |
| 386 var SearchManager = function() { | 391 var SearchManager = function() { |
| 387 /** @private {!TaskQueue} */ | 392 /** @private {!TaskQueue} */ |
| 388 this.queue_ = new TaskQueue(); | 393 this.queue_ = new TaskQueue(); |
| 389 | 394 |
| 390 /** @private {!SearchContext} */ | 395 /** @private {!SearchContext} */ |
| 391 this.activeContext_ = {id: 0, rawQuery: null, regExp: null}; | 396 this.activeContext_ = {id: 0, rawQuery: null, regExp: null}; |
| 397 | |
| 398 /** @private {?SearchObserver} */ | |
| 399 this.observer_ = null; | |
| 392 }; | 400 }; |
| 393 cr.addSingletonGetter(SearchManager); | 401 cr.addSingletonGetter(SearchManager); |
| 394 | 402 |
| 395 /** @private @const {!RegExp} */ | 403 /** @private @const {!RegExp} */ |
| 396 SearchManager.SANITIZE_REGEX_ = /[-[\]{}()*+?.,\\^$|#\s]/g; | 404 SearchManager.SANITIZE_REGEX_ = /[-[\]{}()*+?.,\\^$|#\s]/g; |
| 397 | 405 |
| 398 SearchManager.prototype = { | 406 SearchManager.prototype = { |
| 407 /** @param {!SearchObserver} observer */ | |
| 408 setObserver: function(observer) { | |
| 409 this.observer_ = observer; | |
|
Dan Beam
2016/07/15 19:23:01
i think if there's only 1 of these, maybe just mak
dpapad
2016/07/15 19:41:04
Per discussion, I changed this to be a simple call
| |
| 410 }, | |
| 411 | |
| 399 /** | 412 /** |
| 400 * @param {string} text The text to search for. | 413 * @param {string} text The text to search for. |
| 401 * @param {!Node} page | 414 * @param {!Node} page |
| 402 */ | 415 */ |
| 403 search: function(text, page) { | 416 search: function(text, page) { |
| 404 if (this.activeContext_.rawQuery != text) { | 417 if (this.activeContext_.rawQuery != text) { |
| 405 var newId = this.activeContext_.id + 1; | 418 var newId = this.activeContext_.id + 1; |
| 406 | 419 |
| 407 var regExp = null; | 420 var regExp = null; |
| 408 // Generate search text by escaping any characters that would be | 421 // Generate search text by escaping any characters that would be |
| 409 // problematic for regular expressions. | 422 // problematic for regular expressions. |
| 410 var searchText = text.trim().replace( | 423 var searchText = text.trim().replace( |
| 411 SearchManager.SANITIZE_REGEX_, '\\$&'); | 424 SearchManager.SANITIZE_REGEX_, '\\$&'); |
| 412 if (searchText.length > 0) | 425 if (searchText.length > 0) |
| 413 regExp = new RegExp('(' + searchText + ')', 'i'); | 426 regExp = new RegExp('(' + searchText + ')', 'i'); |
| 414 | 427 |
| 415 this.activeContext_ = {id: newId, rawQuery: text, regExp: regExp}; | 428 this.activeContext_ = {id: newId, rawQuery: text, regExp: regExp}; |
| 416 | 429 |
| 417 // Drop all previously scheduled tasks, since a new search was just | 430 // Drop all previously scheduled tasks, since a new search was just |
| 418 // issued. | 431 // issued. |
| 419 this.queue_.reset(); | 432 this.queue_.reset(); |
| 433 this.observer_.onSearchStatusChanged(true); | |
| 420 } | 434 } |
| 421 | 435 |
| 422 this.queue_.addTopLevelSearchTask( | 436 this.queue_.addTopLevelSearchTask( |
| 423 new TopLevelSearchTask(this.activeContext_, page)); | 437 new TopLevelSearchTask(this.activeContext_, page)); |
| 424 }, | 438 }, |
| 425 }; | 439 }; |
| 426 | 440 |
| 427 /** | 441 /** @return {!SearchManager} */ |
| 428 * @param {string} text | 442 function getSearchManager() { |
|
Dan Beam
2016/07/15 19:23:01
maybe just remove this and make callers do:
set
dpapad
2016/07/15 19:41:04
Acknowledged. I prefer getSearchManager() over Sea
| |
| 429 * @param {!Node} page | 443 return SearchManager.getInstance(); |
| 430 */ | |
| 431 function search(text, page) { | |
| 432 SearchManager.getInstance().search(text, page); | |
| 433 } | 444 } |
| 434 | 445 |
| 435 return { | 446 return { |
| 436 search: search, | 447 getSearchManager: getSearchManager, |
|
Dan Beam
2016/07/15 19:23:01
SearchManager: SearchManager,
dpapad
2016/07/15 19:41:04
Same rationale as before. Exposing SearchManager c
| |
| 437 }; | 448 }; |
| 438 }); | 449 }); |
| OLD | NEW |