diff --git a/packager/getDevToolsMiddleware.js b/packager/getDevToolsMiddleware.js index 2c1d693ae..966e47c45 100644 --- a/packager/getDevToolsMiddleware.js +++ b/packager/getDevToolsMiddleware.js @@ -10,9 +10,21 @@ var execFile = require('child_process').execFile; var fs = require('fs'); +var opn = require('opn'); var path = require('path'); -module.exports = function(options) { +function getChromeAppName() { + switch (process.platform) { + case 'darwin': + return 'google chrome'; + case 'win32': + return 'chrome'; + default: + return 'google-chrome'; + } +} + +module.exports = function(options, isDebuggerConnected) { return function(req, res, next) { if (req.url === '/debugger-ui') { var debuggerPath = path.join(__dirname, 'debugger.html'); @@ -29,19 +41,18 @@ module.exports = function(options) { 'If you still need this, please let us know.' ); } else if (req.url === '/launch-chrome-devtools') { + if (isDebuggerConnected()) { + // Dev tools are already open; no need to open another session + res.end('OK'); + return; + } var debuggerURL = 'http://localhost:' + options.port + '/debugger-ui'; - var script = 'launchChromeDevTools.applescript'; console.log('Launching Dev Tools...'); - execFile( - path.join(__dirname, script), [debuggerURL], - function(err, stdout, stderr) { - if (err) { - console.log('Failed to run ' + script, err); - } - console.log(stdout); - console.warn(stderr); + opn(debuggerURL, {app: [getChromeAppName()]}, function(err) { + if (err) { + console.error('Google Chrome exited with error:', err); } - ); + }); res.end('OK'); } else { next(); diff --git a/packager/launchChromeDevTools.applescript b/packager/launchChromeDevTools.applescript deleted file mode 100755 index a83907905..000000000 --- a/packager/launchChromeDevTools.applescript +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env osascript - --- Copyright (c) 2015-present, Facebook, Inc. --- All rights reserved. --- --- This source code is licensed under the BSD-style license found in the --- LICENSE file in the root directory of this source tree. An additional grant --- of patent rights can be found in the PATENTS file in the same directory. - -on run argv - set theURL to item 1 of argv - - tell application "Chrome" - - if (count every window) = 0 then - make new window - end if - - -- Find a tab currently running the debugger - set found to false - set theTabIndex to -1 - repeat with theWindow in every window - set theTabIndex to 0 - repeat with theTab in every tab of theWindow - set theTabIndex to theTabIndex + 1 - if theTab's URL is theURL then - set found to true - exit repeat - end if - end repeat - - if found then - exit repeat - end if - end repeat - - if found then - set index of theWindow to 1 - set theWindow's active tab index to theTabIndex - else - tell window 1 - activate - make new tab with properties {URL:theURL} - end tell - end if - end tell -end run diff --git a/packager/webSocketProxy.js b/packager/webSocketProxy.js index 0562f050a..65c354640 100644 --- a/packager/webSocketProxy.js +++ b/packager/webSocketProxy.js @@ -22,7 +22,7 @@ function attachToServer(server, path) { try { cn.send(JSON.stringify(message)); } catch(e) { - console.warn('WARN: ' + e.message); + // Sometimes this call throws 'not opened' } }); } @@ -57,7 +57,14 @@ function attachToServer(server, path) { }); }); - return wss; + return { + server: wss, + isChromeConnected: () => + clients + .map(ws => ws.upgradeReq.headers['user-agent']) + .filter(Boolean) + .some(userAgent => userAgent.includes('Chrome')) + }; } module.exports = { diff --git a/private-cli/src/server/runServer.js b/private-cli/src/server/runServer.js index 9071dc140..200857c57 100644 --- a/private-cli/src/server/runServer.js +++ b/private-cli/src/server/runServer.js @@ -20,11 +20,13 @@ const path = require('path'); const ReactPackager = require('../../../packager/react-packager'); const statusPageMiddleware = require('../../../packager/statusPageMiddleware.js'); const systraceProfileMiddleware = require('../../../packager/systraceProfileMiddleware.js'); +const webSocketProxy = require('../../../packager/webSocketProxy.js'); function runServer(args, config, readyCallback) { + var wsProxy = null; const app = connect() .use(loadRawBodyMiddleware) - .use(getDevToolsMiddleware(args)) + .use(getDevToolsMiddleware(args, () => wsProxy && wsProxy.isChromeConnected())) .use(openStackFrameInEditorMiddleware) .use(statusPageMiddleware) .use(systraceProfileMiddleware) @@ -39,7 +41,15 @@ function runServer(args, config, readyCallback) { .use(connect.compress()) .use(connect.errorHandler()); - return http.createServer(app).listen(args.port, '::', readyCallback); + const serverInstance = http.createServer(app).listen( + args.port, + '::', + function() { + wsProxy = webSocketProxy.attachToServer(serverInstance, '/debugger-proxy'); + webSocketProxy.attachToServer(serverInstance, '/devtools'); + readyCallback(); + } + ); } function getAppMiddleware(args, config) { diff --git a/private-cli/src/server/server.js b/private-cli/src/server/server.js index 65ffe8acd..8545e24ea 100644 --- a/private-cli/src/server/server.js +++ b/private-cli/src/server/server.js @@ -15,7 +15,6 @@ const parseCommandLine = require('../../../packager/parseCommandLine'); const path = require('path'); const Promise = require('promise'); const runServer = require('./runServer'); -const webSocketProxy = require('../../../packager/webSocketProxy.js'); /** * Starts the React Native Packager Server. @@ -138,12 +137,9 @@ function _server(argv, config, resolve, reject) { } function startServer(args, config) { - const serverInstance = runServer(args, config, () => + runServer(args, config, () => console.log('\nReact packager ready.\n') ); - - webSocketProxy.attachToServer(serverInstance, '/debugger-proxy'); - webSocketProxy.attachToServer(serverInstance, '/devtools'); } function argToArray(arg) {