358 lines
9.4 KiB
C++
358 lines
9.4 KiB
C++
/* 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/. */
|
|
|
|
#include "mozilla/AlertNotification.h"
|
|
|
|
#include "imgIContainer.h"
|
|
#include "imgINotificationObserver.h"
|
|
#include "imgIRequest.h"
|
|
#include "imgLoader.h"
|
|
#include "nsAlertsUtils.h"
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsDirectoryServiceUtils.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "mozilla/BasePrincipal.h"
|
|
|
|
namespace mozilla {
|
|
|
|
NS_IMPL_ISUPPORTS(AlertNotification, nsIAlertNotification)
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::Init(const nsAString& aName, const nsAString& aImageURL,
|
|
const nsAString& aTitle, const nsAString& aText,
|
|
bool aTextClickable, const nsAString& aCookie,
|
|
const nsAString& aDir, const nsAString& aLang,
|
|
const nsAString& aData, nsIPrincipal* aPrincipal,
|
|
bool aInPrivateBrowsing, bool aRequireInteraction,
|
|
bool aSilent, const nsTArray<uint32_t>& aVibrate) {
|
|
if (!mId.IsEmpty()) {
|
|
return NS_ERROR_ALREADY_INITIALIZED;
|
|
}
|
|
|
|
mName = aName;
|
|
mImageURL = aImageURL;
|
|
mTitle = aTitle;
|
|
mText = aText;
|
|
mTextClickable = aTextClickable;
|
|
mCookie = aCookie;
|
|
mDir = aDir;
|
|
mLang = aLang;
|
|
mData = aData;
|
|
mPrincipal = aPrincipal;
|
|
mInPrivateBrowsing = aInPrivateBrowsing;
|
|
mRequireInteraction = aRequireInteraction;
|
|
mSilent = aSilent;
|
|
mVibrate = aVibrate.Clone();
|
|
|
|
return InitId();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::InitWithObject(nsIAlertNotification* aAlertNotification) {
|
|
MOZ_TRY(aAlertNotification->GetName(mName));
|
|
MOZ_TRY(aAlertNotification->GetImageURL(mImageURL));
|
|
MOZ_TRY(aAlertNotification->GetImage(getter_AddRefs(mImage)));
|
|
MOZ_TRY(aAlertNotification->GetTitle(mTitle));
|
|
MOZ_TRY(aAlertNotification->GetText(mText));
|
|
MOZ_TRY(aAlertNotification->GetTextClickable(&mTextClickable));
|
|
MOZ_TRY(aAlertNotification->GetCookie(mCookie));
|
|
MOZ_TRY(aAlertNotification->GetDir(mDir));
|
|
MOZ_TRY(aAlertNotification->GetLang(mLang));
|
|
MOZ_TRY(aAlertNotification->GetData(mData));
|
|
MOZ_TRY(aAlertNotification->GetPrincipal(getter_AddRefs(mPrincipal)));
|
|
MOZ_TRY(aAlertNotification->GetInPrivateBrowsing(&mInPrivateBrowsing));
|
|
MOZ_TRY(aAlertNotification->GetRequireInteraction(&mRequireInteraction));
|
|
MOZ_TRY(aAlertNotification->GetSilent(&mSilent));
|
|
if (NS_FAILED(aAlertNotification->GetVibrate(mVibrate))) {
|
|
mVibrate.Clear();
|
|
};
|
|
nsTArray<RefPtr<nsIAlertAction>> actions;
|
|
if (NS_SUCCEEDED(aAlertNotification->GetActions(actions))) {
|
|
for (auto& action : actions) {
|
|
if (RefPtr<nsIAlertAction> copied =
|
|
AlertAction::Copy(*action).unwrapOr(nullptr)) {
|
|
mActions.AppendElement(copied);
|
|
}
|
|
}
|
|
};
|
|
return InitId();
|
|
}
|
|
|
|
nsresult AlertNotification::InitId() {
|
|
nsAutoString id;
|
|
|
|
// Multiple profiles might overwrite each other's toast messages when a
|
|
// common name is used for a given origin. We prevent this by including
|
|
// the profile directory as part of the toast hash.
|
|
nsCOMPtr<nsIFile> profDir;
|
|
MOZ_TRY(NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
|
getter_AddRefs(profDir)));
|
|
MOZ_TRY(profDir->Normalize());
|
|
MOZ_TRY(profDir->GetPath(id));
|
|
|
|
if (mPrincipal && mPrincipal->GetIsContentPrincipal()) {
|
|
// Notification originated from a web notification.
|
|
nsAutoCString origin;
|
|
MOZ_TRY(mPrincipal->GetOrigin(origin));
|
|
id += NS_ConvertUTF8toUTF16(origin);
|
|
} else {
|
|
id += u"chrome";
|
|
}
|
|
|
|
if (mName.IsEmpty()) {
|
|
// No associated name, append a UUID to prevent reuse of the same tag.
|
|
nsIDToCString uuidString(nsID::GenerateUUID());
|
|
size_t len = strlen(uuidString.get());
|
|
MOZ_ASSERT(len == NSID_LENGTH - 1);
|
|
nsAutoString uuid;
|
|
CopyASCIItoUTF16(nsDependentCSubstring(uuidString.get(), len), uuid);
|
|
|
|
id += u"#notag:"_ns;
|
|
id += uuid;
|
|
} else {
|
|
id += u"#tag:"_ns;
|
|
id += mName;
|
|
}
|
|
|
|
// Windows notification tags are limited to 16 characters, or 64 characters
|
|
// after the Creators Update; therefore we hash the tag to fit the minimum
|
|
// range.
|
|
HashNumber hash = HashString(id);
|
|
mId.AppendPrintf("%010u", hash);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP AlertNotification::GetId(nsAString& aId) {
|
|
if (mId.IsEmpty()) {
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
}
|
|
aId = mId;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::SetActions(
|
|
const nsTArray<RefPtr<nsIAlertAction>>& aActions) {
|
|
mActions = aActions.Clone();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetName(nsAString& aName) {
|
|
if (mPrincipal && mPrincipal->GetIsContentPrincipal()) {
|
|
// mName is no longer unique, but there has been a long assumption
|
|
// throughout the codebase that GetName will be unique. So we return mId for
|
|
// GetName for web triggered notifications to keep uniqueness without
|
|
// accidentially causing subtle breakage in other modules.
|
|
aName = mId;
|
|
} else {
|
|
// System callers has always been expected to provide unique names
|
|
// themselves, so it's fine to return mName as is.
|
|
aName = mName;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetImageURL(nsAString& aImageURL) {
|
|
aImageURL = mImageURL;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::SetImage(imgIContainer* aImage) {
|
|
mImage = aImage;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetImage(imgIContainer** aImage) {
|
|
nsCOMPtr<imgIContainer> image = mImage;
|
|
image.forget(aImage);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetTitle(nsAString& aTitle) {
|
|
aTitle = mTitle;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetText(nsAString& aText) {
|
|
aText = mText;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetTextClickable(bool* aTextClickable) {
|
|
*aTextClickable = mTextClickable;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetCookie(nsAString& aCookie) {
|
|
aCookie = mCookie;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetDir(nsAString& aDir) {
|
|
aDir = mDir;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetLang(nsAString& aLang) {
|
|
aLang = mLang;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetRequireInteraction(bool* aRequireInteraction) {
|
|
*aRequireInteraction = mRequireInteraction;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetData(nsAString& aData) {
|
|
aData = mData;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetPrincipal(nsIPrincipal** aPrincipal) {
|
|
NS_IF_ADDREF(*aPrincipal = mPrincipal);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetURI(nsIURI** aURI) {
|
|
if (!nsAlertsUtils::IsActionablePrincipal(mPrincipal)) {
|
|
*aURI = nullptr;
|
|
return NS_OK;
|
|
}
|
|
auto* basePrin = BasePrincipal::Cast(mPrincipal);
|
|
return basePrin->GetURI(aURI);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetInPrivateBrowsing(bool* aInPrivateBrowsing) {
|
|
*aInPrivateBrowsing = mInPrivateBrowsing;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetActionable(bool* aActionable) {
|
|
*aActionable = nsAlertsUtils::IsActionablePrincipal(mPrincipal);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetSilent(bool* aSilent) {
|
|
*aSilent = mSilent;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetVibrate(nsTArray<uint32_t>& aVibrate) {
|
|
aVibrate = mVibrate.Clone();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetActions(nsTArray<RefPtr<nsIAlertAction>>& aActions) {
|
|
aActions = mActions.Clone();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetSource(nsAString& aSource) {
|
|
nsAlertsUtils::GetSourceHostPort(mPrincipal, aSource);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetOrigin(nsACString& aOrigin) {
|
|
return nsAlertsUtils::GetOrigin(mPrincipal, aOrigin);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetOpaqueRelaunchData(nsAString& aOpaqueRelaunchData) {
|
|
aOpaqueRelaunchData = mOpaqueRelaunchData;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::SetOpaqueRelaunchData(const nsAString& aOpaqueRelaunchData) {
|
|
mOpaqueRelaunchData = aOpaqueRelaunchData;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertNotification::GetAction(const nsAString& aName,
|
|
nsIAlertAction** aAlertAction) {
|
|
NS_ENSURE_ARG_POINTER(aAlertAction);
|
|
for (const auto& action : mActions) {
|
|
nsString name;
|
|
MOZ_TRY(action->GetAction(name));
|
|
if (name.Equals(aName)) {
|
|
RefPtr<nsIAlertAction> match = action;
|
|
match.forget(aAlertAction);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
*aAlertAction = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(AlertAction, nsIAlertAction)
|
|
|
|
AlertAction::AlertAction(const nsAString& aAction, const nsAString& aTitle)
|
|
: mAction(aAction), mTitle(aTitle) {}
|
|
|
|
Result<already_AddRefed<AlertAction>, nsresult> AlertAction::Copy(
|
|
nsIAlertAction& aAction) {
|
|
nsAutoString action;
|
|
nsAutoString title;
|
|
MOZ_TRY(aAction.GetAction(action));
|
|
MOZ_TRY(aAction.GetTitle(title));
|
|
return do_AddRef(new AlertAction(action, title));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertAction::GetAction(nsAString& aAction) {
|
|
aAction = mAction;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertAction::GetTitle(nsAString& aTitle) {
|
|
aTitle = mTitle;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertAction::GetIconURL(nsAString& aTitle) {
|
|
aTitle.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertAction::GetWindowsSystemActivationType(bool* aType) {
|
|
*aType = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AlertAction::GetOpaqueRelaunchData(nsAString& aData) {
|
|
aData.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla
|