Bug 1945576, part 2 - Add implementation for Login Status JS hooks - r=anti-tracking-reviewers,timhuang
Differential Revision: https://phabricator.services.mozilla.com/D240218
This commit is contained in:
@@ -98,7 +98,9 @@ static bool ConsumeUserActivation(nsPIDOMWindowInner* aParent) {
|
|||||||
return doc->ConsumeTransientUserGestureActivation();
|
return doc->ConsumeTransientUserGestureActivation();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsSameOriginWithAncestors(nsPIDOMWindowInner* aParent) {
|
// static
|
||||||
|
bool CredentialsContainer::IsSameOriginWithAncestors(
|
||||||
|
nsPIDOMWindowInner* aParent) {
|
||||||
// This method returns true if aParent is either not in a frame / iframe, or
|
// This method returns true if aParent is either not in a frame / iframe, or
|
||||||
// is in a frame or iframe and all ancestors for aParent are the same origin.
|
// is in a frame or iframe and all ancestors for aParent are the same origin.
|
||||||
// This is useful for Credential Management because we need to prohibit
|
// This is useful for Credential Management because we need to prohibit
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ class CredentialsContainer final : public nsISupports, public nsWrapperCache {
|
|||||||
|
|
||||||
already_AddRefed<Promise> PreventSilentAccess(ErrorResult& aRv);
|
already_AddRefed<Promise> PreventSilentAccess(ErrorResult& aRv);
|
||||||
|
|
||||||
|
static bool IsSameOriginWithAncestors(nsPIDOMWindowInner* aParent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~CredentialsContainer();
|
~CredentialsContainer();
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "mozilla/dom/IdentityCredential.h"
|
#include "mozilla/dom/IdentityCredential.h"
|
||||||
#include "mozilla/dom/IdentityCredentialBinding.h"
|
#include "mozilla/dom/IdentityCredentialBinding.h"
|
||||||
#include "mozilla/dom/CredentialManagementBinding.h"
|
#include "mozilla/dom/CredentialManagementBinding.h"
|
||||||
|
#include "mozilla/dom/LoginStatusBinding.h"
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
@@ -81,6 +82,10 @@ struct ParamTraits<mozilla::dom::IdentityCredentialRequestOptions> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::dom::LoginStatus>
|
||||||
|
: public mozilla::dom::WebIDLEnumSerializer<mozilla::dom::LoginStatus> {};
|
||||||
|
|
||||||
} // namespace IPC
|
} // namespace IPC
|
||||||
|
|
||||||
#endif // mozilla_dom_identitycredentialserializationhelpers_h__
|
#endif // mozilla_dom_identitycredentialserializationhelpers_h__
|
||||||
|
|||||||
@@ -4,10 +4,48 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/Components.h"
|
||||||
|
#include "mozilla/dom/CredentialsContainer.h"
|
||||||
|
#include "mozilla/dom/Document.h"
|
||||||
#include "mozilla/dom/NavigatorLogin.h"
|
#include "mozilla/dom/NavigatorLogin.h"
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/dom/WindowGlobalChild.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
#include "nsIGlobalObject.h"
|
||||||
|
#include "nsIPermissionManager.h"
|
||||||
|
#include "nsIPrincipal.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
static constexpr nsLiteralCString kLoginStatusPermission =
|
||||||
|
"self-reported-logged-in"_ns;
|
||||||
|
|
||||||
|
uint32_t ConvertStatusToPermission(LoginStatus aStatus) {
|
||||||
|
if (aStatus == LoginStatus::Logged_in) {
|
||||||
|
return nsIPermissionManager::ALLOW_ACTION;
|
||||||
|
} else if (aStatus == LoginStatus::Logged_out) {
|
||||||
|
return nsIPermissionManager::DENY_ACTION;
|
||||||
|
} else {
|
||||||
|
// This should be unreachable, but let's return a real value
|
||||||
|
return nsIPermissionManager::UNKNOWN_ACTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<LoginStatus> PermissionToStatus(uint32_t aPermission) {
|
||||||
|
if (aPermission == nsIPermissionManager::ALLOW_ACTION) {
|
||||||
|
return Some(LoginStatus::Logged_in);
|
||||||
|
} else if (aPermission == nsIPermissionManager::DENY_ACTION) {
|
||||||
|
return Some(LoginStatus::Logged_out);
|
||||||
|
} else {
|
||||||
|
if (aPermission == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||||
|
MOZ_ASSERT(false, "Unexpected permission action from login status");
|
||||||
|
}
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(NavigatorLogin, mOwner)
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(NavigatorLogin, mOwner)
|
||||||
|
|
||||||
@@ -18,21 +56,91 @@ JSObject* NavigatorLogin::WrapObject(JSContext* aCx,
|
|||||||
return NavigatorLogin_Binding::Wrap(aCx, this, aGivenProto);
|
return NavigatorLogin_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigatorLogin::NavigatorLogin(nsIGlobalObject* aGlobal)
|
NavigatorLogin::NavigatorLogin(nsIGlobalObject* aGlobal) : mOwner(aGlobal) {
|
||||||
: mOwner(aGlobal){
|
MOZ_ASSERT(mOwner);
|
||||||
MOZ_ASSERT(mOwner);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
already_AddRefed<mozilla::dom::Promise> NavigatorLogin::SetStatus(
|
already_AddRefed<mozilla::dom::Promise> NavigatorLogin::SetStatus(
|
||||||
const LoginStatus& aStatus, mozilla::ErrorResult& aRv) {
|
LoginStatus aStatus, mozilla::ErrorResult& aRv) {
|
||||||
|
|
||||||
RefPtr<Promise> promise = Promise::Create(mOwner, aRv);
|
RefPtr<Promise> promise = Promise::Create(mOwner, aRv);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
promise->MaybeRejectWithNotSupportedError(
|
|
||||||
"navigator.login.setStatus not implemented"_ns);
|
nsPIDOMWindowInner* window = mOwner->GetAsInnerWindow();
|
||||||
|
if (!window) {
|
||||||
|
promise->MaybeRejectWithUnknownError(
|
||||||
|
"navigator.login.setStatus called on unavailable window"_ns);
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CredentialsContainer::IsSameOriginWithAncestors(window)) {
|
||||||
|
promise->MaybeRejectWithSecurityError(
|
||||||
|
"navigator.login.setStatus must be called in a frame that is same-origin with its ancestors"_ns);
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowGlobalChild* wgc = window->GetWindowGlobalChild();
|
||||||
|
if (!wgc) {
|
||||||
|
promise->MaybeRejectWithUnknownError(
|
||||||
|
"navigator.login.setStatus called while window already destroyed"_ns);
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
wgc->SendSetLoginStatus(aStatus)->Then(
|
||||||
|
GetCurrentSerialEventTarget(), __func__,
|
||||||
|
[promise](
|
||||||
|
const WindowGlobalChild::SetLoginStatusPromise::ResolveValueType&
|
||||||
|
aResult) {
|
||||||
|
if (NS_SUCCEEDED(aResult)) {
|
||||||
|
promise->MaybeResolveWithUndefined();
|
||||||
|
} else {
|
||||||
|
promise->MaybeRejectWithUnknownError(
|
||||||
|
"navigator.login.setStatus had an unexpected internal error");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[promise](const WindowGlobalChild::SetLoginStatusPromise::RejectValueType&
|
||||||
|
aResult) {
|
||||||
|
promise->MaybeRejectWithUnknownError(
|
||||||
|
"navigator.login.setStatus had an unexpected internal error");
|
||||||
|
});
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
// static
|
||||||
|
nsresult NavigatorLogin::SetLoginStatus(nsIPrincipal* aPrincipal,
|
||||||
|
LoginStatus aStatus) {
|
||||||
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPermissionManager> permMgr =
|
||||||
|
components::PermissionManager::Service();
|
||||||
|
if (!permMgr) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return permMgr->AddFromPrincipal(aPrincipal, kLoginStatusPermission,
|
||||||
|
ConvertStatusToPermission(aStatus),
|
||||||
|
nsIPermissionManager::EXPIRE_NEVER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult GetLoginStatus(nsIPrincipal* aPrincipal, Maybe<LoginStatus>& aStatus) {
|
||||||
|
nsCOMPtr<nsIPermissionManager> permMgr =
|
||||||
|
components::PermissionManager::Service();
|
||||||
|
if (!permMgr) {
|
||||||
|
aStatus = Nothing();
|
||||||
|
return NS_ERROR_SERVICE_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
uint32_t action;
|
||||||
|
nsresult rv = permMgr->TestPermissionFromPrincipal(
|
||||||
|
aPrincipal, kLoginStatusPermission, &action);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
aStatus = Nothing();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
aStatus = PermissionToStatus(action);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -7,7 +7,10 @@
|
|||||||
#ifndef mozilla_dom_NavigatorLogin_h
|
#ifndef mozilla_dom_NavigatorLogin_h
|
||||||
#define mozilla_dom_NavigatorLogin_h
|
#define mozilla_dom_NavigatorLogin_h
|
||||||
|
|
||||||
|
#include "ErrorList.h"
|
||||||
#include "mozilla/dom/LoginStatusBinding.h"
|
#include "mozilla/dom/LoginStatusBinding.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "nsIGlobalObject.h"
|
||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
@@ -24,9 +27,12 @@ class NavigatorLogin : public nsWrapperCache {
|
|||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
virtual JSObject* WrapObject(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
already_AddRefed<mozilla::dom::Promise> SetStatus(const LoginStatus& aStatus,
|
already_AddRefed<mozilla::dom::Promise> SetStatus(LoginStatus aStatus,
|
||||||
mozilla::ErrorResult& aRv);
|
mozilla::ErrorResult& aRv);
|
||||||
|
|
||||||
|
static Maybe<LoginStatus> GetLoginStatus(nsIPrincipal* aPrincipal);
|
||||||
|
static nsresult SetLoginStatus(nsIPrincipal* aPrincipal, LoginStatus aStatus);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~NavigatorLogin();
|
virtual ~NavigatorLogin();
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ using mozilla::dom::IdentityCredentialDisconnectOptions from "mozilla/dom/Identi
|
|||||||
using mozilla::dom::IdentityCredentialInit from "mozilla/dom/IdentityCredentialBinding.h";
|
using mozilla::dom::IdentityCredentialInit from "mozilla/dom/IdentityCredentialBinding.h";
|
||||||
using mozilla::dom::IdentityCredentialRequestOptions from "mozilla/dom/IdentityCredentialBinding.h";
|
using mozilla::dom::IdentityCredentialRequestOptions from "mozilla/dom/IdentityCredentialBinding.h";
|
||||||
using mozilla::dom::IdentityLoginTargetType from "mozilla/dom/IdentityCredentialBinding.h";
|
using mozilla::dom::IdentityLoginTargetType from "mozilla/dom/IdentityCredentialBinding.h";
|
||||||
|
using mozilla::dom::LoginStatus from "mozilla/dom/LoginStatusBinding.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@@ -218,6 +219,9 @@ parent:
|
|||||||
async DisconnectIdentityCredential(IdentityCredentialDisconnectOptions aOptions) returns (nsresult rv);
|
async DisconnectIdentityCredential(IdentityCredentialDisconnectOptions aOptions) returns (nsresult rv);
|
||||||
async PreventSilentAccess() returns (nsresult rv);
|
async PreventSilentAccess() returns (nsresult rv);
|
||||||
|
|
||||||
|
// Indicate that the page has reported itself as logged in
|
||||||
|
async SetLoginStatus(LoginStatus foo) returns (nsresult rv);
|
||||||
|
|
||||||
async GetStorageAccessPermission(bool aIncludeIdentityCredential) returns(uint32_t permission_action);
|
async GetStorageAccessPermission(bool aIncludeIdentityCredential) returns(uint32_t permission_action);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "mozilla/dom/BrowserParent.h"
|
#include "mozilla/dom/BrowserParent.h"
|
||||||
#include "mozilla/dom/IdentityCredential.h"
|
#include "mozilla/dom/IdentityCredential.h"
|
||||||
#include "mozilla/dom/MediaController.h"
|
#include "mozilla/dom/MediaController.h"
|
||||||
|
#include "mozilla/dom/NavigatorLogin.h"
|
||||||
#include "mozilla/dom/WebAuthnTransactionParent.h"
|
#include "mozilla/dom/WebAuthnTransactionParent.h"
|
||||||
#include "mozilla/dom/WindowGlobalChild.h"
|
#include "mozilla/dom/WindowGlobalChild.h"
|
||||||
#include "mozilla/dom/ChromeUtils.h"
|
#include "mozilla/dom/ChromeUtils.h"
|
||||||
@@ -1503,6 +1504,18 @@ IPCResult WindowGlobalParent::RecvPreventSilentAccess(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult WindowGlobalParent::RecvSetLoginStatus(
|
||||||
|
LoginStatus aStatus, const SetLoginStatusResolver& aResolver) {
|
||||||
|
nsIPrincipal* principal = DocumentPrincipal();
|
||||||
|
if (!principal) {
|
||||||
|
aResolver(NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
nsresult rv = NavigatorLogin::SetLoginStatus(principal, aStatus);
|
||||||
|
aResolver(rv);
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
IPCResult WindowGlobalParent::RecvGetStorageAccessPermission(
|
IPCResult WindowGlobalParent::RecvGetStorageAccessPermission(
|
||||||
bool aIncludeIdentityCredential,
|
bool aIncludeIdentityCredential,
|
||||||
GetStorageAccessPermissionResolver&& aResolve) {
|
GetStorageAccessPermissionResolver&& aResolve) {
|
||||||
|
|||||||
@@ -328,6 +328,9 @@ class WindowGlobalParent final : public WindowContext,
|
|||||||
mozilla::ipc::IPCResult RecvDisconnectIdentityCredential(
|
mozilla::ipc::IPCResult RecvDisconnectIdentityCredential(
|
||||||
const IdentityCredentialDisconnectOptions& aOptions,
|
const IdentityCredentialDisconnectOptions& aOptions,
|
||||||
const DisconnectIdentityCredentialResolver& aResolver);
|
const DisconnectIdentityCredentialResolver& aResolver);
|
||||||
|
mozilla::ipc::IPCResult RecvSetLoginStatus(
|
||||||
|
LoginStatus aStatus, const SetLoginStatusResolver& aResolver);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvPreventSilentAccess(
|
mozilla::ipc::IPCResult RecvPreventSilentAccess(
|
||||||
const PreventSilentAccessResolver& aResolver);
|
const PreventSilentAccessResolver& aResolver);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user