diff --git a/app/extensions/brave/locales/en-US/preferences.properties b/app/extensions/brave/locales/en-US/preferences.properties index 0b26dcad5ea..f7138e0e8fe 100644 --- a/app/extensions/brave/locales/en-US/preferences.properties +++ b/app/extensions/brave/locales/en-US/preferences.properties @@ -192,7 +192,8 @@ protocolRegistrationPermission=Protocol registration shieldsUp=All Brave Shields ledgerPaymentsShown=Brave Payments flash=Run Adobe Flash Player -flashAllowOnce=Allow once +allowOnce=Allow once +allowUntilRestart=Allow until restart flashAllowAlways=Allow until {{time}} alwaysAllow=Always allow alwaysDeny=Always deny diff --git a/app/sessionStore.js b/app/sessionStore.js index 8d14d406914..e7e3b206625 100644 --- a/app/sessionStore.js +++ b/app/sessionStore.js @@ -248,15 +248,23 @@ module.exports.cleanAppData = (data, isShutdown) => { data.perWindowState.forEach((perWindowState) => module.exports.cleanPerWindowData(perWindowState, isShutdown)) } - // Delete expired Flash approvals + // Delete expired Flash and NoScript allow-once approvals let now = Date.now() for (var host in data.siteSettings) { let expireTime = data.siteSettings[host].flash if (typeof expireTime === 'number' && expireTime < now) { delete data.siteSettings[host].flash } + let noScript = data.siteSettings[host].noScript + if (typeof noScript === 'number') { + delete data.siteSettings[host].noScript + } // Don't write runInsecureContent to session delete data.siteSettings[host].runInsecureContent + // If the site setting is empty, delete it for privacy + if (Object.keys(data.siteSettings[host]).length === 0) { + delete data.siteSettings[host] + } } if (data.sites) { const clearHistory = isShutdown && getSetting(settings.SHUTDOWN_CLEAR_HISTORY) === true diff --git a/docs/state.md b/docs/state.md index 1bdca0b1dfd..db6cc0208bb 100644 --- a/docs/state.md +++ b/docs/state.md @@ -68,7 +68,7 @@ AppStore adControl: string, // (showBraveAds | blockAds | allowAdsAndTracking) cookieControl: string, // (block3rdPartyCookie | allowAllCookies) safeBrowsing: boolean, - noScript: boolean, + noScript: (number|boolean), // true = block scripts, false = allow, 0 = allow once, 1 = allow until restart httpsEverywhere: boolean, fingerprintingProtection: boolean, flash: (number|boolean), // approval expiration time if allowed, false if never allow @@ -79,6 +79,7 @@ AppStore }, temporarySiteSettings: { // Same as above but never gets written to disk + // XXX: This was intended for Private Browsing but is currently unused. }, visits: [{ location: string, diff --git a/js/about/preferences.js b/js/about/preferences.js index 9cd22297284..4978e8aa1a9 100644 --- a/js/about/preferences.js +++ b/js/about/preferences.js @@ -68,7 +68,7 @@ const braveryPermissionNames = { 'safeBrowsing': ['boolean'], 'httpsEverywhere': ['boolean'], 'fingerprintingProtection': ['boolean'], - 'noScript': ['boolean'] + 'noScript': ['boolean', 'number'] } const changeSetting = (cb, key, e) => { @@ -1049,7 +1049,7 @@ class SitePermissionsPage extends React.Component { if (name === 'flash') { if (granted === 1) { // Flash is allowed just one time - statusText = 'flashAllowOnce' + statusText = 'allowOnce' } else if (granted === false) { // Flash installer is never intercepted statusText = 'alwaysDeny' @@ -1060,6 +1060,12 @@ class SitePermissionsPage extends React.Component { time: new Date(granted).toLocaleString() } } + } else if (name === 'noScript' && typeof granted === 'number') { + if (granted === 1) { + statusText = 'allowUntilRestart' + } else if (granted === 0) { + statusText = 'allowOnce' + } } else if (typeof granted === 'string') { statusText = granted } else if (!this.props.defaults) { diff --git a/js/components/frame.js b/js/components/frame.js index b8af2b080cf..c9e5fb63d06 100644 --- a/js/components/frame.js +++ b/js/components/frame.js @@ -200,21 +200,26 @@ class Frame extends ImmutableComponent { return false } - expireFlash (origin) { + expireContentSettings (origin) { // Expired Flash settings should be deleted when the webview is - // navigated or closed. + // navigated or closed. Same for NoScript's allow-once option. const activeSiteSettings = getSiteSettingsForHostPattern(this.props.allSiteSettings, origin) - if (activeSiteSettings && typeof activeSiteSettings.get('flash') === 'number') { + if (!activeSiteSettings) { + return + } + if (typeof activeSiteSettings.get('flash') === 'number') { if (activeSiteSettings.get('flash') < Date.now()) { - // Expired entry. Remove it. appActions.removeSiteSetting(origin, 'flash') } } + if (activeSiteSettings.get('noScript') === 0) { + appActions.removeSiteSetting(origin, 'noScript') + } } componentWillUnmount () { - this.expireFlash(this.origin) + this.expireContentSettings(this.origin) } updateWebview (cb, newSrc) { @@ -381,10 +386,10 @@ class Frame extends ImmutableComponent { this.updateAboutDetails() } - // For cross-origin navigation, clear temp Flash approvals + // For cross-origin navigation, clear temp approvals const prevOrigin = siteUtil.getOrigin(prevProps.location) if (this.origin !== prevOrigin) { - this.expireFlash(prevOrigin) + this.expireContentSettings(prevOrigin) } if (this.props.src !== prevProps.src) { diff --git a/js/components/main.js b/js/components/main.js index fff3934643f..c6571783102 100644 --- a/js/components/main.js +++ b/js/components/main.js @@ -620,7 +620,7 @@ class Main extends ImmutableComponent { } enableNoScript (settings) { - return siteSettings.activeSettings(settings, this.props.appState, appConfig).noScript + return siteSettings.activeSettings(settings, this.props.appState, appConfig).noScript === true } onCloseFrame (activeFrameProps) { @@ -1008,6 +1008,7 @@ class Main extends ImmutableComponent { { noScriptIsVisible ? : null } diff --git a/js/components/noScriptInfo.js b/js/components/noScriptInfo.js index 0f3c898e25a..b34da689e6b 100644 --- a/js/components/noScriptInfo.js +++ b/js/components/noScriptInfo.js @@ -21,24 +21,41 @@ class NoScriptInfo extends ImmutableComponent { return siteUtil.getOrigin(this.props.frameProps.get('location')) } + get isPrivate () { + return this.props.frameProps.get('isPrivate') + } + reload () { ipc.emit(messages.SHORTCUT_ACTIVE_FRAME_CLEAN_RELOAD) } - onAllowOnce () { + onAllow (setting) { if (!this.origin) { return } - ipc.send(messages.TEMPORARY_ALLOW_SCRIPTS, this.origin) + appActions.changeSiteSetting(this.origin, 'noScript', setting) this.reload() } - onAllow (temp) { - if (!this.origin) { - return + get buttons () { + if (!this.props.noScriptGlobalEnabled) { + // NoScript is not turned on globally + return
+ } else { + return
+
+
+ } + } - appActions.changeSiteSetting(this.origin, 'noScript', false, temp) - this.reload() } render () { @@ -50,21 +67,14 @@ class NoScriptInfo extends ImmutableComponent {
-
- { - // TODO: restore the allow-once button - // TODO: If this is a private tab, this should only allow scripts - // temporarily. Depends on #1824 -
+ {this.buttons}
} } NoScriptInfo.propTypes = { + noScriptGlobalEnabled: React.PropTypes.bool, frameProps: React.PropTypes.object, onHide: React.PropTypes.func } diff --git a/js/constants/messages.js b/js/constants/messages.js index 20bc5b1607a..4d071b64087 100644 --- a/js/constants/messages.js +++ b/js/constants/messages.js @@ -137,8 +137,6 @@ const messages = { HTTPSE_RULE_APPLIED: _, /** @arg {string} name of ruleset file, @arg {Object} details of rewritten request */ // Extensions NEW_POPUP_WINDOW: _, - // NoScript - TEMPORARY_ALLOW_SCRIPTS: _, /** @arg {string} origin to allow scripts on */ // Localization LANGUAGE: _, /** @arg {string} langCode, @arg {Array} availableLanguages */ REQUEST_LANGUAGE: _, diff --git a/js/state/contentSettings.js b/js/state/contentSettings.js index 014233ac2d6..5c79ee2e8ad 100644 --- a/js/state/contentSettings.js +++ b/js/state/contentSettings.js @@ -130,10 +130,9 @@ const getContentSettingsFromSiteSettings = (appState) => { // We do 2 passes for setting content settings. On the first pass we consider all shield types. for (let hostPattern in hostSettings) { let hostSetting = hostSettings[hostPattern] - if (typeof hostSetting.noScript === 'boolean') { - // TODO: support temporary override + if (['number', 'boolean'].includes(typeof hostSetting.noScript)) { addContentSettings(contentSettings.javascript, hostPattern, '*', - hostSetting.noScript ? 'block' : 'allow') + hostSetting.noScript === true ? 'block' : 'allow') } if (typeof hostSetting.runInsecureContent === 'boolean') { addContentSettings(contentSettings.runInsecureContent, hostPattern, '*',