UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

237 lines (189 loc) 5.99 kB
var fs = require('fs'); var path = require('path'); var dataUri = require('strong-data-uri'); var inherits = require('util').inherits; var EventEmitter = require('events').EventEmitter; var injection = require.resolve('./Injections/NetworkAgent'); function NetworkAgent(config, session) { try { this._noInject = config.inject === false || config.inject.network === false; } catch (e) { this._noInject = false; } this._debuggerClient = session.debuggerClient; this._frontendClient = session.frontendClient; this._injectorClient = session.injectorClient; this._capturingEnabled = true; this._dataStorage = {}; if (!this._noInject) this._injectorClient.on('inject', this._inject.bind(this)); } NetworkAgent.prototype._inject = function() { this._translateEventToFrontend( 'requestWillBeSent', 'responseReceived', 'dataReceived', 'loadingFinished', 'loadingFailed' ); this._handleEvent('_requestWillBeSent', this._registerInDataStorage.bind(this)); this._handleEvent('_dataReceived', this._saveToDataStorage.bind(this)); this._handleEvent('_loadingFinished', this._constructRequestData.bind(this)); this._handleEvent('_loadingFailed', this._dumpRequestData.bind(this)); this._injectorClient.injection( function(require, debug, options) { require(options.injection)(require, debug, options); }, { injection: injection }, function(error, result) { this._injected = !error; if (error) return this._frontendClient.sendLogToConsole('error', error.message || error); }.bind(this) ); }; /** * @param {...string} eventNames */ NetworkAgent.prototype._translateEventToFrontend = function(eventNames) { Array.prototype.forEach.call(arguments, function(event) { event = 'Network.' + event; this._debuggerClient.on(event, function(message) { this._frontendClient.sendEvent(event, message); }.bind(this)); }, this); }; NetworkAgent.prototype._handleEvent = function(event, handle) { event = 'Network.' + event; this._debuggerClient.on(event, handle); }; NetworkAgent.prototype._registerInDataStorage = function(message) { if (!this._capturingEnabled) return; var requestId = message.requestId; if (this._dataStorage[requestId]) throw new Error('Data storage for request #' + requestId + ' already exists'); this._dataStorage[requestId] = new ResponseData(); }; NetworkAgent.prototype._saveToDataStorage = function(message) { if (!this._capturingEnabled) return; var responseData = this._dataStorage[message.requestId]; if (!responseData) return; responseData.push(message.data); }; NetworkAgent.prototype._constructRequestData = function(message) { if (!this._capturingEnabled) return; var responseData = this._dataStorage[message.requestId]; if (!responseData) return; responseData.finish(); }; NetworkAgent.prototype._dumpRequestData = function(message) { if (!this._capturingEnabled) return; var responseData = this._dataStorage[message.requestId]; if (!responseData) return; responseData.dump(); }; NetworkAgent.prototype.getResponseBody = function(params, done) { var responseData = this._dataStorage[params.requestId]; if (!responseData) return done(new Error('There is no data for request #' + params.requestId)); var result = { base64Encoded: false, body: null }; if (!responseData.finished) { responseData.once('finish', function(data) { result.body = data; done(null, result); }); } else { process.nextTick(function() { result.body = responseData.data; done(null, result); }); } }; NetworkAgent.prototype._setCapturingEnabled = function(params, done) { this._capturingEnabled = params.enabled; done(); }; NetworkAgent.prototype._clearCapturedData = function(params, done) { Object.keys(this._dataStorage).forEach(function(key) { this._dataStorage[key].dispose(); }, this); this._dataStorage = {}; done(); }; NetworkAgent.prototype.loadResourceForFrontend = function(params, done) { if (/^data:/.test(params.url)) { try { done(null, { statusCode: 200, headers: {}, content: dataUri.decode(params.url).toString('ascii') }); } catch (err) { done(err); } return; } loadFileResource(params, done); }; function loadFileResource(params, done) { var match = params.url.match(/^file:\/\/(.*)$/); if (!match) { return done( 'URL scheme not supported by Network.loadResourceForFrontend: ' + params.url); } var filePath = match[1]; if (process.platform == 'win32') { // On Windows, we should receive '/C:/path/to/file'. if (!/^\/[a-zA-Z]:\//.test(filePath)) { return done('Invalid windows path: ' + filePath); } // Remove leading '/' and replace all other '/' with '\' filePath = filePath.slice(1).split('/').join(path.sep); } // ensure there are no ".." in the path filePath = path.normalize(filePath); fs.readFile( filePath, { encoding: 'utf8' }, function(err, content) { if (err) return done(err); done(null, { statusCode: 200, headers: {}, content: content }); } ); } NetworkAgent.prototype.setUserAgentOverride = function(params, done) { done(null, {}); }; function ResponseData(id) { this.data = []; this.finished = false; } inherits(ResponseData, EventEmitter); ResponseData.prototype.finish = function() { if (this.finished) return; this.data = this.data.join(''); this.finished = true; this.emit('finish', this.data); }; ResponseData.prototype.dump = function() { if (this.finished) return; this.data = ''; this.finished = true; this.emit('finish', this.data); }; ResponseData.prototype.push = function(chunk) { this.data.push(chunk); }; ResponseData.prototype.dispose = function() { if (!this.finished) this.dump(); this.removeAllListeners(); }; exports.NetworkAgent = NetworkAgent;