Skip to content

Commit

Permalink
Geolocation audit: warn if page is non-secure origin (#1679)
Browse files Browse the repository at this point in the history
  • Loading branch information
ebidel authored and brendankenny committed Feb 10, 2017
1 parent 0cb9209 commit 5503505
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 9 deletions.
Expand Up @@ -37,12 +37,20 @@ class GeolocationOnStart extends Gatherer {
* @return {!Promise<!Array<{url: string, line: number, col: number}>>}
*/
afterPass(options) {
return options.driver.queryPermissionState('geolocation')
return options.driver.evaluateAsync('(function(){return window.isSecureContext;})()')
.then(isSecureContext => {
if (!isSecureContext) {
throw new Error('Unable to determine if the Geolocation permission requested on page ' +
'load because the page is not hosted on a secure origin. The Geolocation API ' +
'requires an https URL.');
}
})
.then(_ => options.driver.queryPermissionState('geolocation'))
.then(state => {
if (state === 'granted' || state === 'denied') {
throw new Error('Unable to determine if this permission was requested on page load ' +
'because it had already been set. Try resetting the permission and running ' +
'Lighthouse again.');
throw new Error('Unable to determine if the Geolocation permission was ' +
`requested on page load because it was already ${state}. ` +
'Try resetting the permission and running Lighthouse again.');
}

return this.collectCurrentPosUsage().then(results => {
Expand Down
Expand Up @@ -34,9 +34,9 @@ class NotificationOnStart extends Gatherer {
return options.driver.queryPermissionState('notifications')
.then(state => {
if (state === 'granted' || state === 'denied') {
throw new Error('Unable to determine if this permission was requested on page load ' +
'because it had already been set. Try resetting the permission and running ' +
'Lighthouse again.');
throw new Error('Unable to determine if the Notification permission was ' +
`requested on page load because it was already ${state}. ` +
'Try resetting the permission and running Lighthouse again.');
}

return this.collectNotificationUsage();
Expand Down
Expand Up @@ -24,8 +24,8 @@ describe('UX: geolocation audit', () => {
it('fails when geolocation has been automatically requested', () => {
const auditResult = GeolocationOnStartAudit.audit({
GeolocationOnStart: [
{url: 'http://different.com/two', line: 2, col: 2},
{url: 'http://example2.com/two', line: 2, col: 22}
{url: 'https://different.com/two', line: 2, col: 2},
{url: 'https://example2.com/two', line: 2, col: 22}
],
});
assert.equal(auditResult.rawValue, false);
Expand Down
@@ -0,0 +1,68 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';

/* eslint-env mocha */

const GeolocationOnStart =
require('../../../../gather/gatherers/dobetterweb/geolocation-on-start');
const assert = require('assert');

describe('Geolocation permission on page load', () => {
let gatherer;

const opts = {
url: 'http://localhost:8080',
driver: {
evaluateAsync() {
return Promise.resolve(false);
},
queryPermissionState() {
return Promise.resolve('granted');
},
captureFunctionCallSites() {
return Promise.resolve([]);
}
}
};

beforeEach(() => {
gatherer = new GeolocationOnStart();
});

it('throws when the URL is not a secure context', () => {
gatherer.beforePass(opts);
return gatherer.afterPass(opts).then(_ => {
assert.ok(false);
}).catch(err => {
assert.ok(err.message.match(/Geolocation API requires an https/));
assert.ok(true);
});
});

it('throws when the permission has already been granted/denied', () => {
opts.driver.evaluateAsync = _ => Promise.resolve(true);

gatherer.beforePass(opts);
return gatherer.afterPass(opts).then(_ => {
assert.ok(false);
}).catch(err => {
assert.ok(err.message.match(/already granted/));
assert.ok(err.message.match(/Try resetting the permission/));
assert.ok(true);
});
});
});

0 comments on commit 5503505

Please sign in to comment.