| LEFT | RIGHT | 
|---|
| (no file at all) |  | 
| 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-present eyeo GmbH | 3  * Copyright (C) 2006-present 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 | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 12  * GNU General Public License for more details. | 12  * GNU General Public License for more details. | 
| 13  * | 13  * | 
| 14  * You should have received a copy of the GNU General Public License | 14  * You should have received a copy of the GNU General Public License | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 16  */ | 16  */ | 
| 17 | 17 | 
| 18 /* eslint-env node */ |  | 
| 19 /* eslint no-console: "off" */ |  | 
| 20 |  | 
| 21 "use strict"; | 18 "use strict"; | 
| 22 | 19 | 
| 23 const childProcess = require("child_process"); | 20 const childProcess = require("child_process"); | 
| 24 const fs = require("fs"); | 21 const fs = require("fs"); | 
| 25 const https = require("https"); |  | 
| 26 const os = require("os"); | 22 const os = require("os"); | 
| 27 const path = require("path"); | 23 const path = require("path"); | 
| 28 | 24 | 
| 29 const remoteInterface = require("chrome-remote-interface"); | 25 const remoteInterface = require("chrome-remote-interface"); | 
| 30 const extractZip = require("extract-zip"); | 26 | 
| 31 | 27 const {ensureChromium} = require("./chromium_download"); | 
|  | 28 | 
|  | 29 // Chromium 60.0.3082.x | 
| 32 const CHROMIUM_REVISION = 467222; | 30 const CHROMIUM_REVISION = 467222; | 
| 33 | 31 | 
| 34 function rmdir(dirPath) | 32 function rmdir(dirPath) | 
| 35 { | 33 { | 
| 36   for (let file of fs.readdirSync(dirPath)) | 34   for (let file of fs.readdirSync(dirPath)) | 
| 37   { | 35   { | 
| 38     let filePath = path.join(dirPath, file); | 36     let filePath = path.join(dirPath, file); | 
| 39     try | 37     try | 
| 40     { | 38     { | 
| 41       if (fs.statSync(filePath).isDirectory()) | 39       if (fs.statSync(filePath).isDirectory()) | 
| 42         rmdir(filePath); | 40         rmdir(filePath); | 
| 43       else | 41       else | 
| 44         fs.unlinkSync(filePath); | 42         fs.unlinkSync(filePath); | 
| 45     } | 43     } | 
| 46     catch (error) | 44     catch (error) | 
| 47     { | 45     { | 
| 48       console.error(error); | 46       console.error(error); | 
| 49     } | 47     } | 
| 50   } | 48   } | 
| 51 | 49 | 
| 52   try | 50   try | 
| 53   { | 51   { | 
| 54     fs.rmdirSync(dirPath); | 52     fs.rmdirSync(dirPath); | 
| 55   } | 53   } | 
| 56   catch (error) | 54   catch (error) | 
| 57   { | 55   { | 
| 58     console.error(error); | 56     console.error(error); | 
| 59   } | 57   } | 
| 60 } |  | 
| 61 |  | 
| 62 function getChromiumExecutable(chromiumDir) |  | 
| 63 { |  | 
| 64   switch (process.platform) |  | 
| 65   { |  | 
| 66     case "win32": |  | 
| 67       return path.join(chromiumDir, "chrome-win32", "chrome.exe"); |  | 
| 68     case "linux": |  | 
| 69       return path.join(chromiumDir, "chrome-linux", "chrome"); |  | 
| 70     case "darwin": |  | 
| 71       return path.join(chromiumDir, "chrome-mac", "Chromium.app", "Contents", |  | 
| 72                        "MacOS", "Chromium"); |  | 
| 73     default: |  | 
| 74       throw new Error("Unexpected platform"); |  | 
| 75   } |  | 
| 76 } |  | 
| 77 |  | 
| 78 function ensureChromium() |  | 
| 79 { |  | 
| 80   let {platform} = process; |  | 
| 81   if (platform == "win32") |  | 
| 82     platform += "-" + process.arch; |  | 
| 83   let buildTypes = { |  | 
| 84     "win32-ia32": ["Win", "chrome-win32.zip"], |  | 
| 85     "win32-x64": ["Win_x64", "chrome-win32.zip"], |  | 
| 86     "linux": ["Linux_x64", "chrome-linux.zip"], |  | 
| 87     "darwin": ["Mac", "chrome-mac.zip"] |  | 
| 88   }; |  | 
| 89 |  | 
| 90   if (!buildTypes.hasOwnProperty(platform)) |  | 
| 91   { |  | 
| 92     let err = new Error(`Cannot run browser tests, ${platform} is unsupported`); |  | 
| 93     return Promise.reject(err); |  | 
| 94   } |  | 
| 95 |  | 
| 96 |  | 
| 97   return Promise.resolve().then(() => |  | 
| 98   { |  | 
| 99     let snapshotsDir = path.join(__dirname, "chromium-snapshots"); |  | 
| 100     let chromiumDir = path.join(snapshotsDir, |  | 
| 101                                 `chromium-${platform}-${CHROMIUM_REVISION}`); |  | 
| 102     if (fs.existsSync(chromiumDir)) |  | 
| 103       return chromiumDir; |  | 
| 104 |  | 
| 105     if (!fs.existsSync(path.dirname(chromiumDir))) |  | 
| 106       fs.mkdirSync(path.dirname(chromiumDir)); |  | 
| 107 |  | 
| 108     let [dir, fileName] = buildTypes[platform]; |  | 
| 109     let archive = path.join(snapshotsDir, "download-cache", |  | 
| 110                             `${CHROMIUM_REVISION}-${fileName}`); |  | 
| 111 |  | 
| 112     return Promise.resolve() |  | 
| 113       .then(() => |  | 
| 114       { |  | 
| 115         if (!fs.existsSync(archive)) |  | 
| 116         { |  | 
| 117           let url = `https://www.googleapis.com/download/storage/v1/b/chromium-b
     rowser-snapshots/o/${dir}%2F${CHROMIUM_REVISION}%2F${fileName}?alt=media`; |  | 
| 118           console.info("Downloading Chromium..."); |  | 
| 119           return download(url, archive); |  | 
| 120         } |  | 
| 121         console.info(`Reusing cached archive ${archive}`); |  | 
| 122       }) |  | 
| 123       .then(() => unzipArchive(archive, chromiumDir)) |  | 
| 124       .then(() => chromiumDir); |  | 
| 125   }).then(dir => getChromiumExecutable(dir)); |  | 
| 126 } |  | 
| 127 |  | 
| 128 function download(url, destFile) |  | 
| 129 { |  | 
| 130   return new Promise((resolve, reject) => |  | 
| 131   { |  | 
| 132     let cacheDir = path.dirname(destFile); |  | 
| 133     if (!fs.existsSync(cacheDir)) |  | 
| 134       fs.mkdirSync(cacheDir); |  | 
| 135     let tempDest = destFile + "-" + process.pid; |  | 
| 136     let writable = fs.createWriteStream(tempDest); |  | 
| 137 |  | 
| 138     https.get(url, response => |  | 
| 139     { |  | 
| 140       if (response.statusCode != 200) |  | 
| 141       { |  | 
| 142         reject( |  | 
| 143           new Error(`Unexpected server response: ${response.statusCode}`)); |  | 
| 144         response.resume(); |  | 
| 145         return; |  | 
| 146       } |  | 
| 147 |  | 
| 148       response.pipe(writable) |  | 
| 149               .on("error", error => |  | 
| 150               { |  | 
| 151                 writable.close(); |  | 
| 152                 fs.unlinkSync(tempDest); |  | 
| 153                 reject(error); |  | 
| 154               }) |  | 
| 155               .on("close", () => |  | 
| 156               { |  | 
| 157                 writable.close(); |  | 
| 158                 fs.renameSync(tempDest, destFile); |  | 
| 159                 resolve(); |  | 
| 160               }); |  | 
| 161     }).on("error", reject); |  | 
| 162   }); |  | 
| 163 } |  | 
| 164 |  | 
| 165 function unzipArchive(archive, destDir) |  | 
| 166 { |  | 
| 167   return new Promise((resolve, reject) => |  | 
| 168   { |  | 
| 169     extractZip(archive, {dir: destDir}, err => |  | 
| 170     { |  | 
| 171       if (err) |  | 
| 172         reject(err); |  | 
| 173       else |  | 
| 174         resolve(); |  | 
| 175     }); |  | 
| 176   }); |  | 
| 177 } | 58 } | 
| 178 | 59 | 
| 179 function startChromium(chromiumPath) | 60 function startChromium(chromiumPath) | 
| 180 { | 61 { | 
| 181   fs.chmodSync(chromiumPath, fs.constants.S_IRWXU); | 62   fs.chmodSync(chromiumPath, fs.constants.S_IRWXU); | 
| 182 | 63 | 
| 183   let dataDir = fs.mkdtempSync(path.join(os.tmpdir(), "chromium-data")); | 64   let dataDir = fs.mkdtempSync(path.join(os.tmpdir(), "chromium-data")); | 
| 184   let child = null; | 65   let child = null; | 
| 185   return { | 66   return { | 
| 186     kill: () => child && child.kill(), | 67     kill: () => child && child.kill(), | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 249 } | 130 } | 
| 250 | 131 | 
| 251 function runScript(script, scriptName, scriptArgs) | 132 function runScript(script, scriptName, scriptArgs) | 
| 252 { | 133 { | 
| 253   return connectRemoteInterface().then(async client => | 134   return connectRemoteInterface().then(async client => | 
| 254   { | 135   { | 
| 255     try | 136     try | 
| 256     { | 137     { | 
| 257       let {Runtime, Log, Console} = client; | 138       let {Runtime, Log, Console} = client; | 
| 258 | 139 | 
|  | 140       console.log("\nBrowser tests in Chromium (Remote Interface)\n"); | 
|  | 141 | 
| 259       await Log.enable(); | 142       await Log.enable(); | 
| 260       Log.entryAdded(({entry}) => | 143       Log.entryAdded(({entry}) => | 
| 261       { | 144       { | 
| 262         reportMessage(entry.text, entry.level); | 145         reportMessage(entry.text, entry.level); | 
| 263       }); | 146       }); | 
| 264 | 147 | 
| 265       await Console.enable(); | 148       await Console.enable(); | 
| 266       Console.messageAdded(({message}) => | 149       Console.messageAdded(({message}) => | 
| 267       { | 150       { | 
| 268         reportMessage(message.text, message.level); | 151         reportMessage(message.text, message.level); | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 299     } | 182     } | 
| 300     finally | 183     finally | 
| 301     { | 184     { | 
| 302       client.close(); | 185       client.close(); | 
| 303     } | 186     } | 
| 304   }); | 187   }); | 
| 305 } | 188 } | 
| 306 | 189 | 
| 307 module.exports = function(script, scriptName, ...scriptArgs) | 190 module.exports = function(script, scriptName, ...scriptArgs) | 
| 308 { | 191 { | 
| 309   return ensureChromium().then(chromiumPath => | 192   return ensureChromium(CHROMIUM_REVISION).then(chromiumPath => | 
| 310   { | 193   { | 
| 311     let child = startChromium(chromiumPath); | 194     let child = startChromium(chromiumPath); | 
| 312     return Promise.race([ | 195     return Promise.race([ | 
| 313       child.done, | 196       child.done, | 
| 314       runScript(script, scriptName, scriptArgs) | 197       runScript(script, scriptName, scriptArgs) | 
| 315     ]).then(result => | 198     ]).then(result => | 
| 316     { | 199     { | 
| 317       child.kill(); | 200       child.kill(); | 
| 318       return result; | 201       return result; | 
| 319     }).catch(error => | 202     }).catch(error => | 
| 320     { | 203     { | 
| 321       child.kill(); | 204       child.kill(); | 
| 322       throw error; | 205       throw error; | 
| 323     }); | 206     }); | 
| 324   }); | 207   }); | 
| 325 }; | 208 }; | 
| LEFT | RIGHT | 
|---|