1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7// Fake data similar to a file system structure.
8var MODIFICATION_DATE = new Date();
9var SHORT_CONTENTS = 'Just another example.';
10var LONGER_CONTENTS = 'It works!\nEverything gets displayed correctly.';
11
12var METADATA = {
13  '/': {isDirectory: true, name: '/', size: 0,
14      modificationTime: MODIFICATION_DATE},
15  '/file1.txt': {isDirectory: false, name: 'file1.txt',
16      size: LONGER_CONTENTS.length, modificationTime: MODIFICATION_DATE,
17      contents: LONGER_CONTENTS},
18  '/file2': {isDirectory: false, name: 'file2', size: 150,
19      modificationTime: MODIFICATION_DATE},
20  '/dir': {isDirectory: true, name: 'dir', size: 0,
21      modificationTime: MODIFICATION_DATE},
22  '/dir/file3.txt': {isDirectory: false, name: 'file3.txt',
23      size: SHORT_CONTENTS.length, modificationTime: MODIFICATION_DATE,
24      contents: SHORT_CONTENTS}};
25
26// A map with currently opened files. As key it has requestId of
27// openFileRequested and as a value the file path.
28var openedFiles = {};
29
30function onGetMetadataRequested(options, onSuccess, onError) {
31  if (!METADATA[options.entryPath])
32    onError('NOT_FOUND');
33  else
34    onSuccess(METADATA[options.entryPath]);
35}
36
37function onReadDirectoryRequested(options, onSuccess, onError) {
38  if (!METADATA[options.directoryPath]) {
39    onError('NOT_FOUND');
40    return;
41  }
42  if (!METADATA[options.directoryPath].isDirectory) {
43    onError('NOT_A_DIRECTORY');
44    return;
45  }
46
47  // Retrieve directory contents from METADATA.
48  var entries = [];
49  for (var entry in METADATA) {
50    // Do not add itself on the list.
51    if (entry == options.directoryPath)
52      continue;
53    // Check if the entry is a child of the requested directory.
54    if (entry.indexOf(options.directoryPath) != 0)
55      continue;
56    // Restrict to direct children only.
57    if (entry.substring(options.directoryPath.length + 1).indexOf('/') != -1)
58      continue;
59
60    entries.push(METADATA[entry]);
61  }
62  onSuccess(entries, false /* Last call. */);
63}
64
65function onOpenFileRequested(options, onSuccess, onError) {
66  if (options.mode != 'READ' || options.create) {
67    onError('INVALID_OPERATION');
68  } else {
69    openedFiles[options.requestId] = options.filePath;
70    onSuccess();
71  }
72}
73
74function onCloseFileRequested(options, onSuccess, onError) {
75  if (!openedFiles[options.openRequestId]) {
76    onError('INVALID_OPERATION');
77  } else {
78    delete openedFiles[options.openRequestId];
79    onSuccess();
80  }
81}
82
83function onReadFileRequested(options, onSuccess, onError) {
84  if (!openedFiles[options.openRequestId]) {
85    onError('INVALID_OPERATION');
86    return;
87  }
88
89  var contents =
90      METADATA[openedFiles[options.openRequestId]].contents;
91
92  // Write the contents as ASCII text.
93  var buffer = new ArrayBuffer(options.length);
94  var bufferView = new Uint8Array(buffer);
95  for (var i = 0; i < options.length; i++) {
96    bufferView[i] = contents.charCodeAt(i);
97  }
98
99  onSuccess(buffer, false /* Last call. */);
100}
101
102// Mount the file system.
103chrome.runtime.onInstalled.addListener(function(details) {
104  chrome.fileSystemProvider.mount(
105      {fileSystemId: 'sample-file-system', displayName: 'Sample File System'},
106      function() {},
107      function() { console.error('Failed to mount.'); });
108});
109
110chrome.fileSystemProvider.onGetMetadataRequested.addListener(
111    onGetMetadataRequested);
112chrome.fileSystemProvider.onReadDirectoryRequested.addListener(
113    onReadDirectoryRequested);
114chrome.fileSystemProvider.onOpenFileRequested.addListener(
115    onOpenFileRequested);
116chrome.fileSystemProvider.onCloseFileRequested.addListener(
117    onCloseFileRequested);
118chrome.fileSystemProvider.onReadFileRequested.addListener(
119    onReadFileRequested);
120