- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / api_test / file_browser / file_browser_handler / background.js
1 // Copyright (c) 2013 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 /**
6  * This extension provides two file browser handlers: 'ReadOnly' and
7  * 'ReadWrite'. 'ReadOnly' handler handles .xul files and has read-only file
8  * access. 'ReadWrite' handler handles .tiff files and has read-write file
9  * access.
10  *
11  * The extension waits until both handlers are executed and then runs tests for
12  * them. The tests verify that the extension is able to read/write the handled
13  * files as defined by the handlers' file access permissions. If there is an
14  * error before the tests are run, chrome.test.notifyFail will be called, and
15  * further onExecute events will be ignored.
16  *
17  * The handlers are executed by 'file_browser/handler_test_runner' extension.
18  * Each of 'ReadOnly' and 'ReadWrite' handlers should be executed once, and each
19  * should carry exactly one handled file.
20  */
21
22 // Initial content of handled files. The content is set in
23 // external_filesystem_apitest.cc.
24 var kInitialTestFileContent = 'This is some test content.';
25 // Content written by write test.
26 var kTextToWrite = ' Yay!';
27
28 /**
29  * Asserts that |value| equals |expectedValue|. If the assert fails, current
30  * test fails with |errorMessage|. Otherwise, |callback()| is called.
31  */
32 function assertEqAndRunCallback(expectedValue, value, errorMessage, callback) {
33   chrome.test.assertEq(expectedValue, value, errorMessage);
34   callback();
35 }
36
37 /**
38  * Attempts to read file and asserts that the read success and file content are
39  * as expected (|expectSuccess|, |expectedContent|). On success |callback| is
40  * called, otherwise current test is failed.
41  *
42  * @param {FileEntry} entry Entry to be read.
43  * @param {boolean} expectSuccess Whether the read should succeed.
44  * @param {string} expectedContent If the read succeeds, the expected content to
45  *     be read from file. If the read fails, it is ignored.
46  * @param {function()} callback Function called if the read ends as defined by
47  *     |expectSuccess| and |expectedContent|.
48  */
49 function readAndExpectContent(entry, expectSuccess, expectedContent, callback) {
50   var error = 'Reading file \'' + entry.fullPath + '\'.';
51   var reader = new FileReader();
52
53   reader.onload = function() {
54     chrome.test.assertTrue(expectSuccess, error);
55     assertEqAndRunCallback(expectedContent, reader.result, error, callback);
56   };
57
58   entry.file(reader.readAsText.bind(reader),
59              assertEqAndRunCallback.bind(null,
60                  false, expectSuccess, error, callback));
61 };
62
63 /**
64  * Attempts to write |content| to the end of the |entry| and verifies that the
65  * operation success is as expected. On success |callback| is called, else the
66  * current test is failed.
67  *
68  * @param {FileEntry} entry File entry to be read.
69  * @param {string} content String content to be appended to the file.
70  * @param {boolean} expectSuccess Whether the write should succeed.
71  * @param {function()} callback Function called if write ends as defined by
72  *     |expectSuccess|.
73  */
74 function write(entry, content, expectSuccess, callback) {
75   var error = 'Writing to: \'' + entry.fullPath + '\'.';
76
77   entry.createWriter(function(writer) {
78     writer.onerror = assertEqAndRunCallback.bind(null, expectSuccess, false,
79                                                  error, callback);
80     writer.onwrite = assertEqAndRunCallback.bind(null, expectSuccess, true,
81                                                  error, callback);
82
83     writer.seek(kInitialTestFileContent.length);
84     var blob = new Blob([kTextToWrite], {type: 'text/plain'});
85     writer.write(blob);
86   },
87   assertEqAndRunCallback.bind(null, expectSuccess, false,
88       'Getting writer for: \'' + entry.fullPath + '\'.', callback));
89 };
90
91 /**
92  * Runs read test.
93  *
94  * @params {FileEntry} entry File entry for which the test should be run.
95  * @params {boolean} expectSuccess Whether the read should succeed.
96  */
97 function readTest(entry, expectSuccess) {
98   readAndExpectContent(entry, expectSuccess, kInitialTestFileContent,
99                        chrome.test.succeed)
100 }
101
102 /**
103  * Runs test for a file that is not executed for any handler. Test tries to get
104  * an existing file entry from the |entry|'s filesystem. The file path is
105  * constructed by appending '.foo' to the |entry|'s path (the Chrome part of the
106  * test should ensure that the file exists). The get operation is expected to
107  * fail.
108  */
109 function getSiblingTest(entry) {
110   var error = 'Got file (\'' + entry.fullPath.concat('.foo') + '\') for which' +
111               'file access was not granted.';
112   entry.filesystem.root.getFile(
113       entry.fullPath.concat('.foo'), {},
114       chrome.test.fail.bind(null, error),
115       chrome.test.succeed);
116 }
117
118 /**
119  * Runs write test.
120  * Attempts to write to the entry. If the write operation ends as expected, the
121  * test verifies new content of the file.
122  *
123  * @param {FileEntry} entry Entry to be written.
124  * @param {boolean} expectSuccess Whether the test should succeed.
125  */
126 function writeTest(entry, expectSuccess) {
127   var verifyFileContent = function() {
128     var expectedContent = kInitialTestFileContent;
129     // The test file content should change only if the write operatino
130     // succeeded.
131     if (expectSuccess)
132       expectedContent = expectedContent.concat(kTextToWrite);
133
134     readAndExpectContent(entry, true, expectedContent, chrome.test.succeed);
135   };
136
137   write(entry, kTextToWrite, expectSuccess, verifyFileContent);
138 }
139
140 /**
141  * Object that follows the extensions's status before chrome.test.runTests is
142  * called (i.e. while it's waiting for onExecute events).
143  */
144 var testPreRunStatus = {
145   // Whether the 'ReadOnly' handler has been executed.
146   gotReadOnlyAction: false,
147   // Whether the 'ReadWrite' handler has been executed.
148   gotReadWriteAction: false,
149   // |done| is set either when the runTests is called, or an error is detected.
150   // After |done| is set, all other onExecute events will be ignored.
151   done: false,
152 };
153
154 /**
155  * List of tests to be run for the handlers.
156  *
157  * @type {Array.<function()>}
158  */
159 var handlerTests = [];
160
161 /**
162  * Called if an error is detected before chrome.test.runTests. It sends failure
163  * notification and cancels further testing.
164  *
165  * @param {string} message The error message to be reported.
166  */
167 function onError(message) {
168   testPreRunStatus.done = true;
169   chrome.test.notifyFail(message);
170 }
171
172 /**
173  * Listens for onExecute events, and runs tests once all expected events are
174  * received.
175  */
176 function onExecuteListener(id, details) {
177   if (testPreRunStatus.done)
178     return;
179
180   var fileEntries = details.entries;
181   if (!fileEntries || fileEntries.length != 1) {
182     onError('Unexpected file entries size.');
183     return;
184   }
185
186   if ((id == 'ReadOnly' && testPreRunStatus.gotReadOnlyAction) ||
187       (id == 'ReadWrite' && testPreRunStatus.gotReadWriteAction)) {
188     onError('Action \'' + id + '\' executed more than once.');
189     return;
190   }
191
192   if (id == 'ReadOnly') {
193     var entry = fileEntries[0];
194
195     // Add tests for read-only handler.
196     handlerTests.push(function readReadOnly() { readTest(entry, true); });
197     handlerTests.push(
198         function getSiblingReadOnly() { getSiblingTest(entry); });
199     handlerTests.push(function writeReadOnly() { writeTest(entry, false); });
200
201     testPreRunStatus.gotReadOnlyAction = true;
202   } else if (id == 'ReadWrite') {
203     var entry = fileEntries[0];
204
205     // Add tests for read-write handler.
206     handlerTests.push(function readReadWrite() { readTest(entry, true); });
207     handlerTests.push(
208         function getSilblingReadWrite() { getSiblingTest(entry); });
209     handlerTests.push(function writeReadWrite() { writeTest(entry, true); });
210
211     testPreRunStatus.gotReadWriteAction = true;
212   } else {
213     onError('Unexpected action id: ' + id);
214     return;
215   }
216
217   if (testPreRunStatus.gotReadOnlyAction &&
218       testPreRunStatus.gotReadWriteAction) {
219     testPreRunStatus.done = true;
220     chrome.test.runTests(handlerTests);
221   }
222 }
223
224 chrome.fileBrowserHandler.onExecute.addListener(onExecuteListener);