diff --git a/browser/components/urlbar/UrlbarInput.jsm b/browser/components/urlbar/UrlbarInput.jsm index ea2245f31c6c..2add12cc96f2 100644 --- a/browser/components/urlbar/UrlbarInput.jsm +++ b/browser/components/urlbar/UrlbarInput.jsm @@ -1233,29 +1233,18 @@ class UrlbarInput { if (this.getAttribute("pageproxystate") == "valid") { uri = this.window.gBrowser.currentURI; } else { - // We're dealing with an autocompleted value. - if (!this._resultForCurrentValue) { - throw new Error( - "UrlbarInput: Should have a UrlbarResult since " + - "pageproxystate != 'valid' and valueIsTyped == false" - ); - } - let resultURL = this._resultForCurrentValue.payload.url; - if (!resultURL) { - return selectedVal; - } - + // The value could be: + // 1. a trimmed url, set by selecting a result + // 2. a search string set by selecting a result + // 3. a url that was confirmed but didn't finish loading yet + // If it's an url the untrimmedValue should resolve to a valid URI, + // otherwise it's a search string that should be copied as-is. try { - uri = Services.uriFixup.createFixupURI( - resultURL, - Services.uriFixup.FIXUP_FLAG_NONE - ); - } catch (e) {} - if (!uri) { + uri = Services.io.newURI(this._untrimmedValue); + } catch (ex) { return selectedVal; } } - uri = this.makeURIReadable(uri); // If the entire URL is selected, just use the actual loaded URI, diff --git a/browser/components/urlbar/tests/browser/browser.ini b/browser/components/urlbar/tests/browser/browser.ini index 5ab804425a73..69b8f1755908 100644 --- a/browser/components/urlbar/tests/browser/browser.ini +++ b/browser/components/urlbar/tests/browser/browser.ini @@ -118,6 +118,9 @@ support-files = file_blank_but_not_blank.html [browser_urlbar_collapseOnChromeMousedown.js] [browser_urlbar_content_opener.js] +[browser_urlbar_copy_during_load.js] +support-files = + slow-page.sjs [browser_urlbar_display_selectedAction_Extensions.js] [browser_urlbar_empty_search.js] [browser_urlbar_event_telemetry.js] diff --git a/browser/components/urlbar/tests/browser/browser_urlbar_copy_during_load.js b/browser/components/urlbar/tests/browser/browser_urlbar_copy_during_load.js new file mode 100644 index 000000000000..b24cbe077d24 --- /dev/null +++ b/browser/components/urlbar/tests/browser/browser_urlbar_copy_during_load.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that copying from the urlbar page works correctly after a result is +// confirmed but takes a while to load. + +add_task(async function() { + const SLOW_PAGE = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://www.example.com" + ) + "slow-page.sjs"; + + await BrowserTestUtils.withNewTab(gBrowser, async tab => { + gURLBar.focus(); + gURLBar.value = SLOW_PAGE; + let promise = TestUtils.waitForCondition( + () => gURLBar.getAttribute("pageproxystate") == "invalid" + ); + EventUtils.synthesizeKey("KEY_Enter"); + info("wait for the initial conditions"); + await promise; + + info("Copy the whole url"); + await SimpleTest.promiseClipboardChange(SLOW_PAGE, () => { + gURLBar.select(); + goDoCommand("cmd_copy"); + }); + + info("Copy the initial part of the url, as a different valid url"); + await SimpleTest.promiseClipboardChange( + SLOW_PAGE.substring(0, SLOW_PAGE.indexOf("slow-page.sjs")), + () => { + gURLBar.selectionStart = 0; + gURLBar.selectionEnd = gURLBar.value.indexOf("slow-page.sjs"); + goDoCommand("cmd_copy"); + } + ); + + // This is apparently necessary to avoid a timeout on mochitest shutdown(!?) + let browserStoppedPromise = BrowserTestUtils.browserStopped( + gBrowser, + null, + true + ); + BrowserStop(); + await browserStoppedPromise; + }); +}); diff --git a/browser/components/urlbar/tests/browser/slow-page.sjs b/browser/components/urlbar/tests/browser/slow-page.sjs index 2612de834550..ce9a7597445a 100644 --- a/browser/components/urlbar/tests/browser/slow-page.sjs +++ b/browser/components/urlbar/tests/browser/slow-page.sjs @@ -11,9 +11,13 @@ function handleRequest(request, response) { } response.processAsync(); timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - timer.init(() => { - response.setHeader("Content-Type", "text/html", false); - response.write("This was the slow load. You should never see this."); - response.finish(); - }, DELAY_MS, Ci.nsITimer.TYPE_ONE_SHOT); + timer.init( + () => { + response.setHeader("Content-Type", "text/html", false); + response.write("This is a slow loading page."); + response.finish(); + }, + DELAY_MS, + Ci.nsITimer.TYPE_ONE_SHOT + ); }