| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2017 eyeo GmbH | 3 * Copyright (C) 2006-2017 eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 }); | 69 }); |
| 70 } | 70 } |
| 71 | 71 |
| 72 function legacyFile(fileName) | 72 function legacyFile(fileName) |
| 73 { | 73 { |
| 74 let file = LegacyIO.resolveFilePath("adblockplus"); | 74 let file = LegacyIO.resolveFilePath("adblockplus"); |
| 75 file.append(fileName); | 75 file.append(fileName); |
| 76 return file; | 76 return file; |
| 77 } | 77 } |
| 78 | 78 |
| 79 let fallback = { | |
| 80 readFromFile(fileName, listener) | |
| 81 { | |
| 82 let wrapper = { | |
| 83 process(line) | |
| 84 { | |
| 85 if (line !== null) | |
| 86 listener(line); | |
| 87 } | |
| 88 }; | |
| 89 return callLegacy("readFromFile", legacyFile(fileName), wrapper); | |
| 90 }, | |
| 91 | |
| 92 writeToFile(fileName, data) | |
| 93 { | |
| 94 return callLegacy("writeToFile", legacyFile(fileName), data); | |
| 95 }, | |
| 96 | |
| 97 copyFile(fromFile, toFile) | |
| 98 { | |
| 99 return callLegacy("copyFile", legacyFile(fromFile), legacyFile(toFile)); | |
| 100 }, | |
| 101 | |
| 102 renameFile(fromFile, newName) | |
| 103 { | |
| 104 return callLegacy("renameFile", legacyFile(fromFile), newName); | |
| 105 }, | |
| 106 | |
| 107 removeFile(fileName) | |
| 108 { | |
| 109 return callLegacy("removeFile", legacyFile(fileName)); | |
| 110 }, | |
| 111 | |
| 112 statFile(fileName) | |
| 113 { | |
| 114 return callLegacy("statFile", legacyFile(fileName)); | |
| 115 } | |
| 116 }; | |
| 117 | |
| 79 exports.IO = | 118 exports.IO = |
| 80 { | 119 { |
| 81 /** | 120 /** |
| 82 * @callback TextSink | 121 * @callback TextSink |
| 83 * @param {string} line | 122 * @param {string} line |
| 84 */ | 123 */ |
| 85 | 124 |
| 86 /** | 125 /** |
| 87 * Reads text lines from a file. | 126 * Reads text lines from a file. |
| 88 * @param {string} fileName | 127 * @param {string} fileName |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 109 { | 148 { |
| 110 Utils.runAsync(processBatch); | 149 Utils.runAsync(processBatch); |
| 111 return; | 150 return; |
| 112 } | 151 } |
| 113 } | 152 } |
| 114 resolve(); | 153 resolve(); |
| 115 } | 154 } |
| 116 | 155 |
| 117 processBatch(); | 156 processBatch(); |
| 118 }); | 157 }); |
| 119 }).catch(error => | |
| 120 { | |
| 121 if (error == "NoSuchFile") | |
| 122 { | |
| 123 let wrapper = { | |
| 124 process(line) | |
| 125 { | |
| 126 if (line !== null) | |
| 127 listener(line); | |
| 128 } | |
| 129 }; | |
| 130 return callLegacy("readFromFile", legacyFile(fileName), wrapper); | |
| 131 } | |
| 132 throw error; | |
| 133 }); | 158 }); |
| 134 }, | 159 }, |
| 135 | 160 |
| 136 /** | 161 /** |
| 137 * Writes text lines to a file. | 162 * Writes text lines to a file. |
| 138 * @param {string} fileName | 163 * @param {string} fileName |
| 139 * Name of the file to be written | 164 * Name of the file to be written |
| 140 * @param {Iterable.<string>} data | 165 * @param {Iterable.<string>} data |
| 141 * An array-like or iterable object containing the lines (without line | 166 * An array-like or iterable object containing the lines (without line |
| 142 * endings) | 167 * endings) |
| 143 * @return {Promise} | 168 * @return {Promise} |
| 144 * Promise to be resolved or rejected once the operation is completed | 169 * Promise to be resolved or rejected once the operation is completed |
| 145 */ | 170 */ |
| 146 writeToFile(fileName, data) | 171 writeToFile(fileName, data) |
| 147 { | 172 { |
| 148 return callWebExt("writeToFile", fileName, Array.from(data)); | 173 return callWebExt("writeToFile", fileName, Array.from(data)); |
| 149 }, | 174 }, |
| 150 | 175 |
| 151 /** | 176 /** |
| 152 * Copies a file. | 177 * Copies a file. |
| 153 * @param {string} fromFile | 178 * @param {string} fromFile |
| 154 * Name of the file to be copied | 179 * Name of the file to be copied |
| 155 * @param {string} toFile | 180 * @param {string} toFile |
| 156 * Name of the file to be written, will be overwritten if exists | 181 * Name of the file to be written, will be overwritten if exists |
| 157 * @return {Promise} | 182 * @return {Promise} |
| 158 * Promise to be resolved or rejected once the operation is completed | 183 * Promise to be resolved or rejected once the operation is completed |
| 159 */ | 184 */ |
| 160 copyFile(fromFile, toFile) | 185 copyFile(fromFile, toFile) |
| 161 { | 186 { |
| 162 return callWebExt("copyFile", fromFile, toFile).catch(error => | 187 return callWebExt("copyFile", fromFile, toFile); |
| 163 { | |
| 164 if (error == "NoSuchFile") | |
| 165 return callLegacy("copyFile", legacyFile(fromFile), legacyFile(toFile)); | |
| 166 throw error; | |
| 167 }); | |
| 168 }, | 188 }, |
| 169 | 189 |
| 170 /** | 190 /** |
| 171 * Renames a file. | 191 * Renames a file. |
| 172 * @param {string} fromFile | 192 * @param {string} fromFile |
| 173 * Name of the file to be renamed | 193 * Name of the file to be renamed |
| 174 * @param {string} newName | 194 * @param {string} newName |
| 175 * New file name, will be overwritten if exists | 195 * New file name, will be overwritten if exists |
| 176 * @return {Promise} | 196 * @return {Promise} |
| 177 * Promise to be resolved or rejected once the operation is completed | 197 * Promise to be resolved or rejected once the operation is completed |
| 178 */ | 198 */ |
| 179 renameFile(fromFile, newName) | 199 renameFile(fromFile, newName) |
| 180 { | 200 { |
| 181 return callWebExt("renameFile", fromFile, newName).catch(error => | 201 return callWebExt("renameFile", fromFile, newName); |
| 182 { | |
| 183 if (error == "NoSuchFile") | |
| 184 return callLegacy("renameFile", legacyFile(fromFile), newName); | |
| 185 throw error; | |
| 186 }); | |
| 187 }, | 202 }, |
| 188 | 203 |
| 189 /** | 204 /** |
| 190 * Removes a file. | 205 * Removes a file. |
| 191 * @param {string} fileName | 206 * @param {string} fileName |
| 192 * Name of the file to be removed | 207 * Name of the file to be removed |
| 193 * @return {Promise} | 208 * @return {Promise} |
| 194 * Promise to be resolved or rejected once the operation is completed | 209 * Promise to be resolved or rejected once the operation is completed |
| 195 */ | 210 */ |
| 196 removeFile(fileName) | 211 removeFile(fileName) |
| 197 { | 212 { |
| 198 return callWebExt("removeFile", fileName).catch(error => | 213 return callWebExt("removeFile", fileName); |
| 199 { | |
| 200 if (error == "NoSuchFile") | |
| 201 return callLegacy("removeFile", legacyFile(fileName)); | |
| 202 throw error; | |
| 203 }); | |
| 204 }, | 214 }, |
| 205 | 215 |
| 206 /** | 216 /** |
| 207 * @typedef StatData | 217 * @typedef StatData |
| 208 * @type {object} | 218 * @type {object} |
| 209 * @property {boolean} exists | 219 * @property {boolean} exists |
| 210 * true if the file exists | 220 * true if the file exists |
| 211 * @property {number} lastModified | 221 * @property {number} lastModified |
| 212 * file modification time in milliseconds | 222 * file modification time in milliseconds |
| 213 */ | 223 */ |
| 214 | 224 |
| 215 /** | 225 /** |
| 216 * Retrieves file metadata. | 226 * Retrieves file metadata. |
| 217 * @param {string} fileName | 227 * @param {string} fileName |
| 218 * Name of the file to be looked up | 228 * Name of the file to be looked up |
| 219 * @return {Promise.<StatData>} | 229 * @return {Promise.<StatData>} |
| 220 * Promise to be resolved with file metadata once the operation is | 230 * Promise to be resolved with file metadata once the operation is |
| 221 * completed | 231 * completed |
| 222 */ | 232 */ |
| 223 statFile(fileName) | 233 statFile(fileName) |
| 224 { | 234 { |
| 225 return callWebExt("statFile", fileName).catch(error => | 235 return callWebExt("statFile", fileName); |
| 226 { | |
| 227 if (error == "NoSuchFile") | |
| 228 return callLegacy("statFile", legacyFile(fileName)); | |
| 229 throw error; | |
| 230 }); | |
| 231 } | 236 } |
| 232 }; | 237 }; |
| 238 | |
| 239 let {application} = require("info"); | |
| 240 if (application != "firefox" && application != "fennec2") | |
| 241 { | |
| 242 // Currently, only Firefox has a working WebExtensions implementation, other | |
| 243 // applications should just use the fallback. | |
| 244 exports.IO = fallback; | |
| 245 } | |
| 246 else | |
| 247 { | |
| 248 for (let name of [ | |
| 249 "readFromFile", "copyFile", "renameFile", "removeFile", "statFile" | |
|
Felix Dahlke
2017/05/29 12:22:30
We could avoid duplication here by iterating over
Wladimir Palant
2017/05/29 12:41:23
Done.
| |
| 250 ]) | |
| 251 { | |
| 252 // For missing files, fall back to legacy I/O for all methods except | |
|
Felix Dahlke
2017/05/29 12:22:30
Nit: I think that comment should move in front of
Wladimir Palant
2017/05/29 12:41:23
Done.
| |
| 253 // writeToFile() | |
| 254 let method = exports.IO[name]; | |
| 255 let fallbackMethod = fallback[name]; | |
| 256 exports.IO[name] = (...args) => | |
| 257 { | |
| 258 return method(...args).catch(error => | |
| 259 { | |
| 260 if (error == "NoSuchFile") | |
| 261 return fallbackMethod(...args); | |
| 262 throw error; | |
| 263 }); | |
| 264 }; | |
| 265 } | |
| 266 } | |
| OLD | NEW |