Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 // If directory files changes too often, don't rescan directory more than once | 7 // If directory files changes too often, don't rescan directory more than once |
| 8 // per specified interval | 8 // per specified interval |
| 9 var SIMULTANEOUS_RESCAN_INTERVAL = 1000; | 9 var SIMULTANEOUS_RESCAN_INTERVAL = 1000; |
| 10 // Used for operations that require almost instant rescan. | 10 // Used for operations that require almost instant rescan. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 metadataCache, volumeManager) { | 25 metadataCache, volumeManager) { |
| 26 this.fileListSelection_ = singleSelection ? | 26 this.fileListSelection_ = singleSelection ? |
| 27 new cr.ui.ListSingleSelectionModel() : new cr.ui.ListSelectionModel(); | 27 new cr.ui.ListSingleSelectionModel() : new cr.ui.ListSelectionModel(); |
| 28 | 28 |
| 29 this.runningScan_ = null; | 29 this.runningScan_ = null; |
| 30 this.pendingScan_ = null; | 30 this.pendingScan_ = null; |
| 31 this.rescanTime_ = null; | 31 this.rescanTime_ = null; |
| 32 this.scanFailures_ = 0; | 32 this.scanFailures_ = 0; |
| 33 this.changeDirectorySequence_ = 0; | 33 this.changeDirectorySequence_ = 0; |
| 34 | 34 |
| 35 this.directoryChangeQueue_ = new AsyncUtil.Queue(); | |
| 36 | |
| 35 this.fileFilter_ = fileFilter; | 37 this.fileFilter_ = fileFilter; |
| 36 this.fileFilter_.addEventListener('changed', | 38 this.fileFilter_.addEventListener('changed', |
| 37 this.onFilterChanged_.bind(this)); | 39 this.onFilterChanged_.bind(this)); |
| 38 | 40 |
| 39 this.currentFileListContext_ = new FileListContext( | 41 this.currentFileListContext_ = new FileListContext( |
| 40 fileFilter, metadataCache); | 42 fileFilter, metadataCache); |
| 41 this.currentDirContents_ = | 43 this.currentDirContents_ = |
| 42 DirectoryContents.createForDirectory(this.currentFileListContext_, null); | 44 DirectoryContents.createForDirectory(this.currentFileListContext_, null); |
| 43 | 45 |
| 44 this.metadataCache_ = metadataCache; | 46 this.metadataCache_ = metadataCache; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 * a single refresh. | 273 * a single refresh. |
| 272 * @param {number} delay Delay in ms after which the rescan will be performed. | 274 * @param {number} delay Delay in ms after which the rescan will be performed. |
| 273 */ | 275 */ |
| 274 DirectoryModel.prototype.scheduleRescan = function(delay) { | 276 DirectoryModel.prototype.scheduleRescan = function(delay) { |
| 275 if (this.rescanTime_) { | 277 if (this.rescanTime_) { |
| 276 if (this.rescanTime_ <= Date.now() + delay) | 278 if (this.rescanTime_ <= Date.now() + delay) |
| 277 return; | 279 return; |
| 278 clearTimeout(this.rescanTimeoutId_); | 280 clearTimeout(this.rescanTimeoutId_); |
| 279 } | 281 } |
| 280 | 282 |
| 283 var sequence = this.changeDirectorySequence_; | |
| 284 | |
| 281 this.rescanTime_ = Date.now() + delay; | 285 this.rescanTime_ = Date.now() + delay; |
| 282 this.rescanTimeoutId_ = setTimeout(this.rescan.bind(this), delay); | 286 this.rescanTimeoutId_ = setTimeout(function() { |
| 287 this.rescanTimeoutId_ = null; | |
| 288 tracker.stop(); | |
|
hirono
2014/06/02 11:52:07
Remaining line.
yoshiki
2014/06/04 13:46:41
Done.
| |
| 289 if (sequence !== this.changeDirectorySequence_) | |
| 290 this.rescan(); | |
| 291 }.bind(this), delay); | |
| 283 }; | 292 }; |
| 284 | 293 |
| 285 /** | 294 /** |
| 286 * Cancel a rescan on timeout if it is scheduled. | 295 * Cancel a rescan on timeout if it is scheduled. |
| 287 * @private | 296 * @private |
| 288 */ | 297 */ |
| 289 DirectoryModel.prototype.clearRescanTimeout_ = function() { | 298 DirectoryModel.prototype.clearRescanTimeout_ = function() { |
| 290 this.rescanTime_ = null; | 299 this.rescanTime_ = null; |
| 291 if (this.rescanTimeoutId_) { | 300 if (this.rescanTimeoutId_) { |
| 292 clearTimeout(this.rescanTimeoutId_); | 301 clearTimeout(this.rescanTimeoutId_); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 305 DirectoryModel.prototype.rescan = function() { | 314 DirectoryModel.prototype.rescan = function() { |
| 306 this.clearRescanTimeout_(); | 315 this.clearRescanTimeout_(); |
| 307 if (this.runningScan_) { | 316 if (this.runningScan_) { |
| 308 this.pendingRescan_ = true; | 317 this.pendingRescan_ = true; |
| 309 return; | 318 return; |
| 310 } | 319 } |
| 311 | 320 |
| 312 var dirContents = this.currentDirContents_.clone(); | 321 var dirContents = this.currentDirContents_.clone(); |
| 313 dirContents.setFileList([]); | 322 dirContents.setFileList([]); |
| 314 | 323 |
| 324 var sequence = this.changeDirectorySequence_; | |
| 325 | |
| 315 var successCallback = (function() { | 326 var successCallback = (function() { |
| 316 this.replaceDirectoryContents_(dirContents); | 327 if (sequence !== this.changeDirectorySequence_) |
| 328 this.replaceDirectoryContents_(dirContents); | |
| 317 cr.dispatchSimpleEvent(this, 'rescan-completed'); | 329 cr.dispatchSimpleEvent(this, 'rescan-completed'); |
| 318 }).bind(this); | 330 }).bind(this); |
| 319 | 331 |
| 320 this.scan_(dirContents, | 332 this.scan_(dirContents, |
| 321 successCallback, function() {}, function() {}, function() {}); | 333 successCallback, function() {}, function() {}, function() {}); |
| 322 }; | 334 }; |
| 323 | 335 |
| 324 /** | 336 /** |
| 325 * Run scan on the current DirectoryContents. The active fileList is cleared and | 337 * Run scan on the current DirectoryContents. The active fileList is cleared and |
| 326 * the entries are added directly. | 338 * the entries are added directly. |
| 327 * | 339 * |
| 328 * This should be used when changing directory or initiating a new search. | 340 * This should be used when changing directory or initiating a new search. |
| 329 * | 341 * |
| 330 * @param {DirectoryContentes} newDirContents New DirectoryContents instance to | 342 * @param {DirectoryContentes} newDirContents New DirectoryContents instance to |
| 331 * replace currentDirContents_. | 343 * replace currentDirContents_. |
| 332 * @param {function()=} opt_callback Called on success. | 344 * @param {function(boolean)} callback Callback with result. True if the scan |
| 345 * is completed successfully, false if the scan is failed. | |
| 333 * @private | 346 * @private |
| 334 */ | 347 */ |
| 335 DirectoryModel.prototype.clearAndScan_ = function(newDirContents, | 348 DirectoryModel.prototype.clearAndScan_ = function(newDirContents, |
| 336 opt_callback) { | 349 callback) { |
| 337 if (this.currentDirContents_.isScanning()) | 350 if (this.currentDirContents_.isScanning()) |
| 338 this.currentDirContents_.cancelScan(); | 351 this.currentDirContents_.cancelScan(); |
| 339 this.currentDirContents_ = newDirContents; | 352 this.currentDirContents_ = newDirContents; |
| 340 this.clearRescanTimeout_(); | 353 this.clearRescanTimeout_(); |
| 341 | 354 |
| 342 if (this.pendingScan_) | 355 if (this.pendingScan_) |
| 343 this.pendingScan_ = false; | 356 this.pendingScan_ = false; |
| 344 | 357 |
| 345 if (this.runningScan_) { | 358 if (this.runningScan_) { |
| 346 if (this.runningScan_.isScanning()) | 359 if (this.runningScan_.isScanning()) |
| 347 this.runningScan_.cancelScan(); | 360 this.runningScan_.cancelScan(); |
| 348 this.runningScan_ = null; | 361 this.runningScan_ = null; |
| 349 } | 362 } |
| 350 | 363 |
| 364 var sequence = this.changeDirectorySequence_; | |
| 365 var cancelled = false; | |
| 366 | |
| 351 var onDone = function() { | 367 var onDone = function() { |
| 368 if (cancelled) | |
| 369 return; | |
| 370 | |
| 352 cr.dispatchSimpleEvent(this, 'scan-completed'); | 371 cr.dispatchSimpleEvent(this, 'scan-completed'); |
| 353 if (opt_callback) | 372 callback(true); |
| 354 opt_callback(); | |
| 355 }.bind(this); | 373 }.bind(this); |
| 356 | 374 |
| 357 var onFailed = function() { | 375 var onFailed = function() { |
| 376 if (cancelled) | |
| 377 return; | |
| 378 | |
| 358 cr.dispatchSimpleEvent(this, 'scan-failed'); | 379 cr.dispatchSimpleEvent(this, 'scan-failed'); |
| 380 callback(false); | |
| 359 }.bind(this); | 381 }.bind(this); |
| 360 | 382 |
| 361 var onUpdated = function() { | 383 var onUpdated = function() { |
| 384 if (cancelled) | |
| 385 return; | |
| 386 | |
| 387 if (this.changeDirectorySequence_ !== sequence) { | |
| 388 cancelled = true; | |
| 389 cr.dispatchSimpleEvent(this, 'scan-cancelled'); | |
| 390 callback(false); | |
| 391 return; | |
| 392 } | |
| 393 | |
| 362 cr.dispatchSimpleEvent(this, 'scan-updated'); | 394 cr.dispatchSimpleEvent(this, 'scan-updated'); |
| 363 }.bind(this); | 395 }.bind(this); |
| 364 | 396 |
| 365 var onCancelled = function() { | 397 var onCancelled = function() { |
| 398 if (cancelled) | |
| 399 return; | |
| 400 | |
| 401 cancelled = true; | |
| 366 cr.dispatchSimpleEvent(this, 'scan-cancelled'); | 402 cr.dispatchSimpleEvent(this, 'scan-cancelled'); |
| 403 callback(false); | |
| 367 }.bind(this); | 404 }.bind(this); |
| 368 | 405 |
| 369 // Clear the table, and start scanning. | 406 // Clear the table, and start scanning. |
| 370 cr.dispatchSimpleEvent(this, 'scan-started'); | 407 cr.dispatchSimpleEvent(this, 'scan-started'); |
| 371 var fileList = this.getFileList(); | 408 var fileList = this.getFileList(); |
| 372 fileList.splice(0, fileList.length); | 409 fileList.splice(0, fileList.length); |
| 373 this.scan_(this.currentDirContents_, | 410 this.scan_(this.currentDirContents_, |
| 374 onDone, onFailed, onUpdated, onCancelled); | 411 onDone, onFailed, onUpdated, onCancelled); |
| 375 }; | 412 }; |
| 376 | 413 |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 595 errorCallback, | 632 errorCallback, |
| 596 abortCallback) { | 633 abortCallback) { |
| 597 // Obtain and check the current directory. | 634 // Obtain and check the current directory. |
| 598 var entry = this.getCurrentDirEntry(); | 635 var entry = this.getCurrentDirEntry(); |
| 599 if (!entry || this.isSearching()) { | 636 if (!entry || this.isSearching()) { |
| 600 errorCallback(util.createDOMError( | 637 errorCallback(util.createDOMError( |
| 601 util.FileError.INVALID_MODIFICATION_ERR)); | 638 util.FileError.INVALID_MODIFICATION_ERR)); |
| 602 return; | 639 return; |
| 603 } | 640 } |
| 604 | 641 |
| 605 var tracker = this.createDirectoryChangeTracker(); | 642 var sequence = this.changeDirectorySequence_; |
| 606 tracker.start(); | |
| 607 | 643 |
| 608 new Promise(entry.getDirectory.bind( | 644 new Promise(entry.getDirectory.bind( |
| 609 entry, name, {create: true, exclusive: true})). | 645 entry, name, {create: true, exclusive: true})). |
| 610 | 646 |
| 611 then(function(newEntry) { | 647 then(function(newEntry) { |
| 612 // Refresh the cache. | 648 // Refresh the cache. |
| 613 this.metadataCache_.clear([newEntry], '*'); | 649 this.metadataCache_.clear([newEntry], '*'); |
| 614 return new Promise(function(onFulfilled, onRejected) { | 650 return new Promise(function(onFulfilled, onRejected) { |
| 615 this.metadataCache_.get([newEntry], | 651 this.metadataCache_.get([newEntry], |
| 616 'filesystem', | 652 'filesystem', |
| 617 onFulfilled.bind(null, newEntry)); | 653 onFulfilled.bind(null, newEntry)); |
| 618 }.bind(this)); | 654 }.bind(this)); |
| 619 }.bind(this)). | 655 }.bind(this)). |
| 620 | 656 |
| 621 then(function(newEntry) { | 657 then(function(newEntry) { |
| 622 // Do not change anything or call the callback if current | 658 // Do not change anything or call the callback if current |
| 623 // directory changed. | 659 // directory changed. |
| 624 tracker.stop(); | 660 if (this.changeDirectorySequence_ !== sequence) { |
| 625 if (tracker.hasChanged) { | |
| 626 abortCallback(); | 661 abortCallback(); |
| 627 return; | 662 return; |
| 628 } | 663 } |
| 629 | 664 |
| 630 // If target directory is already in the list, just select it. | 665 // If target directory is already in the list, just select it. |
| 631 var existing = this.getFileList().slice().filter( | 666 var existing = this.getFileList().slice().filter( |
| 632 function(e) { return e.name === name; }); | 667 function(e) { return e.name === name; }); |
| 633 if (existing.length) { | 668 if (existing.length) { |
| 634 this.selectEntry(newEntry); | 669 this.selectEntry(newEntry); |
| 635 successCallback(existing[0]); | 670 successCallback(existing[0]); |
| 636 } else { | 671 } else { |
| 637 this.fileListSelection_.beginChange(); | 672 this.fileListSelection_.beginChange(); |
| 638 this.getFileList().splice(0, 0, newEntry); | 673 this.getFileList().splice(0, 0, newEntry); |
| 639 this.selectEntry(newEntry); | 674 this.selectEntry(newEntry); |
| 640 this.fileListSelection_.endChange(); | 675 this.fileListSelection_.endChange(); |
| 641 successCallback(newEntry); | 676 successCallback(newEntry); |
| 642 } | 677 } |
| 643 }.bind(this), function(reason) { | 678 }.bind(this), function(reason) { |
| 644 tracker.stop(); | 679 tracker.stop(); |
|
hirono
2014/06/02 11:52:07
ditto.
yoshiki
2014/06/04 13:46:41
Done.
| |
| 645 errorCallback(reason); | 680 errorCallback(reason); |
| 646 }); | 681 }); |
| 647 }; | 682 }; |
| 648 | 683 |
| 649 /** | 684 /** |
| 650 * Changes the current directory to the directory represented by | 685 * Changes the current directory to the directory represented by |
| 651 * a DirectoryEntry or a fake entry. | 686 * a DirectoryEntry or a fake entry. |
| 652 * | 687 * |
| 653 * Dispatches the 'directory-changed' event when the directory is successfully | 688 * Dispatches the 'directory-changed' event when the directory is successfully |
| 654 * changed. | 689 * changed. |
| 655 * | 690 * |
| 656 * Note : if this is called from UI, please consider to use DirectoryModel. | 691 * Note : if this is called from UI, please consider to use DirectoryModel. |
| 657 * activateDirectoryEntry instead of this, which is higher-level function and | 692 * activateDirectoryEntry instead of this, which is higher-level function and |
| 658 * cares about the selection. | 693 * cares about the selection. |
| 659 * | 694 * |
| 660 * @param {DirectoryEntry|Object} dirEntry The entry of the new directory to | 695 * @param {DirectoryEntry|Object} dirEntry The entry of the new directory to |
| 661 * be opened. | 696 * be opened. |
| 662 * @param {function()=} opt_callback Executed if the directory loads | 697 * @param {function()=} opt_callback Executed if the directory loads |
| 663 * successfully. | 698 * successfully. |
| 664 */ | 699 */ |
| 665 DirectoryModel.prototype.changeDirectoryEntry = function( | 700 DirectoryModel.prototype.changeDirectoryEntry = function( |
| 666 dirEntry, opt_callback) { | 701 dirEntry, opt_callback) { |
| 667 // Increment the sequence value. | 702 // Increment the sequence value. |
| 668 this.changeDirectorySequence_++; | 703 this.changeDirectorySequence_++; |
| 669 this.clearSearch_(); | 704 this.clearSearch_(); |
| 670 | 705 |
| 671 var promise = new Promise( | 706 this.directoryChangeQueue_.run(function(sequence, queueTaskCallback) { |
| 672 function(onFulfilled, onRejected) { | 707 this.fileWatcher_.changeWatchedDirectory( |
| 673 this.fileWatcher_.changeWatchedDirectory(dirEntry, onFulfilled); | 708 dirEntry, |
| 674 }.bind(this)). | 709 function() { |
| 675 | 710 if (this.changeDirectorySequence_ !== sequence) { |
| 676 then(function(sequence) { | 711 callback(); |
| 677 return new Promise(function(onFulfilled, onRejected) { | |
| 678 if (this.changeDirectorySequence_ !== sequence) | |
| 679 return; | 712 return; |
| 713 } | |
| 680 | 714 |
| 681 var newDirectoryContents = this.createDirectoryContents_( | 715 var newDirectoryContents = this.createDirectoryContents_( |
| 682 this.currentFileListContext_, dirEntry, ''); | 716 this.currentFileListContext_, dirEntry, ''); |
| 683 if (!newDirectoryContents) | 717 if (!newDirectoryContents) { |
| 718 callback(); | |
| 684 return; | 719 return; |
| 720 } | |
| 685 | 721 |
| 686 var previousDirEntry = this.currentDirContents_.getDirectoryEntry(); | 722 var previousDirEntry = |
| 687 this.clearAndScan_(newDirectoryContents, opt_callback); | 723 this.currentDirContents_.getDirectoryEntry(); |
| 724 this.clearAndScan_( | |
| 725 newDirectoryContents, | |
| 726 function(result) { | |
| 727 // Calls the callback of the method when successful. | |
| 728 if (result && opt_callback) | |
| 729 opt_callback(); | |
| 688 | 730 |
| 689 // For tests that open the dialog to empty directories, everything is | 731 // Notify that the current task of this.directoryChangeQueue_ |
| 690 // loaded at this point. | 732 // is completed. |
| 733 setTimeout(queueTaskCallback); | |
| 734 }); | |
| 735 | |
| 736 // For tests that open the dialog to empty directories, everything | |
| 737 // is loaded at this point. | |
| 691 util.testSendMessage('directory-change-complete'); | 738 util.testSendMessage('directory-change-complete'); |
| 692 | 739 |
| 693 var event = new Event('directory-changed'); | 740 var event = new Event('directory-changed'); |
| 694 event.previousDirEntry = previousDirEntry; | 741 event.previousDirEntry = previousDirEntry; |
| 695 event.newDirEntry = dirEntry; | 742 event.newDirEntry = dirEntry; |
| 696 this.dispatchEvent(event); | 743 this.dispatchEvent(event); |
| 697 }.bind(this)); | 744 }.bind(this)); |
| 698 }.bind(this, this.changeDirectorySequence_)); | 745 }.bind(this, this.changeDirectorySequence_)); |
| 699 }; | 746 }; |
| 700 | 747 |
| 701 /** | 748 /** |
| 702 * Activates the given directry. | 749 * Activates the given directry. |
| 703 * This method: | 750 * This method: |
| 704 * - Changes the current directory, if the given directory is the current | 751 * - Changes the current directory, if the given directory is the current |
| 705 * directory. | 752 * directory. |
| 706 * - Clears the selection, if the given directory is the current directory. | 753 * - Clears the selection, if the given directory is the current directory. |
| 707 * | 754 * |
| 708 * @param {DirectoryEntry|Object} dirEntry The entry of the new directory to | 755 * @param {DirectoryEntry|Object} dirEntry The entry of the new directory to |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 896 DirectoryModel.prototype.search = function(query, | 943 DirectoryModel.prototype.search = function(query, |
| 897 onSearchRescan, | 944 onSearchRescan, |
| 898 onClearSearch) { | 945 onClearSearch) { |
| 899 this.clearSearch_(); | 946 this.clearSearch_(); |
| 900 var currentDirEntry = this.getCurrentDirEntry(); | 947 var currentDirEntry = this.getCurrentDirEntry(); |
| 901 if (!currentDirEntry) { | 948 if (!currentDirEntry) { |
| 902 // Not yet initialized. Do nothing. | 949 // Not yet initialized. Do nothing. |
| 903 return; | 950 return; |
| 904 } | 951 } |
| 905 | 952 |
| 906 if (!(query || '').trimLeft()) { | 953 this.changeDirectorySequence_++; |
| 907 if (this.isSearching()) { | 954 this.directoryChangeQueue_.run(function(sequence, callback) { |
| 908 var newDirContents = this.createDirectoryContents_( | 955 if (this.changeDirectorySequence_ !== sequence) { |
| 909 this.currentFileListContext_, | 956 callback(); |
| 910 currentDirEntry); | 957 return; |
| 911 this.clearAndScan_(newDirContents); | |
| 912 } | 958 } |
| 913 return; | |
| 914 } | |
| 915 | 959 |
| 916 var newDirContents = this.createDirectoryContents_( | 960 if (!(query || '').trimLeft()) { |
| 917 this.currentFileListContext_, currentDirEntry, query); | 961 if (this.isSearching()) { |
| 918 if (!newDirContents) | 962 var newDirContents = this.createDirectoryContents_( |
| 919 return; | 963 this.currentFileListContext_, |
| 964 currentDirEntry); | |
| 965 this.clearAndScan_(newDirContents, | |
| 966 sequence, | |
| 967 callback); | |
| 968 } else { | |
| 969 callback(); | |
| 970 } | |
| 971 return; | |
| 972 } | |
| 920 | 973 |
| 921 this.onSearchCompleted_ = onSearchRescan; | 974 var newDirContents = this.createDirectoryContents_( |
| 922 this.onClearSearch_ = onClearSearch; | 975 this.currentFileListContext_, currentDirEntry, query); |
| 923 this.addEventListener('scan-completed', this.onSearchCompleted_); | 976 if (!newDirContents) { |
| 924 this.clearAndScan_(newDirContents); | 977 callback(); |
| 978 return; | |
| 979 } | |
| 980 | |
| 981 this.onSearchCompleted_ = onSearchRescan; | |
| 982 this.onClearSearch_ = onClearSearch; | |
| 983 this.addEventListener('scan-completed', this.onSearchCompleted_); | |
| 984 this.clearAndScan_(newDirContents, | |
| 985 sequence, | |
| 986 callback); | |
| 987 }.bind(this, this.changeDirectorySequence_)); | |
| 925 }; | 988 }; |
| 926 | 989 |
| 927 /** | 990 /** |
| 928 * In case the search was active, remove listeners and send notifications on | 991 * In case the search was active, remove listeners and send notifications on |
| 929 * its canceling. | 992 * its canceling. |
| 930 * @private | 993 * @private |
| 931 */ | 994 */ |
| 932 DirectoryModel.prototype.clearSearch_ = function() { | 995 DirectoryModel.prototype.clearSearch_ = function() { |
| 933 if (!this.isSearching()) | 996 if (!this.isSearching()) |
| 934 return; | 997 return; |
| 935 | 998 |
| 936 if (this.onSearchCompleted_) { | 999 if (this.onSearchCompleted_) { |
| 937 this.removeEventListener('scan-completed', this.onSearchCompleted_); | 1000 this.removeEventListener('scan-completed', this.onSearchCompleted_); |
| 938 this.onSearchCompleted_ = null; | 1001 this.onSearchCompleted_ = null; |
| 939 } | 1002 } |
| 940 | 1003 |
| 941 if (this.onClearSearch_) { | 1004 if (this.onClearSearch_) { |
| 942 this.onClearSearch_(); | 1005 this.onClearSearch_(); |
| 943 this.onClearSearch_ = null; | 1006 this.onClearSearch_ = null; |
| 944 } | 1007 } |
| 945 }; | 1008 }; |
| OLD | NEW |