1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "LoginDetectionService.h"
9 #include "nsILoginInfo.h"
10 #include "nsILoginManager.h"
11 #include "nsIObserver.h"
12 #include "nsIXULRuntime.h"
13 #include "nsServiceManagerUtils.h"
14 #include "nsXULAppAPI.h"
16 #include "mozilla/ClearOnShutdown.h"
17 #include "mozilla/StaticPrefs_fission.h"
18 #include "mozilla/dom/ProcessIsolation.h"
20 namespace mozilla::dom
{
22 static StaticRefPtr
<LoginDetectionService
> gLoginDetectionService
;
26 void OnFissionPrefsChange(const char* aPrefName
, void* aData
) {
27 MOZ_ASSERT(gLoginDetectionService
);
29 gLoginDetectionService
->MaybeStartMonitoring();
34 NS_IMPL_ISUPPORTS(LoginDetectionService
, nsILoginDetectionService
,
35 nsILoginSearchCallback
, nsIObserver
, nsISupportsWeakReference
)
38 already_AddRefed
<LoginDetectionService
> LoginDetectionService::GetSingleton() {
39 if (gLoginDetectionService
) {
40 return do_AddRef(gLoginDetectionService
);
43 gLoginDetectionService
= new LoginDetectionService();
44 ClearOnShutdown(&gLoginDetectionService
);
46 return do_AddRef(gLoginDetectionService
);
49 LoginDetectionService::LoginDetectionService() : mIsLoginsLoaded(false) {}
50 LoginDetectionService::~LoginDetectionService() { UnregisterObserver(); }
52 void LoginDetectionService::MaybeStartMonitoring() {
53 if (IsIsolateHighValueSiteEnabled()) {
54 // We want to isolate sites with a saved password, so fetch saved logins
55 // from the password manager, and then add the 'HighValue' permission.
57 // Note that we don't monitor whether a login is added or removed after
58 // logins are fetched. For adding logins, this will be covered by form
59 // submission detection heuristic. As for removing logins, it doesn't
60 // provide security benefit just to NOT isolate the removed site. The site
61 // will not be isolated when its permission expired.
65 if (IsIsolateHighValueSiteEnabled() ||
66 StaticPrefs::fission_highValue_login_monitor()) {
67 // When the pref is on, we monitor users' login attempt event when we
68 // are not isolating high value sites. This is because We can't detect the
69 // case where a user is already logged in to a site, and don't save a
70 // password for it. So we want to start monitoring login attempts prior
71 // to releasing the feature.
73 mObs
= mozilla::services::GetObserverService();
74 mObs
->AddObserver(this, "passwordmgr-form-submission-detected", false);
81 void LoginDetectionService::FetchLogins() {
83 nsCOMPtr
<nsILoginManager
> loginManager
=
84 do_GetService(NS_LOGINMANAGER_CONTRACTID
, &rv
);
85 if (NS_WARN_IF(!loginManager
)) {
89 Unused
<< loginManager
->GetAllLoginsWithCallback(this);
92 void LoginDetectionService::UnregisterObserver() {
94 mObs
->RemoveObserver(this, "passwordmgr-form-submission-detected");
99 ///////////////////////////////////////////////////////////////////////////////
100 // nsILoginDetectionService implementation
101 NS_IMETHODIMP
LoginDetectionService::Init() {
102 if (XRE_IsContentProcess()) {
106 Preferences::RegisterCallback(OnFissionPrefsChange
, "fission.autostart");
107 Preferences::RegisterCallback(OnFissionPrefsChange
,
108 "fission.webContentIsolationStrategy");
110 MaybeStartMonitoring();
115 NS_IMETHODIMP
LoginDetectionService::IsLoginsLoaded(bool* aResult
) {
116 if (IsIsolateHighValueSiteEnabled()) {
117 *aResult
= mIsLoginsLoaded
;
119 // When the feature is disabled, just returns true so testcases don't
120 // block on waiting for us to load logins.
126 ///////////////////////////////////////////////////////////////////////////////
127 // nsILoginSearchObserver implementation
129 LoginDetectionService::OnSearchComplete(
130 const nsTArray
<RefPtr
<nsILoginInfo
>>& aLogins
) {
131 // Add all origins with saved passwords to the permission manager.
132 for (const auto& login
: aLogins
) {
134 login
->GetOrigin(origin
);
136 AddHighValuePermission(NS_ConvertUTF16toUTF8(origin
),
137 mozilla::dom::kHighValueHasSavedLoginPermission
);
140 mIsLoginsLoaded
= true;
144 ///////////////////////////////////////////////////////////////////////////////
145 // nsIObserver implementation
147 LoginDetectionService::Observe(nsISupports
* aSubject
, const char* aTopic
,
148 const char16_t
* aData
) {
149 if ("passwordmgr-form-submission-detected"_ns
.Equals(aTopic
)) {
150 nsDependentString
origin(aData
);
151 AddHighValuePermission(NS_ConvertUTF16toUTF8(origin
),
152 mozilla::dom::kHighValueIsLoggedInPermission
);
158 } // namespace mozilla::dom