/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ function getUrl(hostname, file) { return ( getRootDirectory(gTestPath).replace( "chrome://mochitests/content", hostname ) + file ); } add_task(async function () { await test_copy_values(trimHttpTests, false); await test_copy_values(trimHttpsTests, true); }); async function test_copy_values(testValues, trimHttps) { let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); registerCleanupFunction(function () { gBrowser.removeTab(tab); gURLBar.setURI(); }); await SpecialPowers.pushPrefEnv({ set: [ ["browser.urlbar.scotchBonnet.enableOverride", false], ["browser.urlbar.trimURLs", true], ["browser.urlbar.trimHttps", trimHttps], ], }); for (let testCase of testValues) { if (testCase.setup) { await testCase.setup(); } if (testCase.loadURL) { info(`Loading : ${testCase.loadURL}`); let expectedLoad = testCase.expectedLoad || testCase.loadURL; BrowserTestUtils.startLoadingURIString( gBrowser.selectedBrowser, testCase.loadURL ); await BrowserTestUtils.browserLoaded( gBrowser.selectedBrowser, false, expectedLoad ); } else if (testCase.setURL) { gURLBar.value = testCase.setURL; // After input only the visible text is copied. UrlbarTestUtils.fireInputEvent(window); } if (testCase.setURL || testCase.loadURL) { is( gURLBar.value, testCase.expectedURL, "url bar value set to " + gURLBar.value ); } gURLBar.focus(); if (testCase.expectedValueOnFocus) { Assert.equal( gURLBar.value, testCase.expectedValueOnFocus, "Check value on focus" ); } await testCopy(testCase.copyVal, testCase.copyExpected); gURLBar.blur(); if (testCase.cleanup) { await testCase.cleanup(); } } } var trimHttpTests = [ // pageproxystate="invalid" { setURL: "http://example.com/", expectedURL: "example.com", copyExpected: "example.com", }, { copyVal: "xample.com", copyExpected: "e", }, { copyVal: "xmple.com", copyExpected: "ea", }, { copyVal: "mple.com", copyExpected: "exa", }, { copyVal: "mple.co", copyExpected: "exam", }, { copyVal: "", copyExpected: "example.com", }, // pageproxystate="valid" from this point on (due to the load) { loadURL: "http://example.com/", expectedURL: "example.com", copyExpected: "http://example.com/", }, { copyVal: "m", copyExpected: "example.co", }, { copyVal: "eample.com", copyExpected: "x", }, { copyVal: "xample.com", copyExpected: "e", }, { copyVal: "xample.co", copyExpected: "em", }, { copyVal: "", copyExpected: "example.com", }, { loadURL: "http://example.com/foo", expectedURL: "example.com/foo", copyExpected: "http://example.com/foo", }, { copyVal: "/foo", copyExpected: "http://example.com", }, { copyVal: ".com/foo", copyExpected: "example", }, // Test that partially selected URL is copied with encoded spaces { loadURL: "http://example.com/%20space/test", expectedURL: "example.com/ space/test", copyExpected: "http://example.com/%20space/test", }, { copyVal: "/test", copyExpected: "http://example.com/%20space", }, { copyVal: "", copyExpected: "http://example.com/%20space/test", }, { loadURL: "http://example.com/%20foo%20bar%20baz/", expectedURL: "example.com/ foo bar baz/", copyExpected: "http://example.com/%20foo%20bar%20baz/", }, { copyVal: " baz/", copyExpected: "http://example.com/%20foo%20bar", }, { copyVal: "example. baz/", copyExpected: "com/ foo bar", }, // Test that userPass is stripped out { loadURL: getUrl( "http://user:pass@mochi.test:8888", "authenticate.sjs?user=user&pass=pass" ), expectedURL: getUrl( "mochi.test:8888", "authenticate.sjs?user=user&pass=pass" ), copyExpected: getUrl( "http://mochi.test:8888", "authenticate.sjs?user=user&pass=pass" ), }, // Test escaping { loadURL: "http://example.com/()%28%29%C3%A9", expectedURL: "example.com/()()\xe9", copyExpected: "http://example.com/()%28%29%C3%A9", }, { copyVal: ")()\xe9", copyExpected: "http://example.com/(", }, { copyVal: "e)()\xe9", copyExpected: "xample.com/(", }, { loadURL: "http://example.com/%C3%A9%C3%A9", expectedURL: "example.com/\xe9\xe9", copyExpected: "http://example.com/%C3%A9%C3%A9", }, { copyVal: "e\xe9", copyExpected: "xample.com/\xe9", }, { copyVal: "\xe9", copyExpected: "http://example.com/%C3%A9", }, { // Note: it seems BrowserTestUtils.loadURI fails for unicode domains loadURL: "http://sub2.xn--lt-uia.mochi.test:8888/foo", expectedURL: "sub2.ält.mochi.test:8888/foo", copyExpected: "http://sub2.ält.mochi.test:8888/foo", }, { copyVal: "soo", copyExpected: "ub2.ält.mochi.test:8888/f", }, { copyVal: "oo", copyExpected: "http://sub2.%C3%A4lt.mochi.test:8888/f", }, { loadURL: "http://example.com/?%C3%B7%C3%B7", expectedURL: "example.com/?\xf7\xf7", copyExpected: "http://example.com/?%C3%B7%C3%B7", }, { copyVal: "e\xf7", copyExpected: "xample.com/?\xf7", }, { copyVal: "\xf7", copyExpected: "http://example.com/?%C3%B7", }, { loadURL: "http://example.com/a%20test", expectedURL: "example.com/a test", copyExpected: "http://example.com/a%20test", }, { loadURL: "http://example.com/a%E3%80%80test", expectedURL: "example.com/a%E3%80%80test", copyExpected: "http://example.com/a%E3%80%80test", }, { loadURL: "http://example.com/a%20%C2%A0test", expectedURL: "example.com/a%20%C2%A0test", copyExpected: "http://example.com/a%20%C2%A0test", }, { loadURL: "http://example.com/%20%20%20", expectedURL: "example.com/%20%20%20", copyExpected: "http://example.com/%20%20%20", }, { loadURL: "http://example.com/%E3%80%80%E3%80%80", expectedURL: "example.com/%E3%80%80%E3%80%80", copyExpected: "http://example.com/%E3%80%80%E3%80%80", }, // Loading of javascript: URI results in previous URI, so if the previous // entry changes, change this one too! { loadURL: "javascript:('%C3%A9%20%25%50')", expectedLoad: "http://example.com/%E3%80%80%E3%80%80", expectedURL: "example.com/%E3%80%80%E3%80%80", copyExpected: "http://example.com/%E3%80%80%E3%80%80", }, // data: URIs shouldn't be encoded { loadURL: "data:text/html,(%C3%A9%20%25%50)", expectedURL: "data:text/html,(%C3%A9 %25P)", copyExpected: "data:text/html,(%C3%A9 %25P)", }, { copyVal: "%C3%A9 %25P)", copyExpected: "data:text/html,(", }, { copyVal: ")", copyExpected: "data:text/html,(%C3%A9 %25P", }, { async setup() { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.decodeURLsOnCopy", true]], }); }, async cleanup() { await SpecialPowers.popPrefEnv(); }, loadURL: "http://example.com/%D0%B1%D0%B8%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%8F", expectedURL: "example.com/биография", copyExpected: "http://example.com/биография", }, { copyVal: "ография", copyExpected: "http://example.com/%D0%B1%D0%B8", }, { async setup() { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.decodeURLsOnCopy", true]], }); // Setup a valid intranet url that resolves but is not yet known. const proxyService = Cc[ "@mozilla.org/network/protocol-proxy-service;1" ].getService(Ci.nsIProtocolProxyService); let proxyInfo = proxyService.newProxyInfo( "http", "localhost", 8888, "", "", 0, 4096, null ); this._proxyFilter = { applyFilter(channel, defaultProxyInfo, callback) { callback.onProxyFilterResult( channel.URI.host === "mytest" ? proxyInfo : defaultProxyInfo ); }, }; proxyService.registerChannelFilter(this._proxyFilter, 0); registerCleanupFunction(() => { if (this._proxyFilter) { proxyService.unregisterChannelFilter(this._proxyFilter); } }); }, async cleanup() { await SpecialPowers.popPrefEnv(); const proxyService = Cc[ "@mozilla.org/network/protocol-proxy-service;1" ].getService(Ci.nsIProtocolProxyService); proxyService.unregisterChannelFilter(this._proxyFilter); this._proxyFilter = null; }, loadURL: "http://mytest/", expectedURL: "mytest", expectedValueOnFocus: "http://mytest/", copyExpected: "http://mytest/", }, { async setup() { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.decodeURLsOnCopy", true]], }); }, async cleanup() { await SpecialPowers.popPrefEnv(); }, loadURL: "https://example.com/", expectedURL: "https://example.com", copyExpected: "https://example.com", }, ]; var trimHttpsTests = [ // pageproxystate="invalid" { setURL: "https://example.com/", expectedURL: "example.com", copyExpected: "example.com", }, { copyVal: "xample.com", copyExpected: "e", }, { copyVal: "xmple.com", copyExpected: "ea", }, { copyVal: "mple.com", copyExpected: "exa", }, { copyVal: "mple.co", copyExpected: "exam", }, { copyVal: "", copyExpected: "example.com", }, // pageproxystate="valid" from this point on (due to the load) { loadURL: "https://example.com/", expectedURL: "example.com", copyExpected: "https://example.com/", }, { copyVal: "m", copyExpected: "example.co", }, { copyVal: "eample.com", copyExpected: "x", }, { copyVal: "xample.com", copyExpected: "e", }, { copyVal: "xample.co", copyExpected: "em", }, { copyVal: "", copyExpected: "example.com", }, { loadURL: "https://example.com/foo", expectedURL: "example.com/foo", copyExpected: "https://example.com/foo", }, { copyVal: "/foo", copyExpected: "https://example.com", }, { copyVal: ".com/foo", copyExpected: "example", }, // Test that partially selected URL is copied with encoded spaces { loadURL: "https://example.com/%20space/test", expectedURL: "example.com/ space/test", copyExpected: "https://example.com/%20space/test", }, { copyVal: "/test", copyExpected: "https://example.com/%20space", }, { copyVal: "", copyExpected: "https://example.com/%20space/test", }, { loadURL: "https://example.com/%20foo%20bar%20baz/", expectedURL: "example.com/ foo bar baz/", copyExpected: "https://example.com/%20foo%20bar%20baz/", }, { copyVal: " baz/", copyExpected: "https://example.com/%20foo%20bar", }, { copyVal: "example. baz/", copyExpected: "com/ foo bar", }, // Test escaping { loadURL: "https://example.com/()%28%29%C3%A9", expectedURL: "example.com/()()\xe9", copyExpected: "https://example.com/()%28%29%C3%A9", }, { copyVal: ")()\xe9", copyExpected: "https://example.com/(", }, { copyVal: "e)()\xe9", copyExpected: "xample.com/(", }, { loadURL: "https://example.com/%C3%A9%C3%A9", expectedURL: "example.com/\xe9\xe9", copyExpected: "https://example.com/%C3%A9%C3%A9", }, { copyVal: "e\xe9", copyExpected: "xample.com/\xe9", }, { copyVal: "\xe9", copyExpected: "https://example.com/%C3%A9", } /* { // Note: it seems BrowserTestUtils.loadURI fails for unicode domains loadURL: "https://sub2.xn--lt-uia.mochi.test:8888/foo", expectedURL: "sub2.ält.mochi.test:8888/foo", copyExpected: "https://sub2.ält.mochi.test:8888/foo", }, { copyVal: "soo", copyExpected: "ub2.ält.mochi.test:8888/f", }, { copyVal: "oo", copyExpected: "https://sub2.%C3%A4lt.mochi.test:8888/f", },*/, { loadURL: "https://example.com/?%C3%B7%C3%B7", expectedURL: "example.com/?\xf7\xf7", copyExpected: "https://example.com/?%C3%B7%C3%B7", }, { copyVal: "e\xf7", copyExpected: "xample.com/?\xf7", }, { copyVal: "\xf7", copyExpected: "https://example.com/?%C3%B7", }, { loadURL: "https://example.com/a%20test", expectedURL: "example.com/a test", copyExpected: "https://example.com/a%20test", }, { loadURL: "https://example.com/a%E3%80%80test", expectedURL: "example.com/a%E3%80%80test", copyExpected: "https://example.com/a%E3%80%80test", }, { loadURL: "https://example.com/a%20%C2%A0test", expectedURL: "example.com/a%20%C2%A0test", copyExpected: "https://example.com/a%20%C2%A0test", }, { loadURL: "https://example.com/%20%20%20", expectedURL: "example.com/%20%20%20", copyExpected: "https://example.com/%20%20%20", }, { loadURL: "https://example.com/%E3%80%80%E3%80%80", expectedURL: "example.com/%E3%80%80%E3%80%80", copyExpected: "https://example.com/%E3%80%80%E3%80%80", }, // Loading of javascript: URI results in previous URI, so if the previous // entry changes, change this one too! { loadURL: "javascript:('%C3%A9%20%25%50')", expectedLoad: "https://example.com/%E3%80%80%E3%80%80", expectedURL: "example.com/%E3%80%80%E3%80%80", copyExpected: "https://example.com/%E3%80%80%E3%80%80", }, // data: URIs shouldn't be encoded { loadURL: "data:text/html,(%C3%A9%20%25%50)", expectedURL: "data:text/html,(%C3%A9 %25P)", copyExpected: "data:text/html,(%C3%A9 %25P)", }, { copyVal: "%C3%A9 %25P)", copyExpected: "data:text/html,(", }, { copyVal: ")", copyExpected: "data:text/html,(%C3%A9 %25P", }, { async setup() { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.decodeURLsOnCopy", true]], }); }, async cleanup() { await SpecialPowers.popPrefEnv(); }, loadURL: "https://example.com/%D0%B1%D0%B8%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%8F", expectedURL: "example.com/биография", copyExpected: "https://example.com/биография", }, { copyVal: "ография", copyExpected: "https://example.com/%D0%B1%D0%B8", }, { async setup() { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.decodeURLsOnCopy", true]], }); }, async cleanup() { await SpecialPowers.popPrefEnv(); }, loadURL: "http://example.com/", expectedURL: "http://example.com", copyExpected: "http://example.com", }, ]; function testCopy(copyVal, targetValue) { info("Expecting copy of: " + targetValue); if (copyVal) { let offsets = []; for (;;) { let startBracket = copyVal.indexOf("<"); let endBracket = copyVal.indexOf(">"); if (startBracket == -1 && endBracket == -1) { break; } if (startBracket > endBracket || startBracket == -1) { offsets = []; break; } offsets.push([startBracket, endBracket - 1]); copyVal = copyVal.replace("<", "").replace(">", ""); } if (!offsets.length || copyVal != gURLBar.value) { ok(false, "invalid copyVal: " + copyVal); } gURLBar.selectionStart = offsets[0][0]; gURLBar.selectionEnd = offsets[0][1]; if (offsets.length > 1) { let sel = gURLBar.editor.selection; let r0 = sel.getRangeAt(0); let node0 = r0.startContainer; sel.removeAllRanges(); offsets.map(function (startEnd) { let range = r0.cloneRange(); range.setStart(node0, startEnd[0]); range.setEnd(node0, startEnd[1]); sel.addRange(range); }); } } else { gURLBar.select(); } info(`Target Value ${targetValue}`); return SimpleTest.promiseClipboardChange(targetValue, () => goDoCommand("cmd_copy") ); } add_task(async function includingProtocol() { await PlacesUtils.history.clear(); await PlacesTestUtils.clearInputHistory(); SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.trimHttps", true]] }); await PlacesTestUtils.addVisits([ { url: "https://example.com/", transition: PlacesUtils.history.TRANSITION_TYPED, }, ]); await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); // If the url is autofilled, the protocol should be included in the copied // value. await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, value: "example", fireInputEvent: true, }); Assert.ok( (await UrlbarTestUtils.getDetailsOfResultAt(window, 0)).autofill, "The first result should be autofill suggestion" ); window.goDoCommand("cmd_selectAll"); await SimpleTest.promiseClipboardChange("https://example.com/", () => goDoCommand("cmd_copy") ); Assert.ok(true, "Expected value is copied"); // Then, when adding some more characters, should not be included. gURLBar.selectionStart = gURLBar.value.length; gURLBar.selectionEnd = gURLBar.value.length; EventUtils.synthesizeKey("x"); await UrlbarTestUtils.promiseSearchComplete(window); Assert.ok( !(await UrlbarTestUtils.getDetailsOfResultAt(window, 0)).autofill, "The first result should not be aufotill suggestion" ); window.goDoCommand("cmd_selectAll"); await SimpleTest.promiseClipboardChange("example.com/x", () => goDoCommand("cmd_copy") ); Assert.ok(true, "Expected value is copied"); await PlacesUtils.history.clear(); await PlacesTestUtils.clearInputHistory(); }); add_task(async function loadingPageInBlank() { const home = `${TEST_BASE_URL}file_copying_home.html`; const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, home); const onNewTabCreated = waitForNewTabWithLoadRequest(); SpecialPowers.spawn(tab.linkedBrowser, [], function () { content.document.querySelector("a").click(); }); const newtab = await onNewTabCreated; await TestUtils.waitForCondition( () => newtab.linkedBrowser.browsingContext.mostRecentLoadingSessionHistoryEntry ); gURLBar.focus(); window.goDoCommand("cmd_selectAll"); await SimpleTest.promiseClipboardChange( "https://example.com/browser/browser/components/urlbar/tests/browser-editing/wait-a-bit.sjs", () => goDoCommand("cmd_copy") ); Assert.ok(true, "Expected value is copied"); BrowserTestUtils.removeTab(tab); BrowserTestUtils.removeTab(newtab); }); async function waitForNewTabWithLoadRequest() { return new Promise(resolve => gBrowser.addTabsProgressListener({ onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags) { if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) { gBrowser.removeTabsProgressListener(this); resolve(gBrowser.getTabForBrowser(aBrowser)); } }, }) ); }