Skip to content

Commit dcf76e6

Browse files
esprehnIgorMinar
authored andcommitted
Provide better sandbox error messages, and disallow running from file:// URLs
1 parent 56a3d52 commit dcf76e6

File tree

4 files changed

+48
-26
lines changed

4 files changed

+48
-26
lines changed

css/angular-scenario.css

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ body {
88
font-size: 14px;
99
}
1010

11+
#system-error {
12+
font-size: 1.5em;
13+
text-align: center;
14+
}
15+
1116
#json, #xml {
1217
display: none;
1318
}

src/scenario/Application.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ angular.scenario.Application.prototype.getWindow_ = function() {
4141
* Checks that a URL would return a 2xx success status code. Callback is called
4242
* with no arguments on success, or with an error on failure.
4343
*
44-
* Warning: This requires the server to be able to respond to HEAD requests
44+
* Warning: This requires the server to be able to respond to HEAD requests
4545
* and not modify the state of your application.
4646
*
4747
* @param {string} url Url to check
@@ -69,7 +69,7 @@ angular.scenario.Application.prototype.checkUrlStatus_ = function(url, callback)
6969
/**
7070
* Changes the location of the frame.
7171
*
72-
* @param {string} url The URL. If it begins with a # then only the
72+
* @param {string} url The URL. If it begins with a # then only the
7373
* hash of the page is changed.
7474
* @param {Function} loadFn function($window, $document) Called when frame loads.
7575
* @param {Function} errorFn function(error) Called if any error when loading.
@@ -79,8 +79,8 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF
7979
var frame = this.getFrame_();
8080
//TODO(esprehn): Refactor to use rethrow()
8181
errorFn = errorFn || function(e) { throw e; };
82-
if (/^file:\/\//.test(url)) {
83-
errorFn('Sandbox Error: Cannot load file:// URL.');
82+
if (url === 'about:blank') {
83+
errorFn('Sandbox Error: Navigating to about:blank is not allowed.');
8484
} else if (url.charAt(0) === '#') {
8585
url = frame.attr('src').split('#')[0] + url;
8686
frame.attr('src', url);

src/scenario/Scenario.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ angular.scenario.matcher = angular.scenario.matcher || function(name, fn) {
9393
* @param {Object} config Config options
9494
*/
9595
function angularScenarioInit($scenario, config) {
96+
var href = window.location.href;
9697
var body = _jQuery(document.body);
9798
var output = [];
9899

@@ -108,6 +109,15 @@ function angularScenarioInit($scenario, config) {
108109
}
109110
});
110111

112+
if (!/^http/.test(href) && !/^https/.test(href)) {
113+
body.append('<p id="system-error"></p>');
114+
body.find('#system-error').text(
115+
'Scenario runner must be run using http or https. The protocol ' +
116+
href.split(':')[0] + ':// is not supported.'
117+
);
118+
return;
119+
}
120+
111121
var appFrame = body.append('<div id="application"></div>').find('#application');
112122
var application = new angular.scenario.Application(appFrame);
113123

@@ -134,7 +144,7 @@ function angularScenarioInit($scenario, config) {
134144
*
135145
* @param {Array} list list to iterate over
136146
* @param {Function} iterator Callback function(value, continueFunction)
137-
* @param {Function} done Callback function(error, result) called when
147+
* @param {Function} done Callback function(error, result) called when
138148
* iteration finishes or an error occurs.
139149
*/
140150
function asyncForEach(list, iterator, done) {

test/scenario/ApplicationSpec.js

+28-21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
describe('angular.scenario.Application', function() {
2+
var $window;
23
var app, frames;
34

45
function callLoadHandlers(app) {
@@ -52,61 +53,67 @@ describe('angular.scenario.Application', function() {
5253
});
5354

5455
it('should use a new iframe each time', function() {
55-
app.navigateTo('about:blank');
56+
app.navigateTo('http://localhost/');
5657
var frame = app.getFrame_();
5758
frame.attr('test', true);
58-
app.navigateTo('about:blank');
59+
app.navigateTo('http://localhost/');
5960
expect(app.getFrame_().attr('test')).toBeFalsy();
6061
});
6162

6263
it('should call error handler if document not accessible', function() {
64+
var called;
6365
app.getWindow_ = function() {
6466
return {};
6567
};
66-
app.navigateTo('about:blank', angular.noop, function(error) {
68+
app.navigateTo('http://localhost/', angular.noop, function(error) {
6769
expect(error).toMatch(/Sandbox Error/);
70+
called = true;
6871
});
6972
callLoadHandlers(app);
73+
expect(called).toBeTruthy();
7074
});
7175

72-
it('should call error handler if using file:// URL', function() {
73-
app.navigateTo('file://foo/bar.txt', angular.noop, function(error) {
76+
it('should call error handler if navigating to about:blank', function() {
77+
var called;
78+
app.navigateTo('about:blank', angular.noop, function(error) {
7479
expect(error).toMatch(/Sandbox Error/);
80+
called = true;
7581
});
82+
expect(called).toBeTruthy();
7683
});
7784

7885
it('should call error handler if status check fails', function() {
7986
app.checkUrlStatus_ = function(url, callback) {
8087
callback.call(this, 'Example Error');
8188
};
82-
app.navigateTo('about:blank', angular.noop, function(error) {
89+
app.navigateTo('http://localhost/', angular.noop, function(error) {
8390
expect(error).toEqual('Example Error');
8491
});
8592
});
8693

8794
it('should hide old iframes and navigate to about:blank', function() {
88-
app.navigateTo('about:blank#foo');
89-
app.navigateTo('about:blank#bar');
95+
app.navigateTo('http://localhost/#foo');
96+
app.navigateTo('http://localhost/#bar');
9097
var iframes = frames.find('iframe');
9198
expect(iframes.length).toEqual(2);
9299
expect(iframes[0].src).toEqual('about:blank');
93-
expect(iframes[1].src).toEqual('about:blank#bar');
100+
expect(iframes[1].src).toEqual('http://localhost/#bar');
94101
expect(_jQuery(iframes[0]).css('display')).toEqual('none');
95102
});
96103

97104
it('should URL update description bar', function() {
98-
app.navigateTo('about:blank');
105+
app.navigateTo('http://localhost/');
99106
var anchor = frames.find('> h2 a');
100-
expect(anchor.attr('href')).toEqual('about:blank');
101-
expect(anchor.text()).toEqual('about:blank');
107+
expect(anchor.attr('href')).toEqual('http://localhost/');
108+
expect(anchor.text()).toEqual('http://localhost/');
102109
});
103110

104111
it('should call onload handler when frame loads', function() {
105112
var called;
106113
app.getWindow_ = function() {
107114
return {document: {}};
108115
};
109-
app.navigateTo('about:blank', function($window, $document) {
116+
app.navigateTo('http://localhost/', function($window, $document) {
110117
called = true;
111118
});
112119
callLoadHandlers(app);
@@ -130,7 +137,7 @@ describe('angular.scenario.Application', function() {
130137
notifyWhenNoOutstandingRequests: function(fn) {
131138
handlers.push(fn);
132139
}
133-
}
140+
};
134141
};
135142
app.getWindow_ = function() {
136143
return testWindow;
@@ -173,35 +180,35 @@ describe('angular.scenario.Application', function() {
173180
expect(options.type).toEqual('HEAD');
174181
expect(options.url).toEqual('http://www.google.com/');
175182
});
176-
183+
177184
it('should call error handler if status code is less than 200', function() {
178185
var finished;
179186
response.status = 199;
180187
response.statusText = 'Error Message';
181-
app.navigateTo('about:blank', angular.noop, function(error) {
188+
app.navigateTo('http://localhost/', angular.noop, function(error) {
182189
expect(error).toEqual('199 Error Message');
183190
finished = true;
184191
});
185192
expect(finished).toBeTruthy();
186193
});
187-
194+
188195
it('should call error handler if status code is greater than 299', function() {
189196
var finished;
190197
response.status = 300;
191198
response.statusText = 'Error';
192-
app.navigateTo('about:blank', angular.noop, function(error) {
199+
app.navigateTo('http://localhost/', angular.noop, function(error) {
193200
expect(error).toEqual('300 Error');
194201
finished = true;
195202
});
196203
expect(finished).toBeTruthy();
197204
});
198-
205+
199206
it('should call error handler if status code is 0 for sandbox error', function() {
200207
var finished;
201208
response.status = 0;
202209
response.statusText = '';
203-
app.navigateTo('about:blank', angular.noop, function(error) {
204-
expect(error).toEqual('Sandbox Error: Cannot access about:blank');
210+
app.navigateTo('http://localhost/', angular.noop, function(error) {
211+
expect(error).toEqual('Sandbox Error: Cannot access http://localhost/');
205212
finished = true;
206213
});
207214
expect(finished).toBeTruthy();

0 commit comments

Comments
 (0)