| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2016 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 var fs = require("fs"); |
| 6 var http = require("http"); |
| 7 var https = require("https"); |
| 8 var path = require("path"); |
| 9 var parseURL = require("url").parse; |
| 10 |
| 11 var port = parseInt(process.env.PORT, 10) || 8090; |
| 12 |
| 13 http.createServer(requestHandler).listen(port); |
| 14 console.log("Started hosted mode server at http://localhost:" + port); |
| 15 |
| 16 function requestHandler(request, response) |
| 17 { |
| 18 var filePath = parseURL(request.url).pathname; |
| 19 if (filePath === "/front_end/InspectorBackendCommands.js") { |
| 20 sendResponse(200, " "); |
| 21 return; |
| 22 } |
| 23 |
| 24 var proxiedFile = proxy(filePath, sendResponse); |
| 25 if (proxiedFile) { |
| 26 proxiedFile |
| 27 .then(data => sendResponse(200, data)) |
| 28 .catch(handleProxyError); |
| 29 return; |
| 30 } |
| 31 |
| 32 function handleProxyError(err) |
| 33 { |
| 34 console.log(`Error fetching over the internet file ${filePath}:`, err); |
| 35 sendResponse(500, "500 - Internal Server Error"); |
| 36 } |
| 37 |
| 38 var absoluteFilePath = path.join(process.cwd(), filePath); |
| 39 fs.exists(absoluteFilePath, fsExistsCallback); |
| 40 |
| 41 function fsExistsCallback(fileExists) |
| 42 { |
| 43 if (!fileExists) { |
| 44 console.log(`Cannot find file ${absoluteFilePath}`); |
| 45 sendResponse(404, "404 - File not found"); |
| 46 return; |
| 47 } |
| 48 fs.readFile(absoluteFilePath, "binary", readFileCallback); |
| 49 } |
| 50 |
| 51 function readFileCallback(err, file) |
| 52 { |
| 53 if (err) { |
| 54 console.log(`Unable to read local file ${absoluteFilePath}:`, err); |
| 55 sendResponse(500, "500 - Internal Server Error"); |
| 56 return; |
| 57 } |
| 58 sendResponse(200, file); |
| 59 } |
| 60 |
| 61 function sendResponse(statusCode, data) |
| 62 { |
| 63 response.writeHead(statusCode); |
| 64 response.write(data, "binary"); |
| 65 response.end(); |
| 66 } |
| 67 } |
| 68 |
| 69 var proxyFilePathToURL = { |
| 70 "/front_end/sdk/protocol/js_protocol.json": getWebKitURL.bind(null, "platfor
m/v8_inspector/js_protocol.json"), |
| 71 "/front_end/sdk/protocol/browser_protocol.json": getWebKitURL.bind(null, "co
re/inspector/browser_protocol.json"), |
| 72 "/front_end/SupportedCSSProperties.js": getFrontendURL.bind(null, "Supported
CSSProperties.js") |
| 73 }; |
| 74 |
| 75 function getWebKitURL(path, commitHash) |
| 76 { |
| 77 return { |
| 78 url: `https://chromium.googlesource.com/chromium/src/+/${commitHash}/thi
rd_party/WebKit/Source/${path}?format=TEXT`, |
| 79 isBase64: true |
| 80 } |
| 81 } |
| 82 |
| 83 function getFrontendURL(path, commitHash) |
| 84 { |
| 85 return { |
| 86 url: `https://chrome-devtools-frontend.appspot.com/serve_file/@${commitH
ash}/${path}`, |
| 87 isBase64: false |
| 88 } |
| 89 } |
| 90 |
| 91 var proxyFileCache = new Map(); |
| 92 |
| 93 function proxy(filePath) |
| 94 { |
| 95 if (!(filePath in proxyFilePathToURL)) |
| 96 return null; |
| 97 return fetch("http://localhost:9222/json/version") |
| 98 .then(onBrowserMetadata); |
| 99 |
| 100 function onBrowserMetadata(metadata) |
| 101 { |
| 102 var metadataObject = JSON.parse(metadata); |
| 103 var match = metadataObject["WebKit-Version"].match(/\s\(@(\b[0-9a-f]{5,4
0}\b)/); |
| 104 var commitHash = match[1]; |
| 105 var proxyFile = proxyFilePathToURL[filePath](commitHash); |
| 106 var proxyFileURL = proxyFile.url; |
| 107 if (proxyFileCache.has(proxyFileURL)) |
| 108 return proxyFileCache.get(proxyFileURL); |
| 109 return fetch(proxyFileURL) |
| 110 .then(text => proxyFile.isBase64 ? new Buffer(text, "base64").toStri
ng("binary") : text) |
| 111 .then(cacheProxyFile.bind(null, proxyFileURL)); |
| 112 } |
| 113 |
| 114 function cacheProxyFile(proxyFileURL, data) |
| 115 { |
| 116 proxyFileCache.set(proxyFileURL, data); |
| 117 return data; |
| 118 } |
| 119 } |
| 120 |
| 121 function fetch(url) |
| 122 { |
| 123 return new Promise(fetchPromise); |
| 124 |
| 125 function fetchPromise(resolve, reject) { |
| 126 var request; |
| 127 var protocol = parseURL(url).protocol; |
| 128 var handleResponse = getCallback.bind(null, resolve, reject); |
| 129 if (protocol === "https:") { |
| 130 request = https.get(url, handleResponse); |
| 131 } else if (protocol === "http:") { |
| 132 request = http.get(url, handleResponse); |
| 133 } else { |
| 134 reject(new Error(`Invalid protocol for url: ${url}`)); |
| 135 return; |
| 136 } |
| 137 request.on("error", err => reject(err)); |
| 138 } |
| 139 |
| 140 function getCallback(resolve, reject, response) |
| 141 { |
| 142 if (response.statusCode !== 200) { |
| 143 reject(new Error(`Request error: + ${response.statusCode}`)); |
| 144 return; |
| 145 } |
| 146 var body = ""; |
| 147 response.on("data", chunk => body += chunk); |
| 148 response.on("end", () => resolve(body)); |
| 149 } |
| 150 } |
| 151 |
| OLD | NEW |