Pier Angelo Vendrame pushed to branch base-browser-128.5.0esr-14.5-1 at The Tor Project / Applications / Tor Browser
Commits:
-
9dfe8f86
by Arturo Mejia at 2024-11-26T12:04:40+01:00
-
27cff4ec
by Malte Juergens at 2024-11-26T12:04:42+01:00
-
27cd9ba6
by Makoto Kato at 2024-11-26T12:04:43+01:00
-
e9230608
by Cathy Lu at 2024-11-26T12:04:43+01:00
16 changed files:
- dom/ipc/WindowGlobalParent.cpp
- dom/security/test/https-only/browser.toml
- + dom/security/test/https-only/browser_iframe_buttons.js
- + dom/security/test/https-only/file_iframe_buttons.html
- mobile/android/android-components/components/feature/app-links/src/main/java/mozilla/components/feature/app/links/SimpleRedirectDialogFragment.kt
- mobile/android/android-components/components/feature/app-links/src/test/java/mozilla/components/feature/app/links/SimpleRedirectDialogFragmentTest.kt
- mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionUseCases.kt
- mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionUseCasesTest.kt
- mobile/android/android-components/docs/changelog.md
- mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/CrashReportingTest.kt
- mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
- toolkit/components/httpsonlyerror/content/errorpage.html
- toolkit/components/httpsonlyerror/content/errorpage.js
- toolkit/locales/en-US/toolkit/about/aboutHttpsOnlyError.ftl
- widget/android/nsClipboard.cpp
Changes:
| ... | ... | @@ -1378,18 +1378,11 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvReloadWithHttpsOnlyException() { |
| 1378 | 1378 | return IPC_FAIL(this, "HTTPS-only mode: Illegal state");
|
| 1379 | 1379 | }
|
| 1380 | 1380 | |
| 1381 | - // If the error page is within an iFrame, we create an exception for whatever
|
|
| 1382 | - // scheme the top-level site is currently on, because the user wants to
|
|
| 1383 | - // unbreak the iFrame and not the top-level page. When the error page shows up
|
|
| 1384 | - // on a top-level request, then we replace the scheme with http, because the
|
|
| 1385 | - // user wants to unbreak the whole page.
|
|
| 1381 | + // We replace the scheme with http, because the user wants to unbreak the
|
|
| 1382 | + // whole page.
|
|
| 1386 | 1383 | nsCOMPtr<nsIURI> newURI;
|
| 1387 | - if (!BrowsingContext()->IsTop()) {
|
|
| 1388 | - newURI = innerURI;
|
|
| 1389 | - } else {
|
|
| 1390 | - Unused << NS_MutateURI(innerURI).SetScheme("http"_ns).Finalize(
|
|
| 1391 | - getter_AddRefs(newURI));
|
|
| 1392 | - }
|
|
| 1384 | + Unused << NS_MutateURI(innerURI).SetScheme("http"_ns).Finalize(
|
|
| 1385 | + getter_AddRefs(newURI));
|
|
| 1393 | 1386 | |
| 1394 | 1387 | OriginAttributes originAttributes =
|
| 1395 | 1388 | TopWindowContext()->DocumentPrincipal()->OriginAttributesRef();
|
| ... | ... | @@ -29,6 +29,9 @@ support-files = [ |
| 29 | 29 | ["browser_httpsonly_speculative_connect.js"]
|
| 30 | 30 | support-files = ["file_httpsonly_speculative_connect.html"]
|
| 31 | 31 | |
| 32 | +["browser_iframe_buttons.js"]
|
|
| 33 | +support-files = ["file_iframe_buttons.html"]
|
|
| 34 | + |
|
| 32 | 35 | ["browser_iframe_test.js"]
|
| 33 | 36 | skip-if = [
|
| 34 | 37 | "os == 'linux' && bits == 64", # Bug 1735565
|
| 1 | +/* Any copyright is dedicated to the Public Domain.
|
|
| 2 | + https://creativecommons.org/publicdomain/zero/1.0/ */
|
|
| 3 | + |
|
| 4 | +"use strict";
|
|
| 5 | + |
|
| 6 | +// Ensure the buttons at the buttom of the HTTPS-Only error page do not get
|
|
| 7 | +// displayed in an iframe (Bug 1909396).
|
|
| 8 | + |
|
| 9 | +add_task(async function test_iframe_buttons() {
|
|
| 10 | + await BrowserTestUtils.withNewTab(
|
|
| 11 | + "https://example.com/browser/dom/security/test/https-only/file_iframe_buttons.html",
|
|
| 12 | + async function (browser) {
|
|
| 13 | + await SpecialPowers.pushPrefEnv({
|
|
| 14 | + set: [["dom.security.https_only_mode", true]],
|
|
| 15 | + });
|
|
| 16 | + |
|
| 17 | + await SpecialPowers.spawn(browser, [], async function () {
|
|
| 18 | + const iframe = content.document.getElementById("iframe");
|
|
| 19 | + // eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
| 20 | + iframe.src = "http://nocert.example.com";
|
|
| 21 | + |
|
| 22 | + await ContentTaskUtils.waitForCondition(
|
|
| 23 | + () => iframe.contentWindow.document.readyState === "interactive",
|
|
| 24 | + "Iframe error page should have loaded"
|
|
| 25 | + );
|
|
| 26 | + |
|
| 27 | + ok(
|
|
| 28 | + !!iframe.contentWindow.document.getElementById("explanation-iframe"),
|
|
| 29 | + "#explanation-iframe should exist"
|
|
| 30 | + );
|
|
| 31 | + |
|
| 32 | + is(
|
|
| 33 | + iframe.contentWindow.document
|
|
| 34 | + .getElementById("explanation-iframe")
|
|
| 35 | + .getAttribute("hidden"),
|
|
| 36 | + null,
|
|
| 37 | + "#explanation-iframe should not be hidden"
|
|
| 38 | + );
|
|
| 39 | + |
|
| 40 | + for (const id of ["explanation-continue", "goBack", "openInsecure"]) {
|
|
| 41 | + is(
|
|
| 42 | + iframe.contentWindow.document.getElementById(id),
|
|
| 43 | + null,
|
|
| 44 | + `#${id} should have been removed`
|
|
| 45 | + );
|
|
| 46 | + }
|
|
| 47 | + });
|
|
| 48 | + }
|
|
| 49 | + );
|
|
| 50 | +}); |
| 1 | +<!DOCTYPE html>
|
|
| 2 | +<html lang="en">
|
|
| 3 | +<head>
|
|
| 4 | + <meta charset="UTF-8">
|
|
| 5 | +</head>
|
|
| 6 | +<body>
|
|
| 7 | + <iframe id="iframe" frameborder="0"></iframe>
|
|
| 8 | +</body>
|
|
| 9 | +</html> |
| ... | ... | @@ -11,6 +11,7 @@ import androidx.annotation.StringRes |
| 11 | 11 | import androidx.annotation.StyleRes
|
| 12 | 12 | import androidx.annotation.VisibleForTesting
|
| 13 | 13 | import androidx.appcompat.app.AlertDialog
|
| 14 | +import mozilla.components.support.ktx.util.PromptAbuserDetector
|
|
| 14 | 15 | import mozilla.components.ui.widgets.withCenterAlignedButtons
|
| 15 | 16 | |
| 16 | 17 | /**
|
| ... | ... | @@ -23,6 +24,10 @@ import mozilla.components.ui.widgets.withCenterAlignedButtons |
| 23 | 24 | */
|
| 24 | 25 | class SimpleRedirectDialogFragment : RedirectDialogFragment() {
|
| 25 | 26 | |
| 27 | + @VisibleForTesting
|
|
| 28 | + internal var promptAbuserDetector =
|
|
| 29 | + PromptAbuserDetector(maxSuccessiveDialogSecondsLimit = TIME_SHOWN_OFFSET_SECONDS)
|
|
| 30 | + |
|
| 26 | 31 | @VisibleForTesting
|
| 27 | 32 | internal var testingContext: Context? = null
|
| 28 | 33 | |
| ... | ... | @@ -32,6 +37,8 @@ class SimpleRedirectDialogFragment : RedirectDialogFragment() { |
| 32 | 37 | return if (themeID == 0) AlertDialog.Builder(context) else AlertDialog.Builder(context, themeID)
|
| 33 | 38 | }
|
| 34 | 39 | |
| 40 | + promptAbuserDetector.updateJSDialogAbusedState()
|
|
| 41 | + |
|
| 35 | 42 | return with(requireBundle()) {
|
| 36 | 43 | val dialogTitleText = getInt(KEY_TITLE_TEXT, R.string.mozac_feature_applinks_normal_confirm_dialog_title)
|
| 37 | 44 | val dialogMessageString = getString(KEY_MESSAGE_STRING, "")
|
| ... | ... | @@ -40,18 +47,29 @@ class SimpleRedirectDialogFragment : RedirectDialogFragment() { |
| 40 | 47 | val themeResId = getInt(KEY_THEME_ID, 0)
|
| 41 | 48 | val cancelable = getBoolean(KEY_CANCELABLE, false)
|
| 42 | 49 | |
| 43 | - getBuilder(themeResId)
|
|
| 50 | + val dialog = getBuilder(themeResId)
|
|
| 44 | 51 | .setTitle(dialogTitleText)
|
| 45 | 52 | .setMessage(dialogMessageString)
|
| 46 | - .setPositiveButton(positiveButtonText) { _, _ ->
|
|
| 47 | - onConfirmRedirect()
|
|
| 48 | - }
|
|
| 53 | + .setPositiveButton(positiveButtonText) { _, _ -> }
|
|
| 49 | 54 | .setNegativeButton(negativeButtonText) { _, _ ->
|
| 50 | 55 | onCancelRedirect()
|
| 51 | 56 | }
|
| 52 | 57 | .setCancelable(cancelable)
|
| 53 | 58 | .create()
|
| 54 | - .withCenterAlignedButtons()
|
|
| 59 | + |
|
| 60 | + dialog.withCenterAlignedButtons()
|
|
| 61 | + dialog.setOnShowListener {
|
|
| 62 | + val okButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
|
| 63 | + okButton.setOnClickListener {
|
|
| 64 | + if (promptAbuserDetector.areDialogsBeingAbused()) {
|
|
| 65 | + promptAbuserDetector.updateJSDialogAbusedState()
|
|
| 66 | + } else {
|
|
| 67 | + onConfirmRedirect()
|
|
| 68 | + dialog.dismiss()
|
|
| 69 | + }
|
|
| 70 | + }
|
|
| 71 | + }
|
|
| 72 | + dialog
|
|
| 55 | 73 | }
|
| 56 | 74 | }
|
| 57 | 75 | |
| ... | ... | @@ -101,6 +119,7 @@ class SimpleRedirectDialogFragment : RedirectDialogFragment() { |
| 101 | 119 | const val KEY_THEME_ID = "KEY_THEME_ID"
|
| 102 | 120 | |
| 103 | 121 | const val KEY_CANCELABLE = "KEY_CANCELABLE"
|
| 122 | + private const val TIME_SHOWN_OFFSET_SECONDS = 1
|
|
| 104 | 123 | }
|
| 105 | 124 | |
| 106 | 125 | private fun requireBundle(): Bundle {
|
| ... | ... | @@ -13,6 +13,7 @@ import mozilla.components.support.test.mock |
| 13 | 13 | import mozilla.components.support.test.robolectric.testContext
|
| 14 | 14 | import org.junit.Assert.assertFalse
|
| 15 | 15 | import org.junit.Assert.assertTrue
|
| 16 | +import org.junit.Ignore
|
|
| 16 | 17 | import org.junit.Test
|
| 17 | 18 | import org.junit.runner.RunWith
|
| 18 | 19 | import org.mockito.Mockito.doNothing
|
| ... | ... | @@ -27,6 +28,7 @@ class SimpleRedirectDialogFragmentTest { |
| 27 | 28 | private val themeResId = appcompatR.style.Theme_AppCompat_Light
|
| 28 | 29 | |
| 29 | 30 | @Test
|
| 31 | + @Ignore("This will be addressed in another follow up ticket")
|
|
| 30 | 32 | fun `Dialog confirmed callback is called correctly`() {
|
| 31 | 33 | var onConfirmCalled = false
|
| 32 | 34 | var onCancelCalled = false
|
| ... | ... | @@ -104,6 +106,7 @@ class SimpleRedirectDialogFragmentTest { |
| 104 | 106 | assertFalse(onCancelCalled)
|
| 105 | 107 | }
|
| 106 | 108 | |
| 109 | + @Suppress("unused")
|
|
| 107 | 110 | private fun mockFragmentManager(): FragmentManager {
|
| 108 | 111 | val fragmentManager: FragmentManager = mock()
|
| 109 | 112 | val transaction: FragmentTransaction = mock()
|
| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | |
| 5 | 5 | package mozilla.components.feature.session
|
| 6 | 6 | |
| 7 | -import mozilla.components.browser.state.action.ContentAction
|
|
| 8 | 7 | import mozilla.components.browser.state.action.CrashAction
|
| 9 | 8 | import mozilla.components.browser.state.action.EngineAction
|
| 10 | 9 | import mozilla.components.browser.state.action.LastAccessAction
|
| ... | ... | @@ -94,13 +93,6 @@ class SessionUseCases( |
| 94 | 93 | flags = flags,
|
| 95 | 94 | additionalHeaders = additionalHeaders,
|
| 96 | 95 | )
|
| 97 | - // Update the url in content immediately until the engine updates with any new changes to the state.
|
|
| 98 | - store.dispatch(
|
|
| 99 | - ContentAction.UpdateUrlAction(
|
|
| 100 | - loadSessionId,
|
|
| 101 | - url,
|
|
| 102 | - ),
|
|
| 103 | - )
|
|
| 104 | 96 | store.dispatch(
|
| 105 | 97 | EngineAction.OptimizedLoadUrlTriggeredAction(
|
| 106 | 98 | loadSessionId,
|
| ... | ... | @@ -11,7 +11,6 @@ import mozilla.components.browser.state.action.EngineAction |
| 11 | 11 | import mozilla.components.browser.state.action.TabListAction
|
| 12 | 12 | import mozilla.components.browser.state.engine.EngineMiddleware
|
| 13 | 13 | import mozilla.components.browser.state.selector.findTab
|
| 14 | -import mozilla.components.browser.state.selector.selectedTab
|
|
| 15 | 14 | import mozilla.components.browser.state.state.BrowserState
|
| 16 | 15 | import mozilla.components.browser.state.state.TabSessionState
|
| 17 | 16 | import mozilla.components.browser.state.state.createCustomTab
|
| ... | ... | @@ -81,7 +80,6 @@ class SessionUseCasesTest { |
| 81 | 80 | assertEquals("mozilla", action.tabId)
|
| 82 | 81 | assertEquals("https://getpocket.com", action.url)
|
| 83 | 82 | }
|
| 84 | - assertEquals("https://getpocket.com", store.state.selectedTab?.content?.url)
|
|
| 85 | 83 | |
| 86 | 84 | useCases.loadUrl("https://www.mozilla.org", LoadUrlFlags.select(LoadUrlFlags.EXTERNAL))
|
| 87 | 85 | store.waitUntilIdle()
|
| ... | ... | @@ -95,7 +93,6 @@ class SessionUseCasesTest { |
| 95 | 93 | assertEquals("https://www.mozilla.org", action.url)
|
| 96 | 94 | assertEquals(LoadUrlFlags.select(LoadUrlFlags.EXTERNAL), action.flags)
|
| 97 | 95 | }
|
| 98 | - assertEquals("https://www.mozilla.org", store.state.selectedTab?.content?.url)
|
|
| 99 | 96 | |
| 100 | 97 | useCases.loadUrl("https://firefox.com", store.state.selectedTabId)
|
| 101 | 98 | store.waitUntilIdle()
|
| ... | ... | @@ -105,7 +102,6 @@ class SessionUseCasesTest { |
| 105 | 102 | assertEquals("mozilla", action.tabId)
|
| 106 | 103 | assertEquals("https://firefox.com", action.url)
|
| 107 | 104 | }
|
| 108 | - assertEquals("https://firefox.com", store.state.selectedTab?.content?.url)
|
|
| 109 | 105 | |
| 110 | 106 | useCases.loadUrl.invoke(
|
| 111 | 107 | "https://developer.mozilla.org",
|
| ... | ... | @@ -109,9 +109,6 @@ permalink: /changelog/ |
| 109 | 109 | * **feature-customtabs**
|
| 110 | 110 | * Fallback behaviour when failing to open a new window in custom tab will now be loading the URL directly in the same custom tab. [Bug 1832357](https://bugzilla.mozilla.org/show_bug.cgi?id=1832357)
|
| 111 | 111 | |
| 112 | -* **feature-session**
|
|
| 113 | - * Update URL in the store immediately when using the optimized load URL code path.
|
|
| 114 | - |
|
| 115 | 112 | * **tooling-lint**
|
| 116 | 113 | * Added a lint rule to detect when `Response#close` may not have been called. Note: Currently, this rule only runs on Android Components.
|
| 117 | 114 |
| ... | ... | @@ -83,7 +83,7 @@ class CrashReportingTest : TestSetup() { |
| 83 | 83 | verifyPageContent(tabCrashMessage)
|
| 84 | 84 | }.openTabDrawer(activityTestRule) {
|
| 85 | 85 | verifyExistingOpenTabs(firstWebPage.title)
|
| 86 | - verifyExistingOpenTabs("about:crashcontent")
|
|
| 86 | + verifyExistingOpenTabs(secondWebPage.title)
|
|
| 87 | 87 | }.closeTabDrawer {
|
| 88 | 88 | }.goToHomescreen {
|
| 89 | 89 | verifyExistingTopSitesList()
|
| ... | ... | @@ -11,6 +11,7 @@ import android.content.ClipboardManager.OnPrimaryClipChangedListener; |
| 11 | 11 | import android.content.Context;
|
| 12 | 12 | import android.content.res.AssetFileDescriptor;
|
| 13 | 13 | import android.os.Build;
|
| 14 | +import android.os.PersistableBundle;
|
|
| 14 | 15 | import android.text.TextUtils;
|
| 15 | 16 | import android.util.Log;
|
| 16 | 17 | import java.io.ByteArrayOutputStream;
|
| ... | ... | @@ -133,8 +134,9 @@ public final class Clipboard { |
| 133 | 134 | * @return true if copy is successful.
|
| 134 | 135 | */
|
| 135 | 136 | @WrapForJNI(calledFrom = "gecko")
|
| 136 | - public static boolean setText(final Context context, final CharSequence text) {
|
|
| 137 | - return setData(context, ClipData.newPlainText("text", text));
|
|
| 137 | + public static boolean setText(
|
|
| 138 | + final Context context, final CharSequence text, final boolean isPrivateData) {
|
|
| 139 | + return setData(context, ClipData.newPlainText("text", text), isPrivateData);
|
|
| 138 | 140 | }
|
| 139 | 141 | |
| 140 | 142 | /**
|
| ... | ... | @@ -147,8 +149,11 @@ public final class Clipboard { |
| 147 | 149 | */
|
| 148 | 150 | @WrapForJNI(calledFrom = "gecko")
|
| 149 | 151 | private static boolean setHTML(
|
| 150 | - final Context context, final CharSequence text, final String htmlText) {
|
|
| 151 | - return setData(context, ClipData.newHtmlText("html", text, htmlText));
|
|
| 152 | + final Context context,
|
|
| 153 | + final CharSequence text,
|
|
| 154 | + final String htmlText,
|
|
| 155 | + final boolean isPrivateData) {
|
|
| 156 | + return setData(context, ClipData.newHtmlText("html", text, htmlText), isPrivateData);
|
|
| 152 | 157 | }
|
| 153 | 158 | |
| 154 | 159 | /**
|
| ... | ... | @@ -158,11 +163,17 @@ public final class Clipboard { |
| 158 | 163 | * @param clipData a {@link android.content.ClipData} to set to clipboard
|
| 159 | 164 | * @return true if copy is successful.
|
| 160 | 165 | */
|
| 161 | - private static boolean setData(final Context context, final ClipData clipData) {
|
|
| 166 | + private static boolean setData(
|
|
| 167 | + final Context context, final ClipData clipData, final boolean isPrivateData) {
|
|
| 162 | 168 | // In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
|
| 163 | 169 | // which is a subclass of android.text.ClipboardManager.
|
| 164 | 170 | final ClipboardManager cm =
|
| 165 | 171 | (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
| 172 | + if (isPrivateData && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
| 173 | + final PersistableBundle extras = new PersistableBundle();
|
|
| 174 | + extras.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
|
|
| 175 | + clipData.getDescription().setExtras(extras);
|
|
| 176 | + }
|
|
| 166 | 177 | try {
|
| 167 | 178 | cm.setPrimaryClip(clipData);
|
| 168 | 179 | } catch (final NullPointerException e) {
|
| ... | ... | @@ -228,7 +239,7 @@ public final class Clipboard { |
| 228 | 239 | @WrapForJNI(calledFrom = "gecko")
|
| 229 | 240 | private static void clear(final Context context) {
|
| 230 | 241 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
|
| 231 | - setText(context, null);
|
|
| 242 | + setText(context, null, false);
|
|
| 232 | 243 | return;
|
| 233 | 244 | }
|
| 234 | 245 | // Although we don't know more details of https://crbug.com/1203377, Blink doesn't use
|
| ... | ... | @@ -70,6 +70,7 @@ import org.mozilla.gecko.util.ThreadUtils; |
| 70 | 70 | private ExtractedTextRequest mUpdateRequest;
|
| 71 | 71 | private final InputConnection mKeyInputConnection;
|
| 72 | 72 | private CursorAnchorInfo.Builder mCursorAnchorInfoBuilder;
|
| 73 | + private boolean mIsPrivateBrowsing;
|
|
| 73 | 74 | |
| 74 | 75 | public static SessionTextInput.InputConnectionClient create(
|
| 75 | 76 | final GeckoSession session,
|
| ... | ... | @@ -208,12 +209,13 @@ import org.mozilla.gecko.util.ThreadUtils; |
| 208 | 209 | // If selection is empty, we'll select everything
|
| 209 | 210 | if (selStart == selEnd) {
|
| 210 | 211 | // Fill the clipboard
|
| 211 | - Clipboard.setText(view.getContext(), editable);
|
|
| 212 | + Clipboard.setText(view.getContext(), editable, mIsPrivateBrowsing);
|
|
| 212 | 213 | editable.clear();
|
| 213 | 214 | } else {
|
| 214 | 215 | Clipboard.setText(
|
| 215 | 216 | view.getContext(),
|
| 216 | - editable.subSequence(Math.min(selStart, selEnd), Math.max(selStart, selEnd)));
|
|
| 217 | + editable.subSequence(Math.min(selStart, selEnd), Math.max(selStart, selEnd)),
|
|
| 218 | + mIsPrivateBrowsing);
|
|
| 217 | 219 | editable.delete(selStart, selEnd);
|
| 218 | 220 | }
|
| 219 | 221 | break;
|
| ... | ... | @@ -231,7 +233,7 @@ import org.mozilla.gecko.util.ThreadUtils; |
| 231 | 233 | : editable
|
| 232 | 234 | .toString()
|
| 233 | 235 | .substring(Math.min(selStart, selEnd), Math.max(selStart, selEnd));
|
| 234 | - Clipboard.setText(view.getContext(), copiedText);
|
|
| 236 | + Clipboard.setText(view.getContext(), copiedText, mIsPrivateBrowsing);
|
|
| 235 | 237 | break;
|
| 236 | 238 | }
|
| 237 | 239 | return true;
|
| ... | ... | @@ -603,6 +605,9 @@ import org.mozilla.gecko.util.ThreadUtils; |
| 603 | 605 | outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN;
|
| 604 | 606 | }
|
| 605 | 607 | |
| 608 | + mIsPrivateBrowsing =
|
|
| 609 | + ((outAttrs.imeOptions & InputMethods.IME_FLAG_NO_PERSONALIZED_LEARNING) != 0);
|
|
| 610 | + |
|
| 606 | 611 | if (DEBUG) {
|
| 607 | 612 | Log.d(
|
| 608 | 613 | LOGTAG,
|
| ... | ... | @@ -70,6 +70,16 @@ |
| 70 | 70 | inert
|
| 71 | 71 | ></button>
|
| 72 | 72 | </div>
|
| 73 | + |
|
| 74 | + <p id="explanation-iframe" hidden>
|
|
| 75 | + <span data-l10n-id="about-httpsonly-explanation-iframe"></span>
|
|
| 76 | + <a
|
|
| 77 | + id="mixedContentLearnMoreLink"
|
|
| 78 | + target="_blank"
|
|
| 79 | + data-l10n-id="about-httpsonly-link-learn-more"
|
|
| 80 | + ></a>
|
|
| 81 | + </p>
|
|
| 82 | + |
|
| 73 | 83 | <div class="suggestion-box" hidden>
|
| 74 | 84 | <h2 data-l10n-id="about-httpsonly-suggestion-box-header"></h2>
|
| 75 | 85 | </div>
|
| ... | ... | @@ -29,28 +29,35 @@ function initPage() { |
| 29 | 29 | document
|
| 30 | 30 | .getElementById("learnMoreLink")
|
| 31 | 31 | .setAttribute("href", baseSupportURL + "https-only-prefs");
|
| 32 | + document
|
|
| 33 | + .getElementById("mixedContentLearnMoreLink")
|
|
| 34 | + .setAttribute("href", baseSupportURL + "mixed-content");
|
|
| 35 | + |
|
| 36 | + const isTopLevel = window.top == window;
|
|
| 37 | + if (!isTopLevel) {
|
|
| 38 | + for (const id of ["explanation-continue", "goBack", "openInsecure"]) {
|
|
| 39 | + document.getElementById(id).remove();
|
|
| 40 | + }
|
|
| 41 | + document.getElementById("explanation-iframe").removeAttribute("hidden");
|
|
| 42 | + return;
|
|
| 43 | + }
|
|
| 32 | 44 | |
| 33 | 45 | document
|
| 34 | 46 | .getElementById("openInsecure")
|
| 35 | 47 | .addEventListener("click", onOpenInsecureButtonClick);
|
| 48 | + document
|
|
| 49 | + .getElementById("goBack")
|
|
| 50 | + .addEventListener("click", onReturnButtonClick);
|
|
| 36 | 51 | |
| 37 | 52 | const delay = RPMGetIntPref("security.dialog_enable_delay", 1000);
|
| 38 | 53 | setTimeout(() => {
|
| 39 | 54 | document.getElementById("openInsecure").removeAttribute("inert");
|
| 40 | 55 | }, delay);
|
| 41 | 56 | |
| 42 | - if (window.top == window) {
|
|
| 43 | - document
|
|
| 44 | - .getElementById("goBack")
|
|
| 45 | - .addEventListener("click", onReturnButtonClick);
|
|
| 46 | - addAutofocus("#goBack", "beforeend");
|
|
| 47 | - } else {
|
|
| 48 | - document.getElementById("goBack").remove();
|
|
| 49 | - }
|
|
| 57 | + addAutofocus("#goBack", "beforeend");
|
|
| 50 | 58 | |
| 51 | - const isTopLevel = window.top == window;
|
|
| 52 | 59 | const hasWWWPrefix = pageUrl.href.startsWith("https://www.");
|
| 53 | - if (isTopLevel && !hasWWWPrefix) {
|
|
| 60 | + if (!hasWWWPrefix) {
|
|
| 54 | 61 | // HTTPS-Only generally simply replaces http: with https:;
|
| 55 | 62 | // here we additionally try to add www and see if that allows to upgrade the connection if it is top level
|
| 56 | 63 |
| ... | ... | @@ -12,6 +12,7 @@ about-httpsonly-explanation-question = What could be causing this? |
| 12 | 12 | about-httpsonly-explanation-nosupport = Most likely, the website simply does not support HTTPS.
|
| 13 | 13 | about-httpsonly-explanation-risk = It’s also possible that an attacker is involved. If you decide to visit the website, you should not enter any sensitive information like passwords, emails, or credit card details.
|
| 14 | 14 | about-httpsonly-explanation-continue = If you continue, HTTPS-Only Mode will be turned off temporarily for this site.
|
| 15 | +about-httpsonly-explanation-iframe = Due to mixed content blocking, it is not possible to manually allow this frame to load.
|
|
| 15 | 16 | |
| 16 | 17 | about-httpsonly-button-continue-to-site = Continue to HTTP Site
|
| 17 | 18 | about-httpsonly-button-go-back = Go Back
|
| ... | ... | @@ -92,14 +92,16 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable, |
| 92 | 92 | return rv;
|
| 93 | 93 | }
|
| 94 | 94 | |
| 95 | + bool isPrivate = aTransferable->GetIsPrivateData();
|
|
| 96 | + |
|
| 95 | 97 | if (!html.IsEmpty() &&
|
| 96 | 98 | java::Clipboard::SetHTML(java::GeckoAppShell::GetApplicationContext(),
|
| 97 | - text, html)) {
|
|
| 99 | + text, html, isPrivate)) {
|
|
| 98 | 100 | return NS_OK;
|
| 99 | 101 | }
|
| 100 | 102 | if (!text.IsEmpty() &&
|
| 101 | 103 | java::Clipboard::SetText(java::GeckoAppShell::GetApplicationContext(),
|
| 102 | - text)) {
|
|
| 104 | + text, isPrivate)) {
|
|
| 103 | 105 | return NS_OK;
|
| 104 | 106 | }
|
| 105 | 107 |