blob: f33beb5429bce5936e78ab0eee9207e7f8572c2a [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is the shared code for the new (Chrome 37) security interstitials. It is
// used for both SSL interstitials and Safe Browsing interstitials.
let expandedDetails = false;
let keyPressState = 0;
/**
* This allows errors to be skippped by typing a secret phrase into the page.
* @param {string} e The key that was just pressed.
*/
function handleKeypress(e) {
// HTTPS errors are serious and should not be ignored. For testing purposes,
// other approaches are both safer and have fewer side-effects.
// See https://goo.gl/ZcZixP for more details.
const BYPASS_SEQUENCE = window.atob('dGhpc2lzdW5zYWZl');
if (BYPASS_SEQUENCE.charCodeAt(keyPressState) === e.keyCode) {
keyPressState++;
if (keyPressState === BYPASS_SEQUENCE.length) {
sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
keyPressState = 0;
}
} else {
keyPressState = 0;
}
}
/**
* This appends a piece of debugging information to the end of the warning.
* When complete, the caller must also make the debugging div
* (error-debugging-info) visible.
* @param {string} title The name of this debugging field.
* @param {string} value The value of the debugging field.
* @param {boolean=} fixedWidth If true, the value field is displayed fixed
* width.
*/
function appendDebuggingField(title, value, fixedWidth) {
// The values input here are not trusted. Never use innerHTML on these
// values!
const spanTitle = document.createElement('span');
spanTitle.classList.add('debugging-title');
spanTitle.innerText = title + ': ';
const spanValue = document.createElement('span');
spanValue.classList.add('debugging-content');
if (fixedWidth) {
spanValue.classList.add('debugging-content-fixed-width');
}
spanValue.innerText = value;
const pElem = document.createElement('p');
pElem.classList.add('debugging-content');
pElem.appendChild(spanTitle);
pElem.appendChild(spanValue);
$('error-debugging-info').appendChild(pElem);
}
function toggleDebuggingInfo() {
const hiddenDebug = $('error-debugging-info').classList.toggle(HIDDEN_CLASS);
$('error-code').setAttribute('aria-expanded', !hiddenDebug);
}
function setupEvents() {
const overridable = loadTimeData.getBoolean('overridable');
const interstitialType = loadTimeData.getString('type');
const ssl = interstitialType === 'SSL';
const captivePortal = interstitialType === 'CAPTIVE_PORTAL';
const badClock = ssl && loadTimeData.getBoolean('bad_clock');
const lookalike = interstitialType === 'LOOKALIKE';
const billing =
interstitialType === 'SAFEBROWSING' && loadTimeData.getBoolean('billing');
const originPolicy = interstitialType === 'ORIGIN_POLICY';
const blockedInterception = interstitialType === 'BLOCKED_INTERCEPTION';
const legacyTls = interstitialType == 'LEGACY_TLS';
const insecureForm = interstitialType == 'INSECURE_FORM';
const httpsOnly = interstitialType == 'HTTPS_ONLY';
const hidePrimaryButton = loadTimeData.getBoolean('hide_primary_button');
const showRecurrentErrorParagraph = loadTimeData.getBoolean(
'show_recurrent_error_paragraph');
if (ssl || originPolicy || blockedInterception || legacyTls) {
$('body').classList.add(badClock ? 'bad-clock' : 'ssl');
if (loadTimeData.valueExists('errorCode')) {
$('error-code').textContent = loadTimeData.getString('errorCode');
$('error-code').classList.remove(HIDDEN_CLASS);
}
} else if (captivePortal) {
$('body').classList.add('captive-portal');
} else if (billing) {
$('body').classList.add('safe-browsing-billing');
} else if (lookalike) {
$('body').classList.add('lookalike-url');
} else if (insecureForm) {
$('body').classList.add('insecure-form');
} else if (httpsOnly) {
$('body').classList.add('https-only');
} else {
$('body').classList.add('safe-browsing');
// Override the default theme color.
document.querySelector('meta[name=theme-color]').setAttribute('content',
'rgb(206, 52, 38)');
}
$('icon').classList.add('icon');
if (legacyTls) {
$('icon').classList.add('legacy-tls');
}
if (hidePrimaryButton) {
$('primary-button').classList.add(HIDDEN_CLASS);
} else {
$('primary-button').addEventListener('click', function() {
switch (interstitialType) {
case 'CAPTIVE_PORTAL':
sendCommand(SecurityInterstitialCommandId.CMD_OPEN_LOGIN);
break;
case 'SSL':
case 'LEGACY_TLS':
if (badClock) {
sendCommand(SecurityInterstitialCommandId.CMD_OPEN_DATE_SETTINGS);
} else if (overridable) {
sendCommand(SecurityInterstitialCommandId.CMD_DONT_PROCEED);
} else {
sendCommand(SecurityInterstitialCommandId.CMD_RELOAD);
}
break;
case 'SAFEBROWSING':
case 'ORIGIN_POLICY':
sendCommand(SecurityInterstitialCommandId.CMD_DONT_PROCEED);
break;
case 'HTTPS_ONLY':
case 'INSECURE_FORM':
case 'LOOKALIKE':
sendCommand(SecurityInterstitialCommandId.CMD_DONT_PROCEED);
break;
default:
throw 'Invalid interstitial type';
}
});
}
if (lookalike || insecureForm || httpsOnly) {
const proceedButton = 'proceed-button';
$(proceedButton).classList.remove(HIDDEN_CLASS);
$(proceedButton).textContent = loadTimeData.getString('proceedButtonText');
$(proceedButton).addEventListener('click', function(event) {
sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
});
}
if (lookalike) {
// Lookalike interstitials with a suggested URL have a link in the title:
// "Did you mean <link>example.com</link>?". Handle those clicks. Lookalike
// interstitails without a suggested URL don't have this link.
const dontProceedLink = 'dont-proceed-link';
if ($(dontProceedLink)) {
$(dontProceedLink).addEventListener('click', function(event) {
sendCommand(SecurityInterstitialCommandId.CMD_DONT_PROCEED);
});
}
}
if (overridable) {
const overrideElement = billing ? 'proceed-button' : 'proceed-link';
// Captive portal page isn't overridable.
$(overrideElement).addEventListener('click', function(event) {
sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
});
if (ssl) {
$(overrideElement).classList.add('small-link');
} else if (billing) {
$(overrideElement).classList.remove(HIDDEN_CLASS);
$(overrideElement).textContent =
loadTimeData.getString('proceedButtonText');
}
} else if (!ssl) {
$('final-paragraph').classList.add(HIDDEN_CLASS);
}
if (!ssl || !showRecurrentErrorParagraph) {
$('recurrent-error-message').classList.add(HIDDEN_CLASS);
} else {
$('body').classList.add('showing-recurrent-error-message');
}
if ($('diagnostic-link')) {
$('diagnostic-link').addEventListener('click', function(event) {
sendCommand(SecurityInterstitialCommandId.CMD_OPEN_DIAGNOSTIC);
});
}
if ($('learn-more-link')) {
$('learn-more-link').addEventListener('click', function(event) {
sendCommand(SecurityInterstitialCommandId.CMD_OPEN_HELP_CENTER);
});
}
if (captivePortal || billing || lookalike || insecureForm || httpsOnly) {
// Captive portal, billing, lookalike pages, insecure form, and
// HTTPS only mode interstitials don't have details buttons.
$('details-button').classList.add('hidden');
} else {
$('details-button')
.setAttribute(
'aria-expanded', !$('details').classList.contains(HIDDEN_CLASS));
$('details-button').addEventListener('click', function(event) {
const hiddenDetails = $('details').classList.toggle(HIDDEN_CLASS);
$('details-button').setAttribute('aria-expanded', !hiddenDetails);
if (mobileNav) {
// Details appear over the main content on small screens.
$('main-content').classList.toggle(HIDDEN_CLASS, !hiddenDetails);
} else {
$('main-content').classList.remove(HIDDEN_CLASS);
}
$('details-button').innerText = hiddenDetails ?
loadTimeData.getString('openDetails') :
loadTimeData.getString('closeDetails');
if (!expandedDetails) {
// Record a histogram entry only the first time that details is opened.
sendCommand(SecurityInterstitialCommandId.CMD_SHOW_MORE_SECTION);
expandedDetails = true;
}
});
}
if ($('report-error-link')) {
$('report-error-link').addEventListener('click', function(event) {
sendCommand(SecurityInterstitialCommandId.CMD_REPORT_PHISHING_ERROR);
});
}
if (lookalike) {
console.log(
'Chrome has determined that ' +
loadTimeData.getString('lookalikeRequestHostname') +
' could be fake or fraudulent.\n\n' +
'If you believe this is shown in error please visit ' +
'https://g.co/chrome/lookalike-warnings');
}
preventDefaultOnPoundLinkClicks();
setupExtendedReportingCheckbox();
setupEnhancedProtectionMessage();
setupSSLDebuggingInfo();
document.addEventListener('keypress', handleKeypress);
}
document.addEventListener('DOMContentLoaded', setupEvents);