mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 874050, Make Nofification's click event cancelable, r=wchen
--HG-- extra : rebase_source : c78a2bb9943c67e9baa7cf9a2af6bbe8188f0040
This commit is contained in:
parent
2ba2c95409
commit
c75b15bcb8
@ -28,8 +28,28 @@ function onLoad() {
|
||||
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
|
||||
tab.linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
notification = win.showNotification();
|
||||
win.newWindow = win.open("about:blank", "", "height=100,width=100");
|
||||
win.newWindow.addEventListener("load", function() {
|
||||
info("new window loaded");
|
||||
win.newWindow.addEventListener("blur", function b() {
|
||||
info("new window got blur");
|
||||
win.newWindow.removeEventListener("blur", b);
|
||||
notification = win.showNotification1();
|
||||
win.newWindow.addEventListener("focus", onNewWindowFocused);
|
||||
notification.addEventListener("show", onAlertShowing);
|
||||
});
|
||||
|
||||
function waitUntilNewWindowHasFocus() {
|
||||
if (!win.newWindow.document.hasFocus()) {
|
||||
setTimeout(waitUntilNewWindowHasFocus, 50);
|
||||
} else {
|
||||
// Focus another window so that new window gets blur event.
|
||||
gBrowser.selectedTab.linkedBrowser.contentWindow.focus();
|
||||
}
|
||||
}
|
||||
win.newWindow.focus();
|
||||
waitUntilNewWindowHasFocus();
|
||||
});
|
||||
}
|
||||
|
||||
function onAlertShowing() {
|
||||
@ -49,6 +69,20 @@ function onAlertShowing() {
|
||||
alertWindow.close();
|
||||
}
|
||||
|
||||
function onNewWindowFocused(event) {
|
||||
event.target.close();
|
||||
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
|
||||
// Using timeout to test that something do *not* happen!
|
||||
setTimeout(openSecondNotification, 50);
|
||||
}
|
||||
|
||||
function openSecondNotification() {
|
||||
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
|
||||
let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
notification = win.showNotification2();
|
||||
notification.addEventListener("show", onAlertShowing);
|
||||
}
|
||||
|
||||
function onTabSelect() {
|
||||
gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
|
||||
is(gBrowser.selectedTab.linkedBrowser.contentWindow.location.href, notificationURL,
|
||||
|
@ -3,7 +3,24 @@
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
function showNotification() {
|
||||
function showNotification1() {
|
||||
var options = {
|
||||
dir: undefined,
|
||||
lang: undefined,
|
||||
body: "Test body",
|
||||
tag: "Test tag",
|
||||
icon: undefined,
|
||||
};
|
||||
var n = new Notification("Test title", options);
|
||||
n.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
dump("Should focus new window.");
|
||||
newWindow.focus();
|
||||
});
|
||||
return n;
|
||||
}
|
||||
|
||||
function showNotification2() {
|
||||
var options = {
|
||||
dir: undefined,
|
||||
lang: undefined,
|
||||
|
@ -76,6 +76,7 @@ Event::ConstructorInit(EventTarget* aOwner,
|
||||
}
|
||||
|
||||
mPrivateDataDuplicated = false;
|
||||
mWantsPopupControlCheck = false;
|
||||
|
||||
if (aEvent) {
|
||||
mEvent = aEvent;
|
||||
@ -655,12 +656,20 @@ PopupAllowedForEvent(const char *eventName)
|
||||
|
||||
// static
|
||||
PopupControlState
|
||||
Event::GetEventPopupControlState(WidgetEvent* aEvent)
|
||||
Event::GetEventPopupControlState(WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent)
|
||||
{
|
||||
// generally if an event handler is running, new windows are disallowed.
|
||||
// check for exceptions:
|
||||
PopupControlState abuse = openAbused;
|
||||
|
||||
if (aDOMEvent && aDOMEvent->InternalDOMEvent()->GetWantsPopupControlCheck()) {
|
||||
nsAutoString type;
|
||||
aDOMEvent->GetType(type);
|
||||
if (PopupAllowedForEvent(NS_ConvertUTF16toUTF8(type).get())) {
|
||||
return openAllowed;
|
||||
}
|
||||
}
|
||||
|
||||
switch(aEvent->mClass) {
|
||||
case eBasicEventClass:
|
||||
// For these following events only allow popups if they're
|
||||
|
@ -30,6 +30,7 @@ namespace dom {
|
||||
class EventTarget;
|
||||
class ErrorEvent;
|
||||
class ProgressEvent;
|
||||
class WantsPopupControlCheck;
|
||||
|
||||
// Dummy class so we can cast through it to get from nsISupports to
|
||||
// Event subclasses with only two non-ambiguous static casts.
|
||||
@ -113,7 +114,8 @@ public:
|
||||
// Returns true if the event should be trusted.
|
||||
bool Init(EventTarget* aGlobal);
|
||||
|
||||
static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent);
|
||||
static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent,
|
||||
nsIDOMEvent* aDOMEvent = nullptr);
|
||||
|
||||
static void PopupAllowedEventsChanged();
|
||||
|
||||
@ -235,6 +237,17 @@ protected:
|
||||
void SetEventType(const nsAString& aEventTypeArg);
|
||||
already_AddRefed<nsIContent> GetTargetFromFrame();
|
||||
|
||||
friend class WantsPopupControlCheck;
|
||||
void SetWantsPopupControlCheck(bool aCheck)
|
||||
{
|
||||
mWantsPopupControlCheck = aCheck;
|
||||
}
|
||||
|
||||
bool GetWantsPopupControlCheck()
|
||||
{
|
||||
return IsTrusted() && mWantsPopupControlCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* IsChrome() returns true if aCx is chrome context or the event is created
|
||||
* in chrome's thread. Otherwise, false.
|
||||
@ -248,6 +261,28 @@ protected:
|
||||
bool mEventIsInternal;
|
||||
bool mPrivateDataDuplicated;
|
||||
bool mIsMainThreadEvent;
|
||||
// True when popup control check should rely on event.type, not
|
||||
// WidgetEvent.message.
|
||||
bool mWantsPopupControlCheck;
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS WantsPopupControlCheck
|
||||
{
|
||||
public:
|
||||
WantsPopupControlCheck(nsIDOMEvent* aEvent) : mEvent(aEvent->InternalDOMEvent())
|
||||
{
|
||||
mOriginalWantsPopupControlCheck = mEvent->GetWantsPopupControlCheck();
|
||||
mEvent->SetWantsPopupControlCheck(mEvent->IsTrusted());
|
||||
}
|
||||
|
||||
~WantsPopupControlCheck()
|
||||
{
|
||||
mEvent->SetWantsPopupControlCheck(mOriginalWantsPopupControlCheck);
|
||||
}
|
||||
|
||||
private:
|
||||
Event* mEvent;
|
||||
bool mOriginalWantsPopupControlCheck;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -976,7 +976,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
nsAutoTObserverArray<Listener, 2>::EndLimitedIterator iter(mListeners);
|
||||
Maybe<nsAutoPopupStatePusher> popupStatePusher;
|
||||
if (mIsMainThreadELM) {
|
||||
popupStatePusher.emplace(Event::GetEventPopupControlState(aEvent));
|
||||
popupStatePusher.emplace(Event::GetEventPopupControlState(aEvent, *aDOMEvent));
|
||||
}
|
||||
|
||||
bool hasListener = false;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#ifdef MOZ_B2G
|
||||
@ -360,19 +361,31 @@ NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = mNotification->GetOwner();
|
||||
if (!window) {
|
||||
if (!window || !window->IsCurrentInnerWindow()) {
|
||||
// Window has been closed, this observer is not valid anymore
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!strcmp("alertclickcallback", aTopic)) {
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
NS_NewDOMEvent(getter_AddRefs(event), mNotification, nullptr, nullptr);
|
||||
nsresult rv = event->InitEvent(NS_LITERAL_STRING("click"), false, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
event->SetTrusted(true);
|
||||
WantsPopupControlCheck popupControlCheck(event);
|
||||
bool doDefaultAction = true;
|
||||
mNotification->DispatchEvent(event, &doDefaultAction);
|
||||
if (doDefaultAction) {
|
||||
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
|
||||
if (doc) {
|
||||
nsContentUtils::DispatchChromeEvent(doc, window,
|
||||
// Browser UI may use DOMWebNotificationClicked to focus the tab
|
||||
// from which the event was dispatched.
|
||||
nsContentUtils::DispatchChromeEvent(doc, window->GetOuterWindow(),
|
||||
NS_LITERAL_STRING("DOMWebNotificationClicked"),
|
||||
true, true);
|
||||
}
|
||||
mNotification->DispatchTrustedEvent(NS_LITERAL_STRING("click"));
|
||||
}
|
||||
} else if (!strcmp("alertfinished", aTopic)) {
|
||||
nsCOMPtr<nsINotificationStorage> notificationStorage =
|
||||
do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID);
|
||||
|
Loading…
Reference in New Issue
Block a user