|
| 1 | +// ==UserScript== |
| 2 | +// @name Hit Enter in Urlbar to Refresh |
| 3 | +// @version 1.0 |
| 4 | +// @author aminomancer |
| 5 | +// @homepage https://github.com/aminomancer/uc.css.js |
| 6 | +// @description Due to Firefox's named anchor navigation system, you can't |
| 7 | +// always refresh a page by clicking the urlbar and hitting Enter. If there's a |
| 8 | +// hash mark `#` in the URL, Firefox interprets this as a URL fragment and tries |
| 9 | +// to navigate between anchors within the document, by setting the scroll |
| 10 | +// position and not reloading the document. This works great when clicking links |
| 11 | +// on pages that link to other parts of the page, and when typing new fragments |
| 12 | +// after the hash in the URL. But what if you just want to reload the page? If |
| 13 | +// there is no hash, then hitting Enter will always reload the page. But if |
| 14 | +// there is a hash, hitting Enter will not reload the page, even though the |
| 15 | +// current URL is the same as the typed URL. Bug 1766145 on Bugzilla may resolve |
| 16 | +// that problem, but in the meantime, this script will work. With this |
| 17 | +// installed, hitting Enter in the urlbar when the typed value is the same as |
| 18 | +// the current browser's URL will cause a page reload. If you change the value |
| 19 | +// in the urlbar at all, this won't have any effect. It only comes into play |
| 20 | +// when the URL values are 100% identical. This just ensures that if you click |
| 21 | +// into the urlbar and hit Enter, without doing anything else, it will always |
| 22 | +// work the same — whether there's a hash in the URL or not. |
| 23 | +// @license This Source Code Form is subject to the terms of the Creative Commons Attribution-NonCommercial-ShareAlike International License, v. 4.0. If a copy of the CC BY-NC-SA 4.0 was not distributed with this file, You can obtain one at http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. |
| 24 | +// ==/UserScript== |
| 25 | + |
| 26 | +(function () { |
| 27 | + function init() { |
| 28 | + let source = gURLBar._loadURL.toSource(); |
| 29 | + if (source.startsWith("(function")) return; |
| 30 | + eval( |
| 31 | + `gURLBar._loadURL = function ` + |
| 32 | + source |
| 33 | + .replace( |
| 34 | + /(SitePermissions\.clearTemporaryBlockPermissions\(browser\)\;)/, |
| 35 | + `$1\n params.isReload = true;` |
| 36 | + ) |
| 37 | + .replace( |
| 38 | + /(this\.window\.openTrustedLinkIn\(url, openUILinkWhere, params\);)/, |
| 39 | + `if (params.isReload) {\n delete params.isReload;\n this.openLinkWithForceReload(url, params);\n } else {\n $1\n }` |
| 40 | + ) |
| 41 | + ); |
| 42 | + /** |
| 43 | + * Open a url in the current tab and ensure it reloads rather than anchor navigation. |
| 44 | + * |
| 45 | + * @param {string} url |
| 46 | + * The URL to open. |
| 47 | + * @param {object} params |
| 48 | + * The parameters related to how and where the result will be opened. |
| 49 | + * Further supported paramters are listed in utilityOverlay.js#openUILinkIn. |
| 50 | + */ |
| 51 | + gURLBar.openLinkWithForceReload = function (url, params = {}) { |
| 52 | + if (!url) { |
| 53 | + return; |
| 54 | + } |
| 55 | + if (!params.triggeringPrincipal) { |
| 56 | + params.triggeringPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); |
| 57 | + } |
| 58 | + params.fromChrome = params.fromChrome ?? true; |
| 59 | + |
| 60 | + let aAllowThirdPartyFixup = params.allowThirdPartyFixup; |
| 61 | + let aPostData = params.postData; |
| 62 | + let aReferrerInfo = params.referrerInfo |
| 63 | + ? params.referrerInfo |
| 64 | + : new this.window.ReferrerInfo(Ci.nsIReferrerInfo.EMPTY, true, null); |
| 65 | + let aAllowInheritPrincipal = !!params.allowInheritPrincipal; |
| 66 | + let aForceAllowDataURI = params.forceAllowDataURI; |
| 67 | + let aIsPrivate = params.private; |
| 68 | + let aForceNonPrivate = params.forceNonPrivate; |
| 69 | + let aAllowPopups = !!params.allowPopups; |
| 70 | + let aUserContextId = params.userContextId; |
| 71 | + let aIndicateErrorPageLoad = params.indicateErrorPageLoad; |
| 72 | + let aPrincipal = params.originPrincipal; |
| 73 | + let aStoragePrincipal = params.originStoragePrincipal; |
| 74 | + let aTriggeringPrincipal = params.triggeringPrincipal; |
| 75 | + let aCsp = params.csp; |
| 76 | + let aForceAboutBlankViewerInCurrent = params.forceAboutBlankViewerInCurrent; |
| 77 | + let aResolveOnContentBrowserReady = params.resolveOnContentBrowserCreated; |
| 78 | + |
| 79 | + let w = |
| 80 | + params.targetBrowser?.ownerGlobal || |
| 81 | + this.window.getTopWin({ forceNonPrivate: aForceNonPrivate }); |
| 82 | + |
| 83 | + if (!w) { |
| 84 | + return; |
| 85 | + } |
| 86 | + |
| 87 | + function useOAForPrincipal(principal) { |
| 88 | + if (principal && principal.isContentPrincipal) { |
| 89 | + let attrs = { |
| 90 | + userContextId: aUserContextId, |
| 91 | + privateBrowsingId: |
| 92 | + aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)), |
| 93 | + firstPartyDomain: principal.originAttributes.firstPartyDomain, |
| 94 | + }; |
| 95 | + return Services.scriptSecurityManager.principalWithOA(principal, attrs); |
| 96 | + } |
| 97 | + return principal; |
| 98 | + } |
| 99 | + aPrincipal = useOAForPrincipal(aPrincipal); |
| 100 | + aStoragePrincipal = useOAForPrincipal(aStoragePrincipal); |
| 101 | + aTriggeringPrincipal = useOAForPrincipal(aTriggeringPrincipal); |
| 102 | + |
| 103 | + w.focus(); |
| 104 | + |
| 105 | + let uriObj; |
| 106 | + let targetBrowser = params.targetBrowser || w.gBrowser.selectedBrowser; |
| 107 | + try { |
| 108 | + uriObj = Services.io.newURI(url); |
| 109 | + } catch (e) {} |
| 110 | + |
| 111 | + let flags = Ci.nsIWebNavigation.LOAD_FLAGS_IS_REFRESH; |
| 112 | + if (aAllowThirdPartyFixup) { |
| 113 | + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; |
| 114 | + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; |
| 115 | + } |
| 116 | + if (!aAllowInheritPrincipal) { |
| 117 | + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL; |
| 118 | + } |
| 119 | + if (aAllowPopups) { |
| 120 | + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_POPUPS; |
| 121 | + } |
| 122 | + if (aIndicateErrorPageLoad) { |
| 123 | + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ERROR_LOAD_CHANGES_RV; |
| 124 | + } |
| 125 | + if (aForceAllowDataURI) { |
| 126 | + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI; |
| 127 | + } |
| 128 | + let { URI_INHERITS_SECURITY_CONTEXT } = Ci.nsIProtocolHandler; |
| 129 | + if ( |
| 130 | + aForceAboutBlankViewerInCurrent && |
| 131 | + (!uriObj || this.window.doGetProtocolFlags(uriObj) & URI_INHERITS_SECURITY_CONTEXT) |
| 132 | + ) { |
| 133 | + targetBrowser.createAboutBlankContentViewer(aPrincipal, aStoragePrincipal); |
| 134 | + } |
| 135 | + |
| 136 | + targetBrowser.loadURI(url, { |
| 137 | + triggeringPrincipal: aTriggeringPrincipal, |
| 138 | + csp: aCsp, |
| 139 | + flags, |
| 140 | + referrerInfo: aReferrerInfo, |
| 141 | + postData: aPostData, |
| 142 | + userContextId: aUserContextId, |
| 143 | + }); |
| 144 | + if (aResolveOnContentBrowserReady) { |
| 145 | + aResolveOnContentBrowserReady(targetBrowser); |
| 146 | + } |
| 147 | + |
| 148 | + let focusUrlBar = |
| 149 | + w.document.activeElement == w.gURLBar.inputField && w.isBlankPageURL(url); |
| 150 | + if ( |
| 151 | + !params.avoidBrowserFocus && |
| 152 | + !focusUrlBar && |
| 153 | + targetBrowser == w.gBrowser.selectedBrowser |
| 154 | + ) { |
| 155 | + targetBrowser.focus(); |
| 156 | + } |
| 157 | + }; |
| 158 | + } |
| 159 | + |
| 160 | + if (gBrowserInit.delayedStartupFinished) init(); |
| 161 | + else { |
| 162 | + let delayedListener = (subject, topic) => { |
| 163 | + if (topic == "browser-delayed-startup-finished" && subject == window) { |
| 164 | + Services.obs.removeObserver(delayedListener, topic); |
| 165 | + init(); |
| 166 | + } |
| 167 | + }; |
| 168 | + Services.obs.addObserver(delayedListener, "browser-delayed-startup-finished"); |
| 169 | + } |
| 170 | +})(); |
0 commit comments