15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)'use strict';
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Scanner of the entries.
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @constructor
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function ContentScanner() {
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.cancelled_ = false;
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Starts to scan the entries. For example, starts to read the entries in a
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * directory, or starts to search with some query on a file system.
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Derived classes must override this method.
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {function(Array.<Entry>)} entriesCallback Called when some chunk of
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     entries are read. This can be called a couple of times until the
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     completion.
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {function()} successCallback Called when the scan is completed
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     successfully.
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {function(FileError)} errorCallback Called an error occurs.
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ContentScanner.prototype.scan = function(
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    entriesCallback, successCallback, errorCallback) {
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Request cancelling of the running scan. When the cancelling is done,
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * an error will be reported from errorCallback passed to scan().
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ContentScanner.prototype.cancel = function() {
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.cancelled_ = true;
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Scanner of the entries in a directory.
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DirectoryEntry} entry The directory to be read.
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @constructor
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @extends {ContentScanner}
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function DirectoryContentScanner(entry) {
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ContentScanner.call(this);
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.entry_ = entry;
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Extends ContentScanner.
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectoryContentScanner.prototype.__proto__ = ContentScanner.prototype;
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Starts to read the entries in the directory.
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @override
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectoryContentScanner.prototype.scan = function(
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    entriesCallback, successCallback, errorCallback) {
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!this.entry_ || util.isFakeEntry(this.entry_)) {
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // If entry is not specified or a fake, we cannot read it.
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errorCallback(util.createDOMError(
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        util.FileError.INVALID_MODIFICATION_ERR));
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  metrics.startInterval('DirectoryScan');
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var reader = this.entry_.createReader();
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var readEntries = function() {
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    reader.readEntries(
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        function(entries) {
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (this.cancelled_) {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            errorCallback(util.createDOMError(util.FileError.ABORT_ERR));
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            return;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          }
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (entries.length === 0) {
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            // All entries are read.
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            metrics.recordInterval('DirectoryScan');
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            successCallback();
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            return;
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          }
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          entriesCallback(entries);
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          readEntries();
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }.bind(this),
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        errorCallback);
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }.bind(this);
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  readEntries();
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Scanner of the entries for the search results on Drive File System.
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {string} query The query string.
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @constructor
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @extends {ContentScanner}
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function DriveSearchContentScanner(query) {
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ContentScanner.call(this);
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.query_ = query;
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Extends ContentScanner.
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DriveSearchContentScanner.prototype.__proto__ = ContentScanner.prototype;
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Delay in milliseconds to be used for drive search scan, in order to reduce
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * the number of server requests while user is typing the query.
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @type {number}
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @private
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @const
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DriveSearchContentScanner.SCAN_DELAY_ = 200;
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Maximum number of results which is shown on the search.
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @type {number}
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @private
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @const
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DriveSearchContentScanner.MAX_RESULTS_ = 100;
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Starts to search on Drive File System.
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @override
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DriveSearchContentScanner.prototype.scan = function(
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    entriesCallback, successCallback, errorCallback) {
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var numReadEntries = 0;
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var readEntries = function(nextFeed) {
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    chrome.fileManagerPrivate.searchDrive(
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        {query: this.query_, nextFeed: nextFeed},
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        function(entries, nextFeed) {
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (this.cancelled_) {
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            errorCallback(util.createDOMError(util.FileError.ABORT_ERR));
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            return;
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          }
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          // TODO(tbarzic): Improve error handling.
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (!entries) {
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            console.error('Drive search encountered an error.');
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            errorCallback(util.createDOMError(
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                util.FileError.INVALID_MODIFICATION_ERR));
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            return;
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          }
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          var numRemainingEntries =
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              DriveSearchContentScanner.MAX_RESULTS_ - numReadEntries;
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (entries.length >= numRemainingEntries) {
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            // The limit is hit, so quit the scan here.
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            entries = entries.slice(0, numRemainingEntries);
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            nextFeed = '';
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          }
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          numReadEntries += entries.length;
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (entries.length > 0)
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            entriesCallback(entries);
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (nextFeed === '')
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            successCallback();
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          else
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            readEntries(nextFeed);
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }.bind(this));
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }.bind(this);
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Let's give another search a chance to cancel us before we begin.
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  setTimeout(
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      function() {
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // Check cancelled state before read the entries.
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        if (this.cancelled_) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          errorCallback(util.createDOMError(util.FileError.ABORT_ERR));
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          return;
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        readEntries('');
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }.bind(this),
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      DriveSearchContentScanner.SCAN_DELAY_);
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Scanner of the entries of the file name search on the directory tree, whose
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * root is entry.
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DirectoryEntry} entry The root of the search target directory tree.
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {string} query The query of the search.
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @constructor
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @extends {ContentScanner}
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function LocalSearchContentScanner(entry, query) {
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ContentScanner.call(this);
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.entry_ = entry;
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.query_ = query.toLowerCase();
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Extends ContentScanner.
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)LocalSearchContentScanner.prototype.__proto__ = ContentScanner.prototype;
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Starts the file name search.
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @override
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)LocalSearchContentScanner.prototype.scan = function(
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    entriesCallback, successCallback, errorCallback) {
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var numRunningTasks = 0;
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var error = null;
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var maybeRunCallback = function() {
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (numRunningTasks === 0) {
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (this.cancelled_)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        errorCallback(util.createDOMError(util.FileError.ABORT_ERR));
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      else if (error)
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        errorCallback(error);
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      else
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        successCallback();
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }.bind(this);
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var processEntry = function(entry) {
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    numRunningTasks++;
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    var onError = function(fileError) {
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (!error)
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        error = fileError;
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      numRunningTasks--;
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      maybeRunCallback();
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    };
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    var onSuccess = function(entries) {
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (this.cancelled_ || error || entries.length === 0) {
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        numRunningTasks--;
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        maybeRunCallback();
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return;
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Filters by the query, and if found, run entriesCallback.
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      var foundEntries = entries.filter(function(entry) {
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return entry.name.toLowerCase().indexOf(this.query_) >= 0;
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }.bind(this));
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (foundEntries.length > 0)
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        entriesCallback(foundEntries);
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Start to process sub directories.
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      for (var i = 0; i < entries.length; i++) {
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        if (entries[i].isDirectory)
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          processEntry(entries[i]);
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Read remaining entries.
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      reader.readEntries(onSuccess, onError);
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }.bind(this);
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    var reader = entry.createReader();
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    reader.readEntries(onSuccess, onError);
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }.bind(this);
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  processEntry(this.entry_);
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Scanner of the entries for the metadata search on Drive File System.
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DriveMetadataSearchContentScanner.SearchType} searchType The option
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     of the search.
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @constructor
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @extends {ContentScanner}
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function DriveMetadataSearchContentScanner(searchType) {
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ContentScanner.call(this);
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.searchType_ = searchType;
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Extends ContentScanner.
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DriveMetadataSearchContentScanner.prototype.__proto__ =
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ContentScanner.prototype;
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * The search types on the Drive File System.
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @enum {string}
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DriveMetadataSearchContentScanner.SearchType = Object.freeze({
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SEARCH_ALL: 'ALL',
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SEARCH_SHARED_WITH_ME: 'SHARED_WITH_ME',
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SEARCH_RECENT_FILES: 'EXCLUDE_DIRECTORIES',
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SEARCH_OFFLINE: 'OFFLINE'
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)});
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Starts to metadata-search on Drive File System.
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @override
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DriveMetadataSearchContentScanner.prototype.scan = function(
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    entriesCallback, successCallback, errorCallback) {
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  chrome.fileManagerPrivate.searchDriveMetadata(
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      {query: '', types: this.searchType_, maxResults: 500},
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      function(results) {
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        if (this.cancelled_) {
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          errorCallback(util.createDOMError(util.FileError.ABORT_ERR));
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          return;
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        if (!results) {
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          console.error('Drive search encountered an error.');
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          errorCallback(util.createDOMError(
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              util.FileError.INVALID_MODIFICATION_ERR));
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          return;
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        var entries = results.map(function(result) { return result.entry; });
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        if (entries.length > 0)
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          entriesCallback(entries);
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        successCallback();
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }.bind(this));
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * This class manages filters and determines a file should be shown or not.
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * When filters are changed, a 'changed' event is fired.
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {MetadataCache} metadataCache Metadata cache service.
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {boolean} showHidden If files starting with '.' or ending with
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *     '.crdownlaod' are shown.
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @extends {cr.EventTarget}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function FileFilter(metadataCache, showHidden) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {MetadataCache}
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @private
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  this.metadataCache_ = metadataCache;
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   * @type {Object.<string, Function>}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @private
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.filters_ = {};
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.setFilterHidden(!showHidden);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not show entries marked as 'deleted'.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.addFilter('deleted', function(entry) {
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var internal = this.metadataCache_.getCached(entry, 'internal');
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !(internal && internal.deleted);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }.bind(this));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/*
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * FileFilter extends cr.EventTarget.
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileFilter.prototype = {__proto__: cr.EventTarget.prototype};
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Filter identifier.
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {function(Entry)} callback A filter — a function receiving an Entry,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     and returning bool.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileFilter.prototype.addFilter = function(name, callback) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.filters_[name] = callback;
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cr.dispatchSimpleEvent(this, 'changed');
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Filter identifier.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileFilter.prototype.removeFilter = function(name) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this.filters_[name];
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cr.dispatchSimpleEvent(this, 'changed');
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {boolean} value If do not show hidden files.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileFilter.prototype.setFilterHidden = function(value) {
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  var regexpCrdownloadExtension = /\.crdownload$/i;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.addFilter(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'hidden',
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        function(entry) {
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          return entry.name.substr(0, 1) !== '.' &&
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 !regexpCrdownloadExtension.test(entry.name);
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.removeFilter('hidden');
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} If the files with names starting with "." are not shown.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileFilter.prototype.isFilterHiddenOn = function() {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 'hidden' in this.filters_;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Entry} entry File entry.
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {boolean} True if the file should be shown, false otherwise.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileFilter.prototype.filter = function(entry) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var name in this.filters_) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!this.filters_[name](entry))
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * File list.
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {MetadataCache} metadataCache Metadata cache.
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @constructor
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @extends {cr.ui.ArrayDataModel}
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)function FileListModel(metadataCache) {
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  cr.ui.ArrayDataModel.call(this, []);
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  /**
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   * Metadata cache.
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   * @type {MetadataCache}
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   * @private
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   */
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.metadataCache_ = metadataCache;
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Initialize compare functions.
4256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  this.setCompareFunction('name', util.compareName);
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.setCompareFunction('modificationTime', this.compareMtime_.bind(this));
4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.setCompareFunction('size', this.compareSize_.bind(this));
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.setCompareFunction('type', this.compareType_.bind(this));
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FileListModel.prototype = {
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  __proto__: cr.ui.ArrayDataModel.prototype
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Compare by mtime first, then by name.
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Entry} a First entry.
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Entry} b Second entry.
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {number} Compare result.
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FileListModel.prototype.compareMtime_ = function(a, b) {
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var aCachedFilesystem = this.metadataCache_.getCached(a, 'filesystem');
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var aTime = aCachedFilesystem ? aCachedFilesystem.modificationTime : 0;
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var bCachedFilesystem = this.metadataCache_.getCached(b, 'filesystem');
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var bTime = bCachedFilesystem ? bCachedFilesystem.modificationTime : 0;
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (aTime > bTime)
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 1;
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (aTime < bTime)
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return -1;
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return util.compareName(a, b);
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Compare by size first, then by name.
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Entry} a First entry.
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Entry} b Second entry.
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {number} Compare result.
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FileListModel.prototype.compareSize_ = function(a, b) {
4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var aCachedFilesystem = this.metadataCache_.getCached(a, 'filesystem');
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var aSize = aCachedFilesystem ? aCachedFilesystem.size : 0;
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var bCachedFilesystem = this.metadataCache_.getCached(b, 'filesystem');
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var bSize = bCachedFilesystem ? bCachedFilesystem.size : 0;
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return aSize !== bSize ? aSize - bSize : util.compareName(a, b);
4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Compare by type first, then by subtype and then by name.
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Entry} a First entry.
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Entry} b Second entry.
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {number} Compare result.
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FileListModel.prototype.compareType_ = function(a, b) {
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Directories precede files.
4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (a.isDirectory !== b.isDirectory)
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return Number(b.isDirectory) - Number(a.isDirectory);
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var aType = FileType.typeToString(FileType.getType(a));
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var bType = FileType.typeToString(FileType.getType(b));
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  var result = util.collator.compare(aType, bType);
4916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return result !== 0 ? result : util.compareName(a, b);
4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/**
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * A context of DirectoryContents.
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * TODO(yoshiki): remove this. crbug.com/224869.
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {FileFilter} fileFilter The file-filter context.
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {MetadataCache} metadataCache Metadata cache service.
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @constructor
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function FileListContext(fileFilter, metadataCache) {
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   * @type {FileListModel}
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.fileList = new FileListModel(metadataCache);
5074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @type {MetadataCache}
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  this.metadataCache = metadataCache;
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @type {FileFilter}
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  this.fileFilter = fileFilter;
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This class is responsible for scanning directory (or search results),
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and filling the fileList. Different descendants handle various types of
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * directory contents shown: basic directory, drive search results, local search
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * results.
5244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * TODO(hidehiko): Remove EventTarget from this.
5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {FileListContext} context The file list context.
5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {boolean} isSearch True for search directory contents, otherwise
5284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     false.
5294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DirectoryEntry} directoryEntry The entry of the current directory.
5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {function():ContentScanner} scannerFactory The factory to create
5314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     ContentScanner instance.
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @extends {cr.EventTarget}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function DirectoryContents(context,
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           isSearch,
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           directoryEntry,
5384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           scannerFactory) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.context_ = context;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.fileList_ = context.fileList;
5414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.isSearch_ = isSearch;
5434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.directoryEntry_ = directoryEntry;
5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.scannerFactory_ = scannerFactory;
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.scanner_ = null;
547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.processNewEntriesQueue_ = new AsyncUtil.Queue();
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.scanCancelled_ = false;
549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  this.lastSpaceInMetadataCache_ = 0;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * DirectoryContents extends cr.EventTarget.
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.__proto__ = cr.EventTarget.prototype;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create the copy of the object, but without scan started.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {DirectoryContents} Object copy.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.clone = function() {
5634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return new DirectoryContents(
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      this.context_,
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      this.isSearch_,
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      this.directoryEntry_,
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      this.scannerFactory_);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Disposes the reserved metadata cache.
572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */
573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DirectoryContents.prototype.dispose = function() {
574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  this.context_.metadataCache.resizeBy(-this.lastSpaceInMetadataCache_);
5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Though the lastSpaceInMetadataCache_ is not supposed to be referred after
5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // dispose(), keep it synced with requested cache size just in case.
5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  this.lastSpaceInMetadataCache_ = 0;
578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/**
581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Make a space for current directory size in the metadata cache.
582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *
583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} size The cache size to be set.
584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private
585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */
586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DirectoryContents.prototype.makeSpaceInMetadataCache_ = function(size) {
587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  this.context_.metadataCache.resizeBy(size - this.lastSpaceInMetadataCache_);
588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  this.lastSpaceInMetadataCache_ = size;
589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/**
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use a given fileList instead of the fileList from the context.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array|cr.ui.ArrayDataModel} fileList The new file list.
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.setFileList = function(fileList) {
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (fileList instanceof cr.ui.ArrayDataModel)
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    this.fileList_ = fileList;
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    this.fileList_ = new cr.ui.ArrayDataModel(fileList);
600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  this.makeSpaceInMetadataCache_(this.fileList_.length);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use the filelist from the context and replace its contents with the entries
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * from the current fileList.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.replaceContextFileList = function() {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this.context_.fileList !== this.fileList_) {
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var spliceArgs = this.fileList_.slice();
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var fileList = this.context_.fileList;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    spliceArgs.unshift(0, fileList.length);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fileList.splice.apply(fileList, spliceArgs);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.fileList_ = fileList;
614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    this.makeSpaceInMetadataCache_(this.fileList_.length);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} If the scan is active.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.isScanning = function() {
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.scanner_ || this.processNewEntriesQueue_.isRunning();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {boolean} True if search results (drive or local).
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.isSearch = function() {
6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return this.isSearch_;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {DirectoryEntry} A DirectoryEntry for current directory. In case of
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     search -- the top directory from which search is run.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.getDirectoryEntry = function() {
6374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return this.directoryEntry_;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Start directory scan/search operation. Either 'scan-completed' or
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'scan-failed' event will be fired upon completion.
6436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) *
6446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * @param {boolean} refresh True to refresh metadata, or false to use cached
6456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) *     one.
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)DirectoryContents.prototype.scan = function(refresh) {
648effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  /**
649effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   * Invoked when the scanning is completed successfully.
650effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   * @this {DirectoryContents}
651effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   */
652effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  function completionCallback() {
653effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    this.onScanFinished_();
654effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    this.onScanCompleted_();
655effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
657effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  /**
658effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   * Invoked when the scanning is finished but is not completed due to error.
659effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   * @this {DirectoryContents}
660effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   */
661effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  function errorCallback() {
662effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    this.onScanFinished_();
663effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    this.onScanError_();
664effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
665effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
6664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TODO(hidehiko,mtomasz): this scan method must be called at most once.
6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Remove such a limitation.
6684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.scanner_ = this.scannerFactory_();
6696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  this.scanner_.scan(this.onNewEntries_.bind(this, refresh),
670effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                     completionCallback.bind(this),
671effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                     errorCallback.bind(this));
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
67503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * Adds/removes/updates items of file list.
67603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * @param {Array.<Entry>} updatedEntries Entries of updated/added files.
67703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * @param {Array.<string>} removedUrls URLs of removed files.
67803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) */
67903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)DirectoryContents.prototype.update = function(updatedEntries, removedUrls) {
68003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  var removedMap = {};
68103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (var i = 0; i < removedUrls.length; i++) {
68203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    removedMap[removedUrls[i]] = true;
68303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
68403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
68503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  var updatedMap = {};
68603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (var i = 0; i < updatedEntries.length; i++) {
68703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    updatedMap[updatedEntries[i].toURL()] = updatedEntries[i];
68803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
68903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
69003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  var updatedList = [];
69103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (var i = 0; i < this.fileList_.length; i++) {
69203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var url = this.fileList_.item(i).toURL();
69303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
69403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (url in removedMap) {
69503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.fileList_.splice(i, 1);
69603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      i--;
69703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      continue;
69803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
69903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
70003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (url in updatedMap) {
70103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      updatedList.push(updatedMap[url]);
70203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      delete updatedMap[url];
70303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
70403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
70503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
70603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  var addedList = [];
70703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (var url in updatedMap) {
70803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    addedList.push(updatedMap[url]);
70903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
71003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
71103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (removedUrls.length > 0)
71203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.fileList_.metadataCache_.clearByUrl(removedUrls, '*');
71303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
71403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  this.prefetchMetadata(updatedList, true, function() {
71503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.onNewEntries_(true, addedList);
71603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.onScanFinished_();
71703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.onScanCompleted_();
71803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }.bind(this));
71903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
72003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
72103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/**
7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Cancels the running scan.
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryContents.prototype.cancelScan = function() {
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (this.scanCancelled_)
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this.scanCancelled_ = true;
7284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (this.scanner_)
7294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    this.scanner_.cancel();
7304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
731effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  this.onScanFinished_();
732effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.processNewEntriesQueue_.cancel();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cr.dispatchSimpleEvent(this, 'scan-cancelled');
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
738effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Called when the scanning by scanner_ is done, even when the scanning is
739effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * succeeded or failed. This is called before completion (or error) callback.
740effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *
7414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @private
7424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
743effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochDirectoryContents.prototype.onScanFinished_ = function() {
7444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  this.scanner_ = null;
745effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.processNewEntriesQueue_.run(function(callback) {
747effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // TODO(yoshiki): Here we should fire the update event of changed
748effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // items. Currently we have a method this.fileList_.updateIndex() to
749effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // fire an event, but this method takes only 1 argument and invokes sort
750effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // one by one. It is obviously time wasting. Instead, we call sort
751effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // directory.
752effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // In future, we should implement a good method like updateIndexes and
753effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // use it here.
754effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    var status = this.fileList_.sortStatus;
755effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (status)
756effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      this.fileList_.sort(status.field, status.direction);
757effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
758effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    callback();
759effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }.bind(this));
760effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch};
761effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
762effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/**
763effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Called when the scanning by scanner_ is succeeded.
764effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @private
765effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */
766effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochDirectoryContents.prototype.onScanCompleted_ = function() {
7674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (this.scanCancelled_)
7684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
7694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.processNewEntriesQueue_.run(function(callback) {
7714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Call callback first, so isScanning() returns false in the event handlers.
7724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    callback();
773effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
7744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    cr.dispatchSimpleEvent(this, 'scan-completed');
7754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }.bind(this));
7764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called in case scan has failed. Should send the event.
7804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @private
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectoryContents.prototype.onScanError_ = function() {
7834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (this.scanCancelled_)
7844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
7854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.processNewEntriesQueue_.run(function(callback) {
7874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Call callback first, so isScanning() returns false in the event handlers.
7884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    callback();
7894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    cr.dispatchSimpleEvent(this, 'scan-failed');
7904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }.bind(this));
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
7944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Called when some chunk of entries are read by scanner.
7956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) *
7966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) * @param {boolean} refresh True to refresh metadata, or false to use cached
7976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) *     one.
7984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {Array.<Entry>} entries The list of the scanned entries.
7994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @private
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)DirectoryContents.prototype.onNewEntries_ = function(refresh, entries) {
8024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (this.scanCancelled_)
8034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
8044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var entriesFiltered = [].filter.call(
8064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      entries, this.context_.fileFilter.filter.bind(this.context_.fileFilter));
8074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
808010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Caching URL to reduce a number of calls of toURL in sort.
809010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // This is a temporary solution. We need to fix a root cause of slow toURL.
810010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // See crbug.com/370908 for detail.
811010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  entriesFiltered.forEach(function(entry) { entry.cachedUrl = entry.toURL(); });
812010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
81346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (entriesFiltered.length === 0)
81446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
81546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
816f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Enlarge the cache size into the new filelist size.
817f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  var newListSize = this.fileList_.length + entriesFiltered.length;
818f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  this.makeSpaceInMetadataCache_(newListSize);
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
820cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.processNewEntriesQueue_.run(function(callbackOuter) {
821f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    var finish = function() {
822116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (!this.scanCancelled_) {
823116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // Update the filelist without waiting the metadata.
824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        this.fileList_.push.apply(this.fileList_, entriesFiltered);
825116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        cr.dispatchSimpleEvent(this, 'scan-updated');
826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
827f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      callbackOuter();
828f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }.bind(this);
829cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Because the prefetchMetadata can be slow, throttling by splitting entries
830cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // into smaller chunks to reduce UI latency.
831cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(hidehiko,mtomasz): This should be handled in MetadataCache.
832cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var MAX_CHUNK_SIZE = 25;
833cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var prefetchMetadataQueue = new AsyncUtil.ConcurrentQueue(4);
834cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (var i = 0; i < entriesFiltered.length; i += MAX_CHUNK_SIZE) {
835cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (prefetchMetadataQueue.isCancelled())
836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      var chunk = entriesFiltered.slice(i, i + MAX_CHUNK_SIZE);
839cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      prefetchMetadataQueue.run(function(chunk, callbackInner) {
8406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        this.prefetchMetadata(chunk, refresh, function() {
841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (!prefetchMetadataQueue.isCancelled()) {
842cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            if (this.scanCancelled_)
843cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              prefetchMetadataQueue.cancel();
844cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
8454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
846cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // Checks if this is the last task.
847cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (prefetchMetadataQueue.getWaitingTasksCount() === 0 &&
848cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              prefetchMetadataQueue.getRunningTasksCount() === 1) {
849f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            // |callbackOuter| in |finish| must be called before
850f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            // |callbackInner|, to prevent double-calling.
851f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            finish();
852cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
853cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
854cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          callbackInner();
855cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }.bind(this));
856cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }.bind(this, chunk));
857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }.bind(this));
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array.<Entry>} entries Files.
8636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) * @param {boolean} refresh True to refresh metadata, or false to use cached
8646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) *     one.
865558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {function(Object)} callback Callback on done.
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)DirectoryContents.prototype.prefetchMetadata =
8686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    function(entries, refresh, callback) {
8691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  var TYPES = 'filesystem|external';
8706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (refresh)
8716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    this.context_.metadataCache.getLatest(entries, TYPES, callback);
8726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  else
8736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    this.context_.metadataCache.get(entries, TYPES, callback);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
8774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Creates a DirectoryContents instance to show entries in a directory.
878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
8794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {FileListContext} context File list context.
8804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DirectoryEntry} directoryEntry The current directory entry.
8814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {DirectoryContents} Created DirectoryContents instance.
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectoryContents.createForDirectory = function(context, directoryEntry) {
8844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return new DirectoryContents(
8854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      context,
8864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      false,  // Non search.
8874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      directoryEntry,
8884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      function() {
8894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return new DirectoryContentScanner(directoryEntry);
8904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      });
8914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
8944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Creates a DirectoryContents instance to show the result of the search on
8954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Drive File System.
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {FileListContext} context File list context.
8984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DirectoryEntry} directoryEntry The current directory entry.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} query Search query.
9004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {DirectoryContents} Created DirectoryContents instance.
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectoryContents.createForDriveSearch = function(
9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    context, directoryEntry, query) {
9044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return new DirectoryContents(
9054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      context,
9064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      true,  // Search.
9074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      directoryEntry,
9084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      function() {
9094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return new DriveSearchContentScanner(query);
9104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      });
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
9144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Creates a DirectoryContents instance to show the result of the search on
9154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Local File System.
9164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {FileListContext} context File list context.
9184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DirectoryEntry} directoryEntry The current directory entry.
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} query Search query.
9204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {DirectoryContents} Created DirectoryContents instance.
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectoryContents.createForLocalSearch = function(
9234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    context, directoryEntry, query) {
9244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return new DirectoryContents(
9254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      context,
9264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      true,  // Search.
9274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      directoryEntry,
9284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      function() {
9294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return new LocalSearchContentScanner(directoryEntry, query);
9304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      });
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
9344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Creates a DirectoryContents instance to show the result of metadata search
9354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * on Drive File System.
936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {FileListContext} context File list context.
9384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DirectoryEntry} fakeDirectoryEntry Fake directory entry representing
9394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     the set of result entries. This serves as a top directory for the
9404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     search.
9414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DriveMetadataSearchContentScanner.SearchType} searchType The type of
9424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     the search. The scanner will restricts the entries based on the given
9434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *     type.
9444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {DirectoryContents} Created DirectoryContents instance.
9454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
9464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectoryContents.createForDriveMetadataSearch = function(
9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    context, fakeDirectoryEntry, searchType) {
9484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return new DirectoryContents(
9494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      context,
9504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      true,  // Search
9514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      fakeDirectoryEntry,
9524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      function() {
9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return new DriveMetadataSearchContentScanner(searchType);
9544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      });
955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
956