1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsHTTPSOnlyUtils_h___
#define nsHTTPSOnlyUtils_h___
#include "nsIScriptError.h"
#include "nsISupports.h"
#include "mozilla/net/DocumentLoadListener.h"
class nsHTTPSOnlyUtils {
public:
/**
* Returns if HTTPSOnly-Mode preference is enabled
* @param aFromPrivateWindow true if executing in private browsing mode
* @return true if HTTPS-Only Mode is enabled
*/
static bool IsHttpsOnlyModeEnabled(bool aFromPrivateWindow);
/**
* Potentially fires an http request for a top-level load (provided by
* aDocumentLoadListener) in the background to avoid long timeouts in case
* the upgraded https top-level load most likely will result in timeout.
* @param aDocumentLoadListener The Document listener associated with
* the original top-level channel.
*/
static void PotentiallyFireHttpRequestToShortenTimout(
mozilla::net::DocumentLoadListener* aDocumentLoadListener);
/**
* Determines if a request should get upgraded because of the HTTPS-Only mode.
* If true, the httpsOnlyStatus flag in LoadInfo gets updated and a message is
* logged in the console.
* @param aURI nsIURI of request
* @param aLoadInfo nsILoadInfo of request
* @return true if request should get upgraded
*/
static bool ShouldUpgradeRequest(nsIURI* aURI, nsILoadInfo* aLoadInfo);
/**
* Determines if a request should get upgraded because of the HTTPS-Only mode.
* If true, a message is logged in the console.
* @param aURI nsIURI of request
* @param aLoadInfo nsILoadInfo of request
* @return true if request should get upgraded
*/
static bool ShouldUpgradeWebSocket(nsIURI* aURI, nsILoadInfo* aLoadInfo);
/**
* Checks if the error code is on a block-list of codes that are probably not
* related to a HTTPS-Only Mode upgrade.
* @param aChannel The failed Channel.
* @param aError Error Code from Request
* @return false if error is not related to upgrade
*/
static bool CouldBeHttpsOnlyError(nsIChannel* aChannel, nsresult aError);
/**
* Logs localized message to either content console or browser console
* @param aName Localization key
* @param aParams Localization parameters
* @param aFlags Logging Flag (see nsIScriptError)
* @param aLoadInfo The loadinfo of the request.
* @param [aURI] Optional: URI to log
*/
static void LogLocalizedString(const char* aName,
const nsTArray<nsString>& aParams,
uint32_t aFlags, nsILoadInfo* aLoadInfo,
nsIURI* aURI = nullptr);
/**
* Tests if the HTTPS-Only upgrade exception is set for a given principal.
* @param aPrincipal The principal for whom the exception should be checked
* @return True if exempt
*/
static bool TestIfPrincipalIsExempt(nsIPrincipal* aPrincipal);
/**
* Tests if the HTTPS-Only Mode upgrade exception is set for channel result
* principal and sets or removes the httpsOnlyStatus-flag on the loadinfo
* accordingly.
* Note: This function only adds an exemption for loads of TYPE_DOCUMENT.
* @param aChannel The channel to be checked
*/
static void TestSitePermissionAndPotentiallyAddExemption(
nsIChannel* aChannel);
/**
* Checks whether CORS or mixed content requests are safe because they'll get
* upgraded to HTTPS
* @param aLoadInfo nsILoadInfo of request
* @return true if it's safe to accept
*/
static bool IsSafeToAcceptCORSOrMixedContent(nsILoadInfo* aLoadInfo);
private:
/**
* Logs localized message to either content console or browser console
* @param aMessage Message to log
* @param aFlags Logging Flag (see nsIScriptError)
* @param aLoadInfo The loadinfo of the request.
* @param [aURI] Optional: URI to log
*/
static void LogMessage(const nsAString& aMessage, uint32_t aFlags,
nsILoadInfo* aLoadInfo, nsIURI* aURI = nullptr);
/**
* Checks whether the URI ends with .onion
* @param aURI URI object
* @return true if the URI is an Onion URI
*/
static bool OnionException(nsIURI* aURI);
/**
* Checks whether the URI is a loopback- or local-IP
* @param aURI URI object
* @return true if the URI is either loopback or local
*/
static bool LoopbackOrLocalException(nsIURI* aURI);
};
/**
* Helper class to perform an http request with a N milliseconds
* delay. If that http request is 'receiving data' before the
* upgraded https request, then it's a strong indicator that
* the https request will result in a timeout and hence we
* cancel the https request which will result in displaying
* the exception page.
*/
class TestHTTPAnswerRunnable final : public mozilla::Runnable,
public nsIStreamListener,
public nsIInterfaceRequestor,
public nsITimerCallback {
public:
// TestHTTPAnswerRunnable needs to implement all these channel related
// interfaces because otherwise our Necko code is not happy, but we
// really only care about ::OnStartRequest.
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIRUNNABLE
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSITIMERCALLBACK
explicit TestHTTPAnswerRunnable(
nsIURI* aURI, mozilla::net::DocumentLoadListener* aDocumentLoadListener);
protected:
~TestHTTPAnswerRunnable() = default;
private:
RefPtr<nsIURI> mURI;
// We're keeping a reference to DocumentLoadListener instead of a specific
// channel, because the current top-level channel can change (for example
// through redirects)
RefPtr<mozilla::net::DocumentLoadListener> mDocumentLoadListener;
RefPtr<nsITimer> mTimer;
};
#endif /* nsHTTPSOnlyUtils_h___ */
|