tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

LoginDetectionService.cpp (5150B)


      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/. */
      6 
      7 #include "LoginDetectionService.h"
      8 
      9 #include "mozilla/ClearOnShutdown.h"
     10 #include "mozilla/StaticPrefs_fission.h"
     11 #include "mozilla/dom/ProcessIsolation.h"
     12 #include "nsILoginInfo.h"
     13 #include "nsILoginManager.h"
     14 #include "nsIObserver.h"
     15 #include "nsIXULRuntime.h"
     16 #include "nsServiceManagerUtils.h"
     17 #include "nsXULAppAPI.h"
     18 
     19 namespace mozilla::dom {
     20 
     21 static StaticRefPtr<LoginDetectionService> gLoginDetectionService;
     22 
     23 namespace {
     24 
     25 void OnFissionPrefsChange(const char* aPrefName, void* aData) {
     26  MOZ_ASSERT(gLoginDetectionService);
     27 
     28  gLoginDetectionService->MaybeStartMonitoring();
     29 }
     30 
     31 }  // namespace
     32 
     33 NS_IMPL_ISUPPORTS(LoginDetectionService, nsILoginDetectionService,
     34                  nsILoginSearchCallback, nsIObserver, nsISupportsWeakReference)
     35 
     36 // static
     37 already_AddRefed<LoginDetectionService> LoginDetectionService::GetSingleton() {
     38  if (gLoginDetectionService) {
     39    return do_AddRef(gLoginDetectionService);
     40  }
     41 
     42  gLoginDetectionService = new LoginDetectionService();
     43  ClearOnShutdown(&gLoginDetectionService);
     44 
     45  return do_AddRef(gLoginDetectionService);
     46 }
     47 
     48 LoginDetectionService::LoginDetectionService() : mIsLoginsLoaded(false) {}
     49 LoginDetectionService::~LoginDetectionService() { UnregisterObserver(); }
     50 
     51 void LoginDetectionService::MaybeStartMonitoring() {
     52  if (IsIsolateHighValueSiteEnabled()) {
     53    // We want to isolate sites with a saved password, so fetch saved logins
     54    // from the password manager, and then add the 'HighValue' permission.
     55 
     56    // Note that we don't monitor whether a login is added or removed after
     57    // logins are fetched. For adding logins, this will be covered by form
     58    // submission detection heuristic. As for removing logins, it doesn't
     59    // provide security benefit just to NOT isolate the removed site. The site
     60    // will not be isolated when its permission expired.
     61    FetchLogins();
     62  }
     63 
     64  if (IsIsolateHighValueSiteEnabled() ||
     65      StaticPrefs::fission_highValue_login_monitor()) {
     66    // When the pref is on, we monitor users' login attempt event when we
     67    // are not isolating high value sites. This is because We can't detect the
     68    // case where a user is already logged in to a site, and don't save a
     69    // password for it. So we want to start monitoring login attempts prior
     70    // to releasing the feature.
     71    if (!mObs) {
     72      mObs = mozilla::services::GetObserverService();
     73      mObs->AddObserver(this, "passwordmgr-form-submission-detected", false);
     74    }
     75  } else {
     76    UnregisterObserver();
     77  }
     78 }
     79 
     80 void LoginDetectionService::FetchLogins() {
     81  nsresult rv;
     82  nsCOMPtr<nsILoginManager> loginManager =
     83      do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
     84  if (NS_WARN_IF(!loginManager)) {
     85    return;
     86  }
     87 
     88  (void)loginManager->GetAllLoginsWithCallback(this);
     89 }
     90 
     91 void LoginDetectionService::UnregisterObserver() {
     92  if (mObs) {
     93    mObs->RemoveObserver(this, "passwordmgr-form-submission-detected");
     94    mObs = nullptr;
     95  }
     96 }
     97 
     98 ///////////////////////////////////////////////////////////////////////////////
     99 // nsILoginDetectionService implementation
    100 NS_IMETHODIMP LoginDetectionService::Init() {
    101  if (XRE_IsContentProcess()) {
    102    return NS_OK;
    103  }
    104 
    105  Preferences::RegisterCallback(OnFissionPrefsChange, "fission.autostart");
    106  Preferences::RegisterCallback(OnFissionPrefsChange,
    107                                "fission.webContentIsolationStrategy");
    108 
    109  MaybeStartMonitoring();
    110 
    111  return NS_OK;
    112 }
    113 
    114 NS_IMETHODIMP LoginDetectionService::IsLoginsLoaded(bool* aResult) {
    115  if (IsIsolateHighValueSiteEnabled()) {
    116    *aResult = mIsLoginsLoaded;
    117  } else {
    118    // When the feature is disabled, just returns true so testcases don't
    119    // block on waiting for us to load logins.
    120    *aResult = true;
    121  }
    122  return NS_OK;
    123 }
    124 
    125 ///////////////////////////////////////////////////////////////////////////////
    126 // nsILoginSearchObserver implementation
    127 NS_IMETHODIMP
    128 LoginDetectionService::OnSearchComplete(
    129    const nsTArray<RefPtr<nsILoginInfo>>& aLogins) {
    130  // Add all origins with saved passwords to the permission manager.
    131  for (const auto& login : aLogins) {
    132    nsString origin;
    133    login->GetOrigin(origin);
    134 
    135    AddHighValuePermission(NS_ConvertUTF16toUTF8(origin),
    136                           mozilla::dom::kHighValueHasSavedLoginPermission);
    137  }
    138 
    139  mIsLoginsLoaded = true;
    140  return NS_OK;
    141 }
    142 
    143 ///////////////////////////////////////////////////////////////////////////////
    144 // nsIObserver implementation
    145 NS_IMETHODIMP
    146 LoginDetectionService::Observe(nsISupports* aSubject, const char* aTopic,
    147                               const char16_t* aData) {
    148  if ("passwordmgr-form-submission-detected"_ns.Equals(aTopic)) {
    149    nsDependentString origin(aData);
    150    AddHighValuePermission(NS_ConvertUTF16toUTF8(origin),
    151                           mozilla::dom::kHighValueIsLoggedInPermission);
    152  }
    153 
    154  return NS_OK;
    155 }
    156 
    157 }  // namespace mozilla::dom