From ec065b97fc39e700c0f0333ea02e5f1a4c4be7a3 Mon Sep 17 00:00:00 2001 From: yan Date: Fri, 30 Sep 2016 16:34:08 -0700 Subject: [PATCH] restore noscript allow once & allow temp when noscript is globally on if noscript is on for a site only instead of globally, this feature is not available because it is more complicated to implement and because it is less useful for privacy (since changing shield settings is not possible in private tabs anyway). fix https://github.com/brave/browser-laptop/issues/2745 fix https://github.com/brave/browser-laptop/issues/3835 Auditors: @ayumi Test Plan: 1. turn on 'block scripts' in preferences 2. go to apple.com, click noscript icon, choose 'allow'. verify that scripts are allowed. 3. open private tab, go to bing.com, click noscript icon, verify that 'allow this time'is the only option. click it and verify that scripts are allowed. 4. navigate the private tab to google.com and then back to bing.com. verify that scripts are blocked on both sites. 5. go to google.com in a regular tab and choose 'allow until restart'. verify that scripts are allowed. 6. restart browser and go to about:preferences#shields. verify that only apple.com is listed as an exception. --- .../locales/en-US/preferences.properties | 3 +- app/sessionStore.js | 10 ++++- docs/state.md | 3 +- js/about/preferences.js | 10 ++++- js/components/frame.js | 19 +++++---- js/components/main.js | 3 +- js/components/noScriptInfo.js | 42 ++++++++++++------- js/constants/messages.js | 2 - js/state/contentSettings.js | 5 +-- 9 files changed, 63 insertions(+), 34 deletions(-) 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, '*',