| Index: chrome/test/data/extensions/api_test/file_system_provider/thumbnail/test.js
 | 
| diff --git a/chrome/test/data/extensions/api_test/file_system_provider/thumbnail/test.js b/chrome/test/data/extensions/api_test/file_system_provider/thumbnail/test.js
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..0916a71b754efd5252653dd9e050ff9a9a31f33e
 | 
| --- /dev/null
 | 
| +++ b/chrome/test/data/extensions/api_test/file_system_provider/thumbnail/test.js
 | 
| @@ -0,0 +1,217 @@
 | 
| +// Copyright 2014 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +'use strict';
 | 
| +
 | 
| +/**
 | 
| + * @type {Object}
 | 
| + * @const
 | 
| + */
 | 
| +var TESTING_ROOT = Object.freeze({
 | 
| +  isDirectory: true,
 | 
| +  name: '',
 | 
| +  size: 0,
 | 
| +  modificationTime: new Date(2013, 3, 27, 9, 38, 14)
 | 
| +});
 | 
| +
 | 
| +/**
 | 
| + * @type {Object}
 | 
| + * @const
 | 
| + */
 | 
| +var TESTING_WITH_VALID_THUMBNAIL_FILE = Object.freeze({
 | 
| +  isDirectory: false,
 | 
| +  name: 'valid-thumbnail.txt',
 | 
| +  size: 4096,
 | 
| +  modificationTime: new Date(2014, 4, 28, 10, 39, 15),
 | 
| +  thumbnail: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA' +
 | 
| +             'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO' +
 | 
| +             '9TXL0Y4OHwAAAABJRU5ErkJggg=='
 | 
| +});
 | 
| +
 | 
| +/**
 | 
| + * @type {Object}
 | 
| + * @const
 | 
| + */
 | 
| +var TESTING_ALWAYS_WITH_THUMBNAIL_FILE = Object.freeze({
 | 
| +  isDirectory: false,
 | 
| +  name: 'always-with-thumbnail.txt',
 | 
| +  size: 4096,
 | 
| +  modificationTime: new Date(2014, 4, 28, 10, 39, 15),
 | 
| +  thumbnail: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA' +
 | 
| +             'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO' +
 | 
| +             '9TXL0Y4OHwAAAABJRU5ErkJggg=='
 | 
| +});
 | 
| +
 | 
| +/**
 | 
| + * @type {Object}
 | 
| + * @const
 | 
| + */
 | 
| +var TESTING_WITH_INVALID_THUMBNAIL_FILE = Object.freeze({
 | 
| +  isDirectory: false,
 | 
| +  name: 'invalid-thumbnail.txt',
 | 
| +  size: 4096,
 | 
| +  modificationTime: new Date(2014, 4, 28, 10, 39, 15),
 | 
| +  thumbnail: 'https://www.foobar.com/evil'
 | 
| +});
 | 
| +
 | 
| +/**
 | 
| + * Returns metadata for a requested entry.
 | 
| + *
 | 
| + * @param {GetMetadataRequestedOptions} options Options.
 | 
| + * @param {function(Object)} onSuccess Success callback with metadata passed
 | 
| + *     an argument.
 | 
| + * @param {function(string)} onError Error callback with an error code.
 | 
| + */
 | 
| +function onGetMetadataRequested(options, onSuccess, onError) {
 | 
| +  if (options.fileSystemId != test_util.FILE_SYSTEM_ID) {
 | 
| +    onError('SECURITY');  // enum ProviderError.
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  // Metadata to be returned.
 | 
| +  var metadata;
 | 
| +
 | 
| +  switch (options.entryPath) {
 | 
| +    case '/':
 | 
| +      metadata = TESTING_ROOT;
 | 
| +      break;
 | 
| +
 | 
| +    case '/' + TESTING_WITH_VALID_THUMBNAIL_FILE.name:
 | 
| +      metadata = TESTING_WITH_VALID_THUMBNAIL_FILE;
 | 
| +      break;
 | 
| +
 | 
| +    case '/' + TESTING_ALWAYS_WITH_THUMBNAIL_FILE.name:
 | 
| +      metadata = TESTING_ALWAYS_WITH_THUMBNAIL_FILE;
 | 
| +      break;
 | 
| +
 | 
| +    case '/' + TESTING_WITH_INVALID_THUMBNAIL_FILE.name:
 | 
| +      metadata = TESTING_WITH_INVALID_THUMBNAIL_FILE;
 | 
| +      break;
 | 
| +
 | 
| +    default:
 | 
| +      onError('NOT_FOUND');  // enum ProviderError.
 | 
| +      return;
 | 
| +  }
 | 
| +
 | 
| +  // Returning a thumbnail while not requested is not allowed for performance
 | 
| +  // reasons. Remove the field if needed. However, do not remove it for one
 | 
| +  // file, to simulate an error.
 | 
| +  if (!options.thumbnail && metadata.thumbnail &&
 | 
| +      options.entryPath != '/' + TESTING_ALWAYS_WITH_THUMBNAIL_FILE.name) {
 | 
| +    var metadataWithoutThumbnail = {
 | 
| +      isDirectory: metadata.isDirectory,
 | 
| +      name: metadata.name,
 | 
| +      size: metadata.size,
 | 
| +      modificationTime: metadata.modificationTime
 | 
| +    };
 | 
| +    onSuccess(metadataWithoutThumbnail);
 | 
| +  } else {
 | 
| +    onSuccess(metadata);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +/**
 | 
| + * Sets up the tests. Called once per all test cases. In case of a failure,
 | 
| + * the callback is not called.
 | 
| + *
 | 
| + * @param {function()} callback Success callback.
 | 
| + */
 | 
| +function setUp(callback) {
 | 
| +  chrome.fileSystemProvider.onGetMetadataRequested.addListener(
 | 
| +      onGetMetadataRequested);
 | 
| +  test_util.mountFileSystem(callback);
 | 
| +}
 | 
| +
 | 
| +/**
 | 
| + * Runs all of the test cases, one by one.
 | 
| + */
 | 
| +function runTests() {
 | 
| +  chrome.test.runTests([
 | 
| +    // Test if providers are notified that no thumbnail is requested when normal
 | 
| +    // metadata is requested.
 | 
| +    function notRequestedAndNotProvidedThumbnailSuccess() {
 | 
| +      var onSuccess = chrome.test.callbackPass();
 | 
| +      test_util.fileSystem.root.getFile(
 | 
| +          TESTING_WITH_VALID_THUMBNAIL_FILE.name,
 | 
| +          {create: false},
 | 
| +          function(fileEntry) {
 | 
| +            onSuccess();
 | 
| +          }, function(error) {
 | 
| +            chrome.test.fail(error.name);
 | 
| +          });
 | 
| +    },
 | 
| +
 | 
| +    // If providers return a thumbnail data despite not being requested for
 | 
| +    // that, then the operation must fail.
 | 
| +    function notRequestedButProvidedThumbnailError() {
 | 
| +      var onSuccess = chrome.test.callbackPass();
 | 
| +      test_util.fileSystem.root.getFile(
 | 
| +          TESTING_ALWAYS_WITH_THUMBNAIL_FILE.name,
 | 
| +          {create: false},
 | 
| +          function(fileEntry) {
 | 
| +            chrome.test.fail(
 | 
| +                'Thumbnail returned when not requested should result in an ' +
 | 
| +                'error, but the operation succeeded.');
 | 
| +          }, function(error) {
 | 
| +            chrome.test.assertEq('InvalidStateError', error.name);
 | 
| +            onSuccess();
 | 
| +          });
 | 
| +    },
 | 
| +
 | 
| +    // Thumbnails should be returned when available for private API request.
 | 
| +    function getEntryPropertiesWithThumbnailSuccess() {
 | 
| +      var onSuccess = chrome.test.callbackPass();
 | 
| +      test_util.fileSystem.root.getFile(
 | 
| +          TESTING_WITH_VALID_THUMBNAIL_FILE.name,
 | 
| +          {create: false},
 | 
| +          function(fileEntry) {
 | 
| +            chrome.fileBrowserPrivate.getEntryProperties(
 | 
| +                [fileEntry.toURL()],
 | 
| +                function(fileProperties) {
 | 
| +                  chrome.test.assertEq(1, fileProperties.length);
 | 
| +                  chrome.test.assertEq(
 | 
| +                      TESTING_WITH_VALID_THUMBNAIL_FILE.thumbnail,
 | 
| +                      fileProperties[0].thumbnailUrl);
 | 
| +                  chrome.test.assertEq(
 | 
| +                      TESTING_WITH_VALID_THUMBNAIL_FILE.fileSize,
 | 
| +                      fileProperties[0].size);
 | 
| +                  chrome.test.assertEq(
 | 
| +                      TESTING_WITH_VALID_THUMBNAIL_FILE.modificationTime,
 | 
| +                      new Date(fileProperties[0].lastModifiedTime));
 | 
| +                  onSuccess();
 | 
| +                });
 | 
| +            },
 | 
| +            function(error) {
 | 
| +              chrome.test.fail(error.name);
 | 
| +            });
 | 
| +    },
 | 
| +
 | 
| +    // Confirm that extensions are not able to pass an invalid thumbnail url,
 | 
| +    // including evil urls.
 | 
| +    function getEntryPropertiesWithInvalidThumbnail() {
 | 
| +      var onSuccess = chrome.test.callbackPass();
 | 
| +      test_util.fileSystem.root.getFile(
 | 
| +          TESTING_WITH_INVALID_THUMBNAIL_FILE.name,
 | 
| +          {create: false},
 | 
| +          function(fileEntry) {
 | 
| +            chrome.fileBrowserPrivate.getEntryProperties(
 | 
| +                [fileEntry.toURL()],
 | 
| +                function(fileProperties) {
 | 
| +                  chrome.test.assertEq(1, fileProperties.length);
 | 
| +                  // The results for an entry is an empty dictionary in case of
 | 
| +                  // an error.
 | 
| +                  chrome.test.assertEq(
 | 
| +                      0, Object.keys(fileProperties[0]).length);
 | 
| +                  onSuccess();
 | 
| +                });
 | 
| +            },
 | 
| +            function(error) {
 | 
| +              chrome.test.fail(error.name);
 | 
| +            });
 | 
| +    }
 | 
| +  ]);
 | 
| +}
 | 
| +
 | 
| +// Setup and run all of the test cases.
 | 
| +setUp(runTests);
 | 
| 
 |