Skip to content
Browse files

Fixing bug 68215. Adding support for the onbeforeunload event. r=pete…

…rv@propagandism.org, sr=brendan@mozilla.org
  • Loading branch information...
1 parent 2703a27 commit 64ad19a8011d2c468ba07c1e78759d9046a24fbd jst%mozilla.jstenback.com committed Feb 11, 2004
Showing with 630 additions and 330 deletions.
  1. +109 −3 content/base/src/nsDocumentViewer.cpp
  2. +22 −0 content/base/src/nsSyncLoadService.cpp
  3. +53 −51 content/events/src/nsDOMEvent.cpp
  4. +1 −0 content/events/src/nsDOMEvent.h
  5. +46 −148 content/events/src/nsEventListenerManager.cpp
  6. +6 −5 content/events/src/nsEventListenerManager.h
  7. +1 −0 content/html/content/src/nsGenericHTMLElement.cpp
  8. +3 −3 content/html/content/src/nsHTMLScriptElement.cpp
  9. +20 −3 content/html/document/src/nsHTMLDocument.cpp
  10. +1 −0 content/shared/public/nsLayoutAtomList.h
  11. +1 −0 content/xbl/src/nsXBLService.cpp
  12. +40 −20 docshell/base/nsDocShell.cpp
  13. +13 −13 docshell/base/nsDocShell.h
  14. +1 −0 docshell/base/nsIContentViewer.idl
  15. +7 −0 dom/public/coreEvents/nsIDOMLoadListener.h
  16. +3 −3 dom/public/nsIScriptContext.h
  17. +3 −1 dom/resources/locale/dom.properties
  18. +1 −0 dom/src/base/nsDOMClassInfo.h
  19. +9 −3 dom/src/base/nsGlobalWindow.cpp
  20. +9 −9 dom/src/base/nsJSEnvironment.cpp
  21. +2 −3 dom/src/base/nsJSEnvironment.h
  22. +35 −9 dom/src/events/nsJSEventListener.cpp
  23. +32 −4 dom/src/jsurl/nsJSProtocolHandler.cpp
  24. +6 −0 extensions/xmlextras/base/src/nsDOMParser.cpp
  25. +1 −0 extensions/xmlextras/base/src/nsDOMParser.h
  26. +12 −0 extensions/xmlextras/base/src/nsLoadListenerProxy.cpp
  27. +1 −0 extensions/xmlextras/base/src/nsLoadListenerProxy.h
  28. +6 −0 extensions/xmlextras/base/src/nsXMLHttpRequest.cpp
  29. +1 −0 extensions/xmlextras/base/src/nsXMLHttpRequest.h
  30. +109 −3 layout/base/nsDocumentViewer.cpp
  31. +1 −0 layout/base/nsLayoutAtomList.h
  32. +37 −24 widget/public/nsGUIEvent.h
  33. +18 −19 xpfe/appshell/src/nsWebShellWindow.cpp
  34. +10 −1 xpfe/browser/resources/content/navigator.js
  35. +10 −5 xpfe/global/resources/content/bindings/tabbrowser.xml
View
112 content/base/src/nsDocumentViewer.cpp
@@ -199,6 +199,10 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
static NS_DEFINE_CID(kGalleyContextCID, NS_GALLEYCONTEXT_CID);
+static const char kDOMStringBundleURL[] =
+ "chrome://communicator/locale/dom/dom.properties";
+
+
#ifdef NS_DEBUG
#undef NOISY_VIEWER
@@ -414,9 +418,11 @@ class DocumentViewerImpl : public nsIDocumentViewer,
nsIWidget* mParentWidget; // purposely won't be ref counted
+ PRPackedBool mInPermitUnload;
+
#ifdef NS_PRINTING
+ PRPackedBool mClosingWhilePrinting;
nsPrintEngine* mPrintEngine;
- PRBool mClosingWhilePrinting;
nsCOMPtr<nsIDOMWindowInternal> mDialogParentWin;
#if NS_PRINT_PREVIEW
// These data member support delayed printing when the document is loading
@@ -962,6 +968,104 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
}
NS_IMETHODIMP
+DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
+{
+ *aPermitUnload = PR_TRUE;
+
+ if (!mDocument || mInPermitUnload) {
+ return NS_OK;
+ }
+
+ // First, get the script global object from the document...
+ nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
+
+ if (!global) {
+ // This is odd, but not fatal
+ NS_WARNING("nsIScriptGlobalObject not set for document!");
+ return NS_OK;
+ }
+
+ // Now, fire an BeforeUnload event to the document and see if it's ok
+ // to unload...
+ nsEventStatus status = nsEventStatus_eIgnore;
+ nsBeforePageUnloadEvent event(NS_BEFORE_PAGE_UNLOAD);
+
+ // In evil cases we might be destroyed while handling the
+ // onbeforeunload event, don't let that happen.
+ nsRefPtr<DocumentViewerImpl> kungFuDeathGrip(this);
+
+ mInPermitUnload = PR_TRUE;
+ nsresult rv = global->HandleDOMEvent(mPresContext, &event, nsnull,
+ NS_EVENT_FLAG_INIT, &status);
+ mInPermitUnload = PR_FALSE;
+
+ if (NS_SUCCEEDED(rv) && event.flags & NS_EVENT_FLAG_NO_DEFAULT) {
+ // Ask the user if it's ok to unload the current page
+
+ nsCOMPtr<nsIPrompt> prompt(do_GetInterface(mContainer));
+
+ if (prompt) {
+ nsCOMPtr<nsIStringBundleService>
+ stringService(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
+ NS_ENSURE_TRUE(stringService, NS_OK);
+
+ nsCOMPtr<nsIStringBundle> bundle;
+ stringService->CreateBundle(kDOMStringBundleURL, getter_AddRefs(bundle));
+ NS_ENSURE_TRUE(bundle, NS_OK);
+
+ nsXPIDLString preMsg, postMsg;
+ nsresult rv;
+ rv = bundle->GetStringFromName(NS_LITERAL_STRING("OnBeforeUnloadPreMessage").get(), getter_Copies(preMsg));
+ rv |= bundle->GetStringFromName(NS_LITERAL_STRING("OnBeforeUnloadPostMessage").get(), getter_Copies(postMsg));
+
+ // GetStringFromName can succeed, yet give NULL strings back.
+ if (NS_FAILED(rv) || !preMsg || !postMsg) {
+ NS_ERROR("Failed to get strings from dom.properties!");
+ return NS_OK;
+ }
+
+ // Limit the length of the text the page can inject into this
+ // dialogue to 1024 characters.
+ PRInt32 len = PR_MIN(event.text.Length(), 1024);
+
+ nsAutoString msg(preMsg + NS_LITERAL_STRING("\n\n") +
+ StringHead(event.text, len) +
+ NS_LITERAL_STRING("\n\n") + postMsg);
+
+ // This doesn't pass a title, which makes the title be
+ // "Confirm", is that ok, or do we want a localizable title for
+ // this dialogue?
+ if (NS_FAILED(prompt->Confirm(nsnull, msg.get(), aPermitUnload))) {
+ *aPermitUnload = PR_TRUE;
+ }
+ }
+ }
+
+ nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryInterface(mContainer));
+
+ if (docShellNode) {
+ PRInt32 childCount;
+ docShellNode->GetChildCount(&childCount);
+
+ for (PRInt32 i = 0; i < childCount && *aPermitUnload; ++i) {
+ nsCOMPtr<nsIDocShellTreeItem> item;
+ docShellNode->GetChildAt(i, getter_AddRefs(item));
+
+ nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(item));
+ nsCOMPtr<nsIContentViewer> cv;
+
+ docShell->GetContentViewer(getter_AddRefs(cv));
+
+ if (cv) {
+ cv->PermitUnload(aPermitUnload);
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
DocumentViewerImpl::Unload()
{
mEnableRendering = PR_FALSE;
@@ -971,11 +1075,11 @@ DocumentViewerImpl::Unload()
}
// First, get the script global object from the document...
- nsCOMPtr<nsIScriptGlobalObject> global = mDocument->GetScriptGlobalObject();
+ nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
if (!global) {
// Fail if no ScriptGlobalObject is available...
- NS_ASSERTION(0, "nsIScriptGlobalObject not set for document!");
+ NS_ERROR("nsIScriptGlobalObject not set for document!");
return NS_ERROR_NULL_POINTER;
}
@@ -1121,6 +1225,8 @@ DocumentViewerImpl::Destroy()
mPresShell = nsnull;
}
+ mContainer = nsnull;
+
return NS_OK;
}
View
22 content/base/src/nsSyncLoadService.cpp
@@ -117,6 +117,7 @@ class nsSyncLoader : public nsIDOMLoadListener,
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent* aEvent);
+ NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
NS_IMETHOD Error(nsIDOMEvent* aEvent);
@@ -157,6 +158,7 @@ class txLoadListenerProxy : public nsIDOMLoadListener {
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent* aEvent);
+ NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
NS_IMETHOD Error(nsIDOMEvent* aEvent);
@@ -201,6 +203,18 @@ txLoadListenerProxy::Load(nsIDOMEvent* aEvent)
}
NS_IMETHODIMP
+txLoadListenerProxy::BeforeUnload(nsIDOMEvent* aEvent)
+{
+ nsCOMPtr<nsIDOMLoadListener> listener = do_QueryReferent(mParent);
+
+ if (listener) {
+ return listener->BeforeUnload(aEvent);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
txLoadListenerProxy::Unload(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIDOMLoadListener> listener = do_QueryReferent(mParent);
@@ -466,6 +480,14 @@ nsSyncLoader::Load(nsIDOMEvent* aEvent)
}
nsresult
+nsSyncLoader::BeforeUnload(nsIDOMEvent* aEvent)
+{
+ // Like, whatever.
+
+ return NS_OK;
+}
+
+nsresult
nsSyncLoader::Unload(nsIDOMEvent* aEvent)
{
return NS_OK;
View
104 content/events/src/nsDOMEvent.cpp
@@ -64,10 +64,10 @@
#include "nsIDOMMutationEvent.h"
#include "nsIURI.h"
-static const char* const mEventNames[] = {
+static const char* const sEventNames[] = {
"mousedown", "mouseup", "click", "dblclick", "mouseover",
"mouseout", "mousemove", "contextmenu", "keydown", "keyup", "keypress",
- "focus", "blur", "load", "unload", "abort", "error",
+ "focus", "blur", "load", "beforeunload", "unload", "abort", "error",
"submit", "reset", "change", "select", "input", "paint" ,"text",
"popupshowing", "popupshown", "popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize",
@@ -1482,113 +1482,115 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
case NS_MOUSE_LEFT_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_RIGHT_BUTTON_DOWN:
- return mEventNames[eDOMEvents_mousedown];
+ return sEventNames[eDOMEvents_mousedown];
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_MOUSE_RIGHT_BUTTON_UP:
- return mEventNames[eDOMEvents_mouseup];
+ return sEventNames[eDOMEvents_mouseup];
case NS_MOUSE_LEFT_CLICK:
case NS_MOUSE_MIDDLE_CLICK:
case NS_MOUSE_RIGHT_CLICK:
- return mEventNames[eDOMEvents_click];
+ return sEventNames[eDOMEvents_click];
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
- return mEventNames[eDOMEvents_dblclick];
+ return sEventNames[eDOMEvents_dblclick];
case NS_MOUSE_ENTER_SYNTH:
- return mEventNames[eDOMEvents_mouseover];
+ return sEventNames[eDOMEvents_mouseover];
case NS_MOUSE_EXIT_SYNTH:
- return mEventNames[eDOMEvents_mouseout];
+ return sEventNames[eDOMEvents_mouseout];
case NS_MOUSE_MOVE:
- return mEventNames[eDOMEvents_mousemove];
+ return sEventNames[eDOMEvents_mousemove];
case NS_KEY_UP:
- return mEventNames[eDOMEvents_keyup];
+ return sEventNames[eDOMEvents_keyup];
case NS_KEY_DOWN:
- return mEventNames[eDOMEvents_keydown];
+ return sEventNames[eDOMEvents_keydown];
case NS_KEY_PRESS:
- return mEventNames[eDOMEvents_keypress];
+ return sEventNames[eDOMEvents_keypress];
case NS_FOCUS_CONTENT:
- return mEventNames[eDOMEvents_focus];
+ return sEventNames[eDOMEvents_focus];
case NS_BLUR_CONTENT:
- return mEventNames[eDOMEvents_blur];
+ return sEventNames[eDOMEvents_blur];
case NS_XUL_CLOSE:
- return mEventNames[eDOMEvents_close];
+ return sEventNames[eDOMEvents_close];
case NS_PAGE_LOAD:
case NS_IMAGE_LOAD:
case NS_SCRIPT_LOAD:
- return mEventNames[eDOMEvents_load];
+ return sEventNames[eDOMEvents_load];
+ case NS_BEFORE_PAGE_UNLOAD:
+ return sEventNames[eDOMEvents_beforeunload];
case NS_PAGE_UNLOAD:
- return mEventNames[eDOMEvents_unload];
+ return sEventNames[eDOMEvents_unload];
case NS_IMAGE_ABORT:
- return mEventNames[eDOMEvents_abort];
+ return sEventNames[eDOMEvents_abort];
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
- return mEventNames[eDOMEvents_error];
+ return sEventNames[eDOMEvents_error];
case NS_FORM_SUBMIT:
- return mEventNames[eDOMEvents_submit];
+ return sEventNames[eDOMEvents_submit];
case NS_FORM_RESET:
- return mEventNames[eDOMEvents_reset];
+ return sEventNames[eDOMEvents_reset];
case NS_FORM_CHANGE:
- return mEventNames[eDOMEvents_change];
+ return sEventNames[eDOMEvents_change];
case NS_FORM_SELECTED:
- return mEventNames[eDOMEvents_select];
+ return sEventNames[eDOMEvents_select];
case NS_FORM_INPUT:
- return mEventNames[eDOMEvents_input];
+ return sEventNames[eDOMEvents_input];
case NS_PAINT:
- return mEventNames[eDOMEvents_paint];
+ return sEventNames[eDOMEvents_paint];
case NS_RESIZE_EVENT:
- return mEventNames[eDOMEvents_resize];
+ return sEventNames[eDOMEvents_resize];
case NS_SCROLL_EVENT:
- return mEventNames[eDOMEvents_scroll];
+ return sEventNames[eDOMEvents_scroll];
case NS_TEXT_TEXT:
- return mEventNames[eDOMEvents_text];
+ return sEventNames[eDOMEvents_text];
case NS_XUL_POPUP_SHOWING:
- return mEventNames[eDOMEvents_popupShowing];
+ return sEventNames[eDOMEvents_popupShowing];
case NS_XUL_POPUP_SHOWN:
- return mEventNames[eDOMEvents_popupShown];
+ return sEventNames[eDOMEvents_popupShown];
case NS_XUL_POPUP_HIDING:
- return mEventNames[eDOMEvents_popupHiding];
+ return sEventNames[eDOMEvents_popupHiding];
case NS_XUL_POPUP_HIDDEN:
- return mEventNames[eDOMEvents_popupHidden];
+ return sEventNames[eDOMEvents_popupHidden];
case NS_XUL_COMMAND:
- return mEventNames[eDOMEvents_command];
+ return sEventNames[eDOMEvents_command];
case NS_XUL_BROADCAST:
- return mEventNames[eDOMEvents_broadcast];
+ return sEventNames[eDOMEvents_broadcast];
case NS_XUL_COMMAND_UPDATE:
- return mEventNames[eDOMEvents_commandupdate];
+ return sEventNames[eDOMEvents_commandupdate];
case NS_DRAGDROP_ENTER:
- return mEventNames[eDOMEvents_dragenter];
+ return sEventNames[eDOMEvents_dragenter];
case NS_DRAGDROP_OVER_SYNTH:
- return mEventNames[eDOMEvents_dragover];
+ return sEventNames[eDOMEvents_dragover];
case NS_DRAGDROP_EXIT_SYNTH:
- return mEventNames[eDOMEvents_dragexit];
+ return sEventNames[eDOMEvents_dragexit];
case NS_DRAGDROP_DROP:
- return mEventNames[eDOMEvents_dragdrop];
+ return sEventNames[eDOMEvents_dragdrop];
case NS_DRAGDROP_GESTURE:
- return mEventNames[eDOMEvents_draggesture];
+ return sEventNames[eDOMEvents_draggesture];
case NS_SCROLLPORT_OVERFLOW:
- return mEventNames[eDOMEvents_overflow];
+ return sEventNames[eDOMEvents_overflow];
case NS_SCROLLPORT_UNDERFLOW:
- return mEventNames[eDOMEvents_underflow];
+ return sEventNames[eDOMEvents_underflow];
case NS_SCROLLPORT_OVERFLOWCHANGED:
- return mEventNames[eDOMEvents_overflowchanged];
+ return sEventNames[eDOMEvents_overflowchanged];
case NS_MUTATION_SUBTREEMODIFIED:
- return mEventNames[eDOMEvents_subtreemodified];
+ return sEventNames[eDOMEvents_subtreemodified];
case NS_MUTATION_NODEINSERTED:
- return mEventNames[eDOMEvents_nodeinserted];
+ return sEventNames[eDOMEvents_nodeinserted];
case NS_MUTATION_NODEREMOVED:
- return mEventNames[eDOMEvents_noderemoved];
+ return sEventNames[eDOMEvents_noderemoved];
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
- return mEventNames[eDOMEvents_noderemovedfromdocument];
+ return sEventNames[eDOMEvents_noderemovedfromdocument];
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
- return mEventNames[eDOMEvents_nodeinsertedintodocument];
+ return sEventNames[eDOMEvents_nodeinsertedintodocument];
case NS_MUTATION_ATTRMODIFIED:
- return mEventNames[eDOMEvents_attrmodified];
+ return sEventNames[eDOMEvents_attrmodified];
case NS_MUTATION_CHARACTERDATAMODIFIED:
- return mEventNames[eDOMEvents_characterdatamodified];
+ return sEventNames[eDOMEvents_characterdatamodified];
case NS_CONTEXTMENU:
case NS_CONTEXTMENU_KEY:
- return mEventNames[eDOMEvents_contextmenu];
+ return sEventNames[eDOMEvents_contextmenu];
default:
break;
}
View
1 content/events/src/nsDOMEvent.h
@@ -86,6 +86,7 @@ class nsDOMEvent : public nsIDOMKeyEvent,
eDOMEvents_focus,
eDOMEvents_blur,
eDOMEvents_load,
+ eDOMEvents_beforeunload,
eDOMEvents_unload,
eDOMEvents_abort,
eDOMEvents_error,
View
194 content/events/src/nsEventListenerManager.cpp
@@ -229,7 +229,8 @@ static const EventDispatchData sLoadEvents[] = {
{NS_SCRIPT_LOAD, HANDLER(&nsIDOMLoadListener::Load), NS_EVENT_BITS_LOAD_LOAD},
{NS_PAGE_UNLOAD, HANDLER(&nsIDOMLoadListener::Unload),NS_EVENT_BITS_LOAD_UNLOAD},
{NS_IMAGE_ERROR, HANDLER(&nsIDOMLoadListener::Error), NS_EVENT_BITS_LOAD_ERROR},
- {NS_SCRIPT_ERROR,HANDLER(&nsIDOMLoadListener::Error), NS_EVENT_BITS_LOAD_ERROR}
+ {NS_SCRIPT_ERROR,HANDLER(&nsIDOMLoadListener::Error), NS_EVENT_BITS_LOAD_ERROR},
+ {NS_BEFORE_PAGE_UNLOAD,HANDLER(&nsIDOMLoadListener::BeforeUnload), NS_EVENT_BITS_LOAD_BEFORE_UNLOAD}
};
static const EventDispatchData sPaintEvents[] = {
@@ -842,6 +843,10 @@ nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType,
*aArrayType = eEventArrayType_Load;
*aFlags = NS_EVENT_BITS_LOAD_LOAD;
}
+ else if (aType == nsLayoutAtoms::onbeforeunload) {
+ *aArrayType = eEventArrayType_Load;
+ *aFlags = NS_EVENT_BITS_LOAD_BEFORE_UNLOAD;
+ }
else if (aType == nsLayoutAtoms::onunload) {
*aArrayType = eEventArrayType_Load;
*aFlags = NS_EVENT_BITS_LOAD_UNLOAD;
@@ -1465,7 +1470,6 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
keys which cause window deletion, can destroy this object
before we're ready. */
nsCOMPtr<nsIEventListenerManager> kungFuDeathGrip(this);
- nsString empty;
nsVoidArray *listeners = nsnull;
if (aEvent->message == NS_CONTEXTMENU || aEvent->message == NS_CONTEXTMENU_KEY) {
@@ -1476,6 +1480,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
}
}
+
const EventTypeData* typeData = nsnull;
const EventDispatchData* dispData = nsnull;
@@ -1500,7 +1505,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
if (aEvent->eventStructType == NS_MUTATION_EVENT)
ret = NS_NewDOMMutationEvent(aDOMEvent, aPresContext, aEvent);
else
- ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent);
+ ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, EmptyString(), aEvent);
}
if (NS_SUCCEEDED(ret)) {
@@ -1590,225 +1595,119 @@ nsresult
nsEventListenerManager::FlipCaptureBit(PRInt32 aEventTypes,
PRBool aInitCapture)
{
- EventArrayType arrayType;
- nsListenerStruct *ls;
+ EventArrayType arrayType = eEventArrayType_None;
+ PRUint8 bits;
if (aEventTypes & nsIDOMNSEvent::MOUSEDOWN) {
arrayType = eEventArrayType_Mouse;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEDOWN;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEDOWN;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSE_MOUSEDOWN;
}
if (aEventTypes & nsIDOMNSEvent::MOUSEUP) {
arrayType = eEventArrayType_Mouse;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEUP;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEUP;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSE_MOUSEUP;
}
if (aEventTypes & nsIDOMNSEvent::MOUSEOVER) {
arrayType = eEventArrayType_Mouse;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEOVER;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEOVER;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSE_MOUSEOVER;
}
if (aEventTypes & nsIDOMNSEvent::MOUSEOUT) {
arrayType = eEventArrayType_Mouse;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEOUT;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEOUT;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSE_MOUSEOUT;
}
if (aEventTypes & nsIDOMNSEvent::MOUSEMOVE) {
arrayType = eEventArrayType_MouseMotion;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSEMOTION_MOUSEMOVE;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSEMOTION_MOUSEMOVE;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSEMOTION_MOUSEMOVE;
}
if (aEventTypes & nsIDOMNSEvent::CLICK) {
arrayType = eEventArrayType_Mouse;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_CLICK;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_CLICK;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSE_CLICK;
}
if (aEventTypes & nsIDOMNSEvent::DBLCLICK) {
arrayType = eEventArrayType_Mouse;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_DBLCLICK;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_DBLCLICK;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSE_DBLCLICK;
}
if (aEventTypes & nsIDOMNSEvent::KEYDOWN) {
arrayType = eEventArrayType_Key;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_KEY_KEYDOWN;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_KEY_KEYDOWN;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_KEY_KEYDOWN;
}
if (aEventTypes & nsIDOMNSEvent::KEYUP) {
arrayType = eEventArrayType_Key;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_KEY_KEYUP;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_KEY_KEYUP;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_KEY_KEYUP;
}
if (aEventTypes & nsIDOMNSEvent::KEYPRESS) {
arrayType = eEventArrayType_Key;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_KEY_KEYPRESS;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_KEY_KEYPRESS;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_KEY_KEYPRESS;
}
if (aEventTypes & nsIDOMNSEvent::DRAGDROP) {
arrayType = eEventArrayType_Drag;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_DRAG_ENTER;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_DRAG_ENTER;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_DRAG_ENTER;
}
/*if (aEventTypes & nsIDOMNSEvent::MOUSEDRAG) {
arrayType = kIDOMMouseListenerarrayType;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_MOUSE_MOUSEDOWN;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_MOUSE_MOUSEDOWN;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_MOUSE_MOUSEDOWN;
}*/
if (aEventTypes & nsIDOMNSEvent::FOCUS) {
arrayType = eEventArrayType_Focus;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FOCUS_FOCUS;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FOCUS_FOCUS;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_FOCUS_FOCUS;
}
if (aEventTypes & nsIDOMNSEvent::BLUR) {
arrayType = eEventArrayType_Focus;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FOCUS_BLUR;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FOCUS_BLUR;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_FOCUS_BLUR;
}
if (aEventTypes & nsIDOMNSEvent::SELECT) {
arrayType = eEventArrayType_Form;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_SELECT;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_SELECT;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_FORM_SELECT;
}
if (aEventTypes & nsIDOMNSEvent::CHANGE) {
arrayType = eEventArrayType_Form;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_CHANGE;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_CHANGE;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_FORM_CHANGE;
}
if (aEventTypes & nsIDOMNSEvent::RESET) {
arrayType = eEventArrayType_Form;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_RESET;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_RESET;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_FORM_RESET;
}
if (aEventTypes & nsIDOMNSEvent::SUBMIT) {
arrayType = eEventArrayType_Form;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_FORM_SUBMIT;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_FORM_SUBMIT;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_FORM_SUBMIT;
}
if (aEventTypes & nsIDOMNSEvent::LOAD) {
arrayType = eEventArrayType_Load;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_LOAD;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_LOAD;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_LOAD_LOAD;
}
if (aEventTypes & nsIDOMNSEvent::UNLOAD) {
arrayType = eEventArrayType_Load;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_UNLOAD;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_UNLOAD;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_LOAD_UNLOAD;
}
if (aEventTypes & nsIDOMNSEvent::ABORT) {
arrayType = eEventArrayType_Load;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_ABORT;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_ABORT;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_LOAD_ABORT;
}
if (aEventTypes & nsIDOMNSEvent::ERROR) {
arrayType = eEventArrayType_Load;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_LOAD_ERROR;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_LOAD_ERROR;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_LOAD_ERROR;
}
if (aEventTypes & nsIDOMNSEvent::RESIZE) {
arrayType = eEventArrayType_Paint;
- ls = FindJSEventListener(arrayType);
- if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_PAINT_RESIZE;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_PAINT_RESIZE;
- ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
- }
+ bits = NS_EVENT_BITS_PAINT_RESIZE;
}
if (aEventTypes & nsIDOMNSEvent::SCROLL) {
arrayType = eEventArrayType_Scroll;
- ls = FindJSEventListener(arrayType);
+ bits = NS_EVENT_BITS_PAINT_RESIZE;
+ }
+
+ if (arrayType != eEventArrayType_None) {
+ nsListenerStruct *ls = FindJSEventListener(arrayType);
+
if (ls) {
- if (aInitCapture) ls->mSubTypeCapture |= NS_EVENT_BITS_PAINT_RESIZE;
- else ls->mSubTypeCapture &= ~NS_EVENT_BITS_PAINT_RESIZE;
+ if (aInitCapture)
+ ls->mSubTypeCapture |= bits;
+ else
+ ls->mSubTypeCapture &= ~bits;
+
ls->mFlags |= NS_EVENT_FLAG_CAPTURE;
}
}
+
return NS_OK;
}
@@ -2002,7 +1901,6 @@ nsEventListenerManager::FixContextMenuEvent(nsIPresContext* aPresContext,
nsCOMPtr<nsIDOMElement> currentFocus;
nsCOMPtr<nsIDocument> doc;
nsIPresShell* shell = aPresContext->PresShell();
- nsString empty;
if (aEvent->message == NS_CONTEXTMENU_KEY) {
shell->GetDocument(getter_AddRefs(doc));
@@ -2027,7 +1925,7 @@ nsEventListenerManager::FixContextMenuEvent(nsIPresContext* aPresContext,
// the client X/Y will be 0,0. We can make use of that if the widget is null.
if (aEvent->message == NS_CONTEXTMENU_KEY)
NS_IF_RELEASE(((nsGUIEvent*)aEvent)->widget); // nulls out widget
- ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, empty, aEvent);
+ ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, EmptyString(), aEvent);
}
if (NS_SUCCEEDED(ret)) {
View
11 content/events/src/nsEventListenerManager.h
@@ -292,11 +292,12 @@ class nsEventListenerManager : public nsIEventListenerManager,
#define NS_EVENT_BITS_FORM_INPUT 0x10
//nsIDOMLoadListener
-#define NS_EVENT_BITS_LOAD_NONE 0x00
-#define NS_EVENT_BITS_LOAD_LOAD 0x01
-#define NS_EVENT_BITS_LOAD_UNLOAD 0x02
-#define NS_EVENT_BITS_LOAD_ABORT 0x04
-#define NS_EVENT_BITS_LOAD_ERROR 0x08
+#define NS_EVENT_BITS_LOAD_NONE 0x00
+#define NS_EVENT_BITS_LOAD_LOAD 0x01
+#define NS_EVENT_BITS_LOAD_UNLOAD 0x02
+#define NS_EVENT_BITS_LOAD_ABORT 0x04
+#define NS_EVENT_BITS_LOAD_ERROR 0x08
+#define NS_EVENT_BITS_LOAD_BEFORE_UNLOAD 0x10
//nsIDOMXULListener
#define NS_EVENT_BITS_XUL_NONE 0x00
View
1 content/html/content/src/nsGenericHTMLElement.cpp
@@ -1809,6 +1809,7 @@ PRBool nsGenericHTMLElement::IsEventName(nsIAtom* aName)
aName == nsLayoutAtoms::onmousemove ||
aName == nsLayoutAtoms::onload ||
aName == nsLayoutAtoms::onunload ||
+ aName == nsLayoutAtoms::onbeforeunload ||
aName == nsLayoutAtoms::onabort ||
aName == nsLayoutAtoms::onerror ||
aName == nsLayoutAtoms::onfocus ||
View
6 content/html/content/src/nsHTMLScriptElement.cpp
@@ -301,9 +301,9 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject,
}
// Invoke the event handler script...
- PRBool dummy;
- return scriptContext->CallEventHandler(scriptObject, funcObject, aArgCount,
- aArgs, &dummy);
+ jsval dummy;
+ return scriptContext->CallEventHandler(scriptObject, (JSObject *)funcObject,
+ aArgCount, (jsval *)aArgs, &dummy);
}
View
23 content/html/document/src/nsHTMLDocument.cpp
@@ -2020,15 +2020,28 @@ nsHTMLDocument::OpenCommon(nsIURI* aSourceURI)
}
nsCOMPtr<nsIDocShell> docshell = do_QueryReferent(mDocumentContainer);
+ nsresult rv = NS_OK;
// Stop current loads targeted at the window this document is in.
if (mScriptGlobalObject && docshell) {
+ nsCOMPtr<nsIContentViewer> cv;
+ docshell->GetContentViewer(getter_AddRefs(cv));
+
+ if (cv) {
+ PRBool okToUnload;
+ rv = cv->PermitUnload(&okToUnload);
+
+ if (NS_SUCCEEDED(rv) && !okToUnload) {
+ // We don't want to unload, so stop here, but don't throw an
+ // exception.
+ return NS_OK;
+ }
+ }
+
nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(docshell));
webnav->Stop(nsIWebNavigation::STOP_NETWORK);
}
- nsresult rv = NS_OK;
-
// The open occurred after the document finished loading.
// So we reset the document and create a new one.
nsCOMPtr<nsIChannel> channel;
@@ -2242,7 +2255,11 @@ nsHTMLDocument::WriteCommon(const nsAString& aText,
if (!mParser) {
rv = Open();
- if (NS_FAILED(rv)) {
+
+ // If Open() fails, or if it didn't create a parser (as it won't
+ // if the user chose to not discard the current document through
+ // onbeforeunload), don't write anything.
+ if (NS_FAILED(rv) || !mParser) {
return rv;
}
} else if (IsXHTML()) {
View
1 content/shared/public/nsLayoutAtomList.h
@@ -147,6 +147,7 @@ LAYOUT_ATOM(viewProperty, "ViewProperty")
// Alphabetical list of event handler names
LAYOUT_ATOM(onabort, "onabort")
+LAYOUT_ATOM(onbeforeunload, "onbeforeunload")
LAYOUT_ATOM(onblur, "onblur")
LAYOUT_ATOM(onbroadcast, "onbroadcast")
LAYOUT_ATOM(onchange, "onchange")
View
1 content/xbl/src/nsXBLService.cpp
@@ -232,6 +232,7 @@ class nsXBLStreamListener : public nsIStreamListener, public nsIDOMLoadListener
NS_DECL_NSIREQUESTOBSERVER
NS_IMETHOD Load(nsIDOMEvent* aEvent);
+ NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD Unload(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD Abort(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD Error(nsIDOMEvent* aEvent) { return NS_OK; };
View
60 docshell/base/nsDocShell.cpp
@@ -228,6 +228,7 @@ nsDocShell::nsDocShell():
mAllowMetaRedirects(PR_TRUE),
mAllowImages(PR_TRUE),
mFocusDocFirst(PR_FALSE),
+ mHasFocus(PR_FALSE),
mCreatingDocument(PR_FALSE),
mUseErrorPages(PR_FALSE),
mAllowAuth(PR_TRUE),
@@ -236,15 +237,15 @@ nsDocShell::nsDocShell():
mFiredUnloadEvent(PR_FALSE),
mEODForCurrentDocument(PR_FALSE),
mURIResultedInDocument(PR_FALSE),
- mUseExternalProtocolHandler(PR_FALSE),
mDisallowPopupWindows(PR_FALSE),
+ mUseExternalProtocolHandler(PR_FALSE),
mIsBeingDestroyed(PR_FALSE),
mIsExecutingOnLoadHandler(PR_FALSE),
+ mIsPrintingOrPP(PR_FALSE),
mEditorData(nsnull),
mParent(nsnull),
mTreeOwner(nsnull),
- mChromeEventHandler(nsnull),
- mIsPrintingOrPP(PR_FALSE)
+ mChromeEventHandler(nsnull)
{
#ifdef PR_LOGGING
if (! gDocShellLog)
@@ -816,21 +817,18 @@ nsDocShell::PrepareForNewContentModel()
NS_IMETHODIMP
nsDocShell::FireUnloadNotification()
{
- nsresult rv;
-
if (mContentViewer && !mFiredUnloadEvent) {
mFiredUnloadEvent = PR_TRUE;
- rv = mContentViewer->Unload();
+ mContentViewer->Unload();
PRInt32 i, n = mChildren.Count();
for (i = 0; i < n; i++) {
nsIDocShellTreeItem* item = (nsIDocShellTreeItem*) mChildren.ElementAt(i);
- if(item) {
- nsCOMPtr<nsIDocShell> shell(do_QueryInterface(item));
- if (shell) {
- rv = shell->FireUnloadNotification();
- }
+
+ nsCOMPtr<nsIDocShell> shell(do_QueryInterface(item));
+ if (shell) {
+ shell->FireUnloadNotification();
}
}
}
@@ -2996,20 +2994,27 @@ nsDocShell::Create()
mPrefs = do_GetService(NS_PREF_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
+ PRBool tmpbool;
+
// i don't want to read this pref in every time we load a url
// so read it in once here and be done with it...
mPrefs->GetBoolPref("network.protocols.useSystemDefaults",
- &mUseExternalProtocolHandler);
- mPrefs->GetBoolPref("browser.block.target_new_window", &mDisallowPopupWindows);
- mPrefs->GetBoolPref("browser.frames.enabled", &mAllowSubframes);
+ &tmpbool);
+ mUseExternalProtocolHandler = tmpbool;
+
+ mPrefs->GetBoolPref("browser.block.target_new_window", &tmpbool);
+ mDisallowPopupWindows = tmpbool;
+
+ mPrefs->GetBoolPref("browser.frames.enabled", &tmpbool);
+ mAllowSubframes = tmpbool;
// Check pref to see if we should prevent frameset spoofing
- mPrefs->GetBoolPref("browser.frame.validate_origin", &mValidateOrigin);
+ mPrefs->GetBoolPref("browser.frame.validate_origin", &tmpbool);
+ mValidateOrigin = tmpbool;
// Should we use XUL error pages instead of alerts if possible?
- PRBool useErrorPages = PR_FALSE;
- mPrefs->GetBoolPref("browser.xul.error_pages.enabled", &useErrorPages);
- mUseErrorPages = useErrorPages;
+ mPrefs->GetBoolPref("browser.xul.error_pages.enabled", &tmpbool);
+ mUseErrorPages = tmpbool;
return NS_OK;
}
@@ -4464,6 +4469,8 @@ nsDocShell::CreateContentViewer(const char *aContentType,
nsIRequest * request,
nsIStreamListener ** aContentHandler)
{
+ *aContentHandler = nsnull;
+
// Can we check the content type of the current content viewer
// and reuse it without destroying it and re-creating it?
@@ -5095,6 +5102,19 @@ nsDocShell::InternalLoad(nsIURI * aURI,
return rv;
}
+ // Check if the page doesn't want to be unloaded. The javascript:
+ // protocol handler deals with this for javascript: URLs.
+ if (!bIsJavascript && mContentViewer) {
+ PRBool okToUnload;
+ rv = mContentViewer->PermitUnload(&okToUnload);
+
+ if (NS_SUCCEEDED(rv) && !okToUnload) {
+ // The user chose not to unload the page, interrupt the
+ // load.
+ return NS_OK;
+ }
+ }
+
//
// Load is being targetted at this docshell so return an error if the
// docshell is in the process of being destroyed.
@@ -6867,8 +6887,8 @@ nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState *aLayoutHistoryState)
//*** nsRefreshTimer: Object Management
//*****************************************************************************
-nsRefreshTimer::nsRefreshTimer():mRepeat(PR_FALSE), mDelay(0),
-mMetaRefresh(PR_FALSE)
+nsRefreshTimer::nsRefreshTimer()
+ : mDelay(0), mRepeat(PR_FALSE), mMetaRefresh(PR_FALSE)
{
}
View
26 docshell/base/nsDocShell.h
@@ -149,10 +149,9 @@ class nsRefreshTimer : public nsITimerCallback
nsCOMPtr<nsIDocShell> mDocShell;
nsCOMPtr<nsIURI> mURI;
- PRBool mRepeat;
PRInt32 mDelay;
- PRBool mMetaRefresh;
-
+ PRPackedBool mRepeat;
+ PRPackedBool mMetaRefresh;
protected:
virtual ~nsRefreshTimer();
@@ -359,31 +358,34 @@ friend class nsDSURIContentListener;
// Somebody give me better name
nsCOMPtr<nsISHEntry> mLSHE;
- PRBool mFiredUnloadEvent;
+ PRPackedBool mFiredUnloadEvent;
// this flag is for bug #21358. a docshell may load many urls
// which don't result in new documents being created (i.e. a new content viewer)
// we want to make sure we don't call a on load event more than once for a given
// content viewer.
- PRBool mEODForCurrentDocument;
- PRBool mURIResultedInDocument;
+ PRPackedBool mEODForCurrentDocument;
+ PRPackedBool mURIResultedInDocument;
+
+ PRPackedBool mIsBeingDestroyed;
// used to keep track of whether user click links should be handle by us
// or immediately kicked out to an external application. mscott: eventually
// i'm going to try to fold this up into the uriloader where it belongs but i haven't
// figured out how to do that yet.
- PRBool mUseExternalProtocolHandler;
+ PRPackedBool mUseExternalProtocolHandler;
// Disallow popping up new windows with target=
- PRBool mDisallowPopupWindows;
+ PRPackedBool mDisallowPopupWindows;
// Validate window targets to prevent frameset spoofing
- PRBool mValidateOrigin;
-
- PRBool mIsBeingDestroyed;
+ PRPackedBool mValidateOrigin;
PRPackedBool mIsExecutingOnLoadHandler;
+ // Indicates that a DocShell in this "docshell tree" is printing
+ PRPackedBool mIsPrintingOrPP;
+
// Editor stuff
nsDocShellEditorData* mEditorData; // editor data, if any
@@ -398,8 +400,6 @@ friend class nsDSURIContentListener;
nsIDocShellTreeOwner * mTreeOwner; // Weak Reference
nsIChromeEventHandler * mChromeEventHandler; //Weak Reference
- // Indicates that a DocShell in this "docshell tree" is printing
- PRBool mIsPrintingOrPP;
public:
class InterfaceRequestorProxy : public nsIInterfaceRequestor {
View
1 docshell/base/nsIContentViewer.idl
@@ -25,6 +25,7 @@ interface nsIContentViewer : nsISupports
void loadStart(in nsISupports aDoc);
void loadComplete(in unsigned long aStatus);
+ boolean permitUnload();
void unload();
/**
View
7 dom/public/coreEvents/nsIDOMLoadListener.h
@@ -64,6 +64,13 @@ class nsIDOMLoadListener : public nsIDOMEventListener {
NS_IMETHOD Load(nsIDOMEvent* aEvent) = 0;
/**
+ * Processes a page beforeUnload event
+ * @param aMouseEvent @see nsIDOMEvent.h
+ * @returns whether the event was consumed or ignored. @see nsresult
+ */
+ NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent) = 0;
+
+ /**
* Processes a page unload event
* @param aMouseEvent @see nsIDOMEvent.h
* @returns whether the event was consumed or ignored. @see nsresult
View
6 dom/public/nsIScriptContext.h
@@ -195,9 +195,9 @@ class nsIScriptContext : public nsISupports
* @param aBoolResult out parameter returning boolean function result, or
* true if the result was not boolean.
**/
- virtual nsresult CallEventHandler(void* aTarget, void* aHandler,
- PRUint32 argc, void* argv,
- PRBool* aBoolResult) = 0;
+ virtual nsresult CallEventHandler(JSObject* aTarget, JSObject* aHandler,
+ uintN argc, jsval* argv,
+ jsval* rval) = 0;
/**
* Bind an already-compiled event handler function to a name in the given
View
4 dom/resources/locale/dom.properties
@@ -1,2 +1,4 @@
JSURLLoadBlockedWarning=Attempt to load a javascript: URL from one host\nin a window displaying content from another host\nwas blocked by the security manager.
-WindowCloseBlockedWarning=Scripts may not close windows that were not opened by script.
+WindowCloseBlockedWarning=Scripts may not close windows that were not opened by script.
+OnBeforeUnloadPreMessage=Are you sure you want to navigate away from this page?
+OnBeforeUnloadPostMessage=Press OK to continue, or Cancel to stay on the current page.
View
1 dom/src/base/nsDOMClassInfo.h
@@ -240,6 +240,7 @@ class nsDOMClassInfo : public nsIXPCScriptable,
static jsval sOnchange_id;
static jsval sOnselect_id;
static jsval sOnload_id;
+ static jsval sOnbeforeunload_id;
static jsval sOnunload_id;
static jsval sOnabort_id;
static jsval sOnerror_id;
View
12 dom/src/base/nsGlobalWindow.cpp
@@ -3563,6 +3563,7 @@ GlobalWindowImpl::Close()
}
}
}
+
return NS_OK;
}
}
@@ -3578,8 +3579,13 @@ GlobalWindowImpl::Close()
mDocShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
PRBool canClose;
- cv->RequestWindowClose(&canClose);
- if (!canClose)
+
+ rv = cv->PermitUnload(&canClose);
+ if (NS_SUCCEEDED(rv) && !canClose)
+ return NS_OK;
+
+ rv = cv->RequestWindowClose(&canClose);
+ if (NS_SUCCEEDED(rv) && !canClose)
return NS_OK;
}
@@ -5133,7 +5139,7 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout)
lateness = PR_IntervalToMilliseconds(lateness);
timeout->mArgv[timeout->mArgc] = INT_TO_JSVAL((jsint) lateness);
- PRBool dummy;
+ jsval dummy;
rv = mContext->CallEventHandler(mJSObject, timeout->mFunObj,
timeout->mArgc + 1, timeout->mArgv,
&dummy);
View
18 dom/src/base/nsJSEnvironment.cpp
@@ -1195,10 +1195,10 @@ nsJSContext::CompileFunction(void* aTarget,
}
nsresult
-nsJSContext::CallEventHandler(void *aTarget, void *aHandler, PRUint32 argc,
- void *argv, PRBool *aBoolResult)
+nsJSContext::CallEventHandler(JSObject *aTarget, JSObject *aHandler,
+ uintN argc, jsval *argv, jsval *rval)
{
- *aBoolResult = PR_TRUE;
+ *rval = JSVAL_VOID;
if (!mScriptsEnabled) {
return NS_OK;
@@ -1226,21 +1226,21 @@ nsJSContext::CallEventHandler(void *aTarget, void *aHandler, PRUint32 argc,
rv = sSecurityManager->CheckFunctionAccess(mContext, aHandler, aTarget);
if (NS_SUCCEEDED(rv)) {
- jsval val;
jsval funval = OBJECT_TO_JSVAL(aHandler);
- PRBool ok = ::JS_CallFunctionValue(mContext, (JSObject *)aTarget, funval,
- argc, (jsval *)argv, &val);
+ PRBool ok = ::JS_CallFunctionValue(mContext, aTarget, funval, argc, argv,
+ rval);
ScriptEvaluated(PR_TRUE);
- if (ok) {
- *aBoolResult = !JSVAL_IS_BOOLEAN(val) || JSVAL_TO_BOOLEAN(val);
- } else {
+ if (!ok) {
// Tell XPConnect about any pending exceptions. This is needed
// to avoid dropping JS exceptions in case we got here through
// nested calls through XPConnect.
NotifyXPCIfExceptionPending(mContext);
+
+ // Don't pass back results from failed calls.
+ *rval = JSVAL_VOID;
}
}
View
5 dom/src/base/nsJSEnvironment.h
@@ -94,9 +94,8 @@ class nsJSContext : public nsIScriptContext,
PRUint32 aLineNo,
PRBool aShared,
void** aHandler);
- virtual nsresult CallEventHandler(void *aTarget, void *aHandler,
- PRUint32 argc, void *argv,
- PRBool *aBoolResult);
+ virtual nsresult CallEventHandler(JSObject *aTarget, JSObject *aHandler,
+ uintN argc, jsval *argv, jsval* rval);
virtual nsresult BindCompiledEventHandler(void *aTarget,
nsIAtom *aName,
void *aHandler);
View
44 dom/src/events/nsJSEventListener.cpp
@@ -36,6 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsJSEventListener.h"
+#include "nsJSUtils.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsIServiceManager.h"
@@ -52,9 +53,9 @@
*/
nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
nsISupports *aObject)
- : nsIJSEventListener(aContext, aObject)
+ : nsIJSEventListener(aContext, aObject),
+ mReturnResult(nsReturnResult_eNotSet)
{
- mReturnResult = nsReturnResult_eNotSet;
}
nsJSEventListener::~nsJSEventListener()
@@ -168,21 +169,46 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
argc = 1;
}
- PRBool jsBoolResult;
+ jsval rval;
rv = mContext->CallEventHandler(obj, JSVAL_TO_OBJECT(funval), argc, argv,
- &jsBoolResult);
+ &rval);
if (argv != &arg) {
::JS_PopArguments(cx, stackPtr);
}
if (NS_SUCCEEDED(rv)) {
- // if the handler returned false and its sense is not reversed, or
- // the handler returned true and its sense is reversed from the
- // usual (false means cancel), then prevent default.
+ if (eventString.Equals(NS_LITERAL_STRING("onbeforeunload"))) {
+ nsCOMPtr<nsIPrivateDOMEvent> priv(do_QueryInterface(aEvent));
+ NS_ENSURE_TRUE(priv, NS_ERROR_UNEXPECTED);
- if (!(jsBoolResult ^ (mReturnResult == nsReturnResult_eReverseReturnResult)))
- aEvent->PreventDefault();
+ nsEvent* event;
+ priv->GetInternalNSEvent(&event);
+ NS_ENSURE_TRUE(event && event->message == NS_BEFORE_PAGE_UNLOAD,
+ NS_ERROR_UNEXPECTED);
+
+ nsBeforePageUnloadEvent *beforeUnload =
+ NS_STATIC_CAST(nsBeforePageUnloadEvent *, event);
+
+ if (!JSVAL_IS_VOID(rval)) {
+ aEvent->PreventDefault();
+
+ if (JSVAL_IS_STRING(rval)) {
+ beforeUnload->text = nsDependentJSString(JSVAL_TO_STRING(rval));
+ }
+ }
+ } else {
+ // if the handler returned false and its sense is not reversed,
+ // or the handler returned true and its sense is reversed from
+ // the usual (false means cancel), then prevent default.
+
+ PRBool jsBoolResult = !JSVAL_IS_BOOLEAN(rval) || JSVAL_TO_BOOLEAN(rval);
+
+ if (jsBoolResult ==
+ (mReturnResult == nsReturnResult_eReverseReturnResult)) {
+ aEvent->PreventDefault();
+ }
+ }
}
return rv;
View
36 dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -68,6 +68,8 @@
#include "nsEscape.h"
#include "nsIJSContextStack.h"
#include "nsIWebNavigation.h"
+#include "nsIDocShell.h"
+#include "nsIContentViewer.h"
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
@@ -534,10 +536,34 @@ nsJSChannel::InternalOpen(PRBool aIsAsync, nsIStreamListener *aListener,
mStreamChannel->GetLoadFlags(&loadFlags);
if (loadFlags & LOAD_DOCUMENT_URI) {
- // We're loaded as the document channel. Stop all pending
- // network loads.
+ // We're loaded as the document channel. If we go on,
+ // we'll blow away the current document. Make sure that's
+ // ok. If so, stop all pending network loads.
+
+ nsCOMPtr<nsIInterfaceRequestor> cb;
+ mStreamChannel->GetNotificationCallbacks(getter_AddRefs(cb));
+
+ nsCOMPtr<nsIDocShell> docShell(do_GetInterface(cb));
+ if (docShell) {
+ nsCOMPtr<nsIContentViewer> cv;
+ docShell->GetContentViewer(getter_AddRefs(cv));
+
+ if (cv) {
+ PRBool okToUnload;
+
+ if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) &&
+ !okToUnload) {
+ // The user didn't want to unload the current
+ // page, translate this into an undefined
+ // return from the javascript: URL...
+ rv = NS_ERROR_DOM_RETVAL_UNDEFINED;
+ }
+ }
+ }
- rv = StopAll();
+ if (NS_SUCCEEDED(rv)) {
+ rv = StopAll();
+ }
}
if (NS_SUCCEEDED(rv)) {
@@ -549,7 +575,9 @@ nsJSChannel::InternalOpen(PRBool aIsAsync, nsIStreamListener *aListener,
rv = mStreamChannel->Open(aResult);
}
}
- } else {
+ }
+
+ if (NS_FAILED(rv)) {
// Propagate the failure down to the underlying channel...
mStreamChannel->Cancel(rv);
}
View
6 extensions/xmlextras/base/src/nsDOMParser.cpp
@@ -302,6 +302,12 @@ nsDOMParser::Load(nsIDOMEvent* aEvent)
}
nsresult
+nsDOMParser::BeforeUnload(nsIDOMEvent* aEvent)
+{
+ return NS_OK;
+}
+
+nsresult
nsDOMParser::Unload(nsIDOMEvent* aEvent)
{
return NS_OK;
View
1 extensions/xmlextras/base/src/nsDOMParser.h
@@ -64,6 +64,7 @@ class nsDOMParser : public nsIDOMParser,
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent* aEvent);
+ NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
NS_IMETHOD Error(nsIDOMEvent* aEvent);
View
12 extensions/xmlextras/base/src/nsLoadListenerProxy.cpp
@@ -75,6 +75,18 @@ nsLoadListenerProxy::Load(nsIDOMEvent* aEvent)
}
NS_IMETHODIMP
+nsLoadListenerProxy::BeforeUnload(nsIDOMEvent* aEvent)
+{
+ nsCOMPtr<nsIDOMLoadListener> listener(do_QueryReferent(mParent));
+
+ if (listener) {
+ return listener->BeforeUnload(aEvent);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsLoadListenerProxy::Unload(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIDOMLoadListener> listener(do_QueryReferent(mParent));
View
1 extensions/xmlextras/base/src/nsLoadListenerProxy.h
@@ -66,6 +66,7 @@ class nsLoadListenerProxy : public nsIDOMLoadListener {
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent* aEvent);
+ NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
NS_IMETHOD Error(nsIDOMEvent* aEvent);
View
6 extensions/xmlextras/base/src/nsXMLHttpRequest.cpp
@@ -1436,6 +1436,12 @@ nsXMLHttpRequest::Unload(nsIDOMEvent* aEvent)
}
nsresult
+nsXMLHttpRequest::BeforeUnload(nsIDOMEvent* aEvent)
+{
+ return NS_OK;
+}
+
+nsresult
nsXMLHttpRequest::Abort(nsIDOMEvent* aEvent)
{
Abort();
View
1 extensions/xmlextras/base/src/nsXMLHttpRequest.h
@@ -89,6 +89,7 @@ class nsXMLHttpRequest : public nsIXMLHttpRequest,
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent* aEvent);
+ NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
NS_IMETHOD Error(nsIDOMEvent* aEvent);
View
112 layout/base/nsDocumentViewer.cpp
@@ -199,6 +199,10 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
static NS_DEFINE_CID(kGalleyContextCID, NS_GALLEYCONTEXT_CID);
+static const char kDOMStringBundleURL[] =
+ "chrome://communicator/locale/dom/dom.properties";
+
+
#ifdef NS_DEBUG
#undef NOISY_VIEWER
@@ -414,9 +418,11 @@ class DocumentViewerImpl : public nsIDocumentViewer,
nsIWidget* mParentWidget; // purposely won't be ref counted
+ PRPackedBool mInPermitUnload;
+
#ifdef NS_PRINTING
+ PRPackedBool mClosingWhilePrinting;
nsPrintEngine* mPrintEngine;
- PRBool mClosingWhilePrinting;
nsCOMPtr<nsIDOMWindowInternal> mDialogParentWin;
#if NS_PRINT_PREVIEW
// These data member support delayed printing when the document is loading
@@ -962,6 +968,104 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
}
NS_IMETHODIMP
+DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
+{
+ *aPermitUnload = PR_TRUE;
+
+ if (!mDocument || mInPermitUnload) {
+ return NS_OK;
+ }
+
+ // First, get the script global object from the document...
+ nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
+
+ if (!global) {
+ // This is odd, but not fatal
+ NS_WARNING("nsIScriptGlobalObject not set for document!");
+ return NS_OK;
+ }
+
+ // Now, fire an BeforeUnload event to the document and see if it's ok
+ // to unload...
+ nsEventStatus status = nsEventStatus_eIgnore;
+ nsBeforePageUnloadEvent event(NS_BEFORE_PAGE_UNLOAD);
+
+ // In evil cases we might be destroyed while handling the
+ // onbeforeunload event, don't let that happen.
+ nsRefPtr<DocumentViewerImpl> kungFuDeathGrip(this);
+
+ mInPermitUnload = PR_TRUE;
+ nsresult rv = global->HandleDOMEvent(mPresContext, &event, nsnull,
+ NS_EVENT_FLAG_INIT, &status);
+ mInPermitUnload = PR_FALSE;
+
+ if (NS_SUCCEEDED(rv) && event.flags & NS_EVENT_FLAG_NO_DEFAULT) {
+ // Ask the user if it's ok to unload the current page
+
+ nsCOMPtr<nsIPrompt> prompt(do_GetInterface(mContainer));
+
+ if (prompt) {
+ nsCOMPtr<nsIStringBundleService>
+ stringService(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
+ NS_ENSURE_TRUE(stringService, NS_OK);
+
+ nsCOMPtr<nsIStringBundle> bundle;
+ stringService->CreateBundle(kDOMStringBundleURL, getter_AddRefs(bundle));
+ NS_ENSURE_TRUE(bundle, NS_OK);
+
+ nsXPIDLString preMsg, postMsg;
+ nsresult rv;
+ rv = bundle->GetStringFromName(NS_LITERAL_STRING("OnBeforeUnloadPreMessage").get(), getter_Copies(preMsg));
+ rv |= bundle->GetStringFromName(NS_LITERAL_STRING("OnBeforeUnloadPostMessage").get(), getter_Copies(postMsg));
+
+ // GetStringFromName can succeed, yet give NULL strings back.
+ if (NS_FAILED(rv) || !preMsg || !postMsg) {
+ NS_ERROR("Failed to get strings from dom.properties!");
+ return NS_OK;
+ }
+
+ // Limit the length of the text the page can inject into this
+ // dialogue to 1024 characters.
+ PRInt32 len = PR_MIN(event.text.Length(), 1024);
+
+ nsAutoString msg(preMsg + NS_LITERAL_STRING("\n\n") +
+ StringHead(event.text, len) +
+ NS_LITERAL_STRING("\n\n") + postMsg);
+
+ // This doesn't pass a title, which makes the title be
+ // "Confirm", is that ok, or do we want a localizable title for
+ // this dialogue?
+ if (NS_FAILED(prompt->Confirm(nsnull, msg.get(), aPermitUnload))) {
+ *aPermitUnload = PR_TRUE;
+ }
+ }
+ }
+
+ nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryInterface(mContainer));
+
+ if (docShellNode) {
+ PRInt32 childCount;
+ docShellNode->GetChildCount(&childCount);
+
+ for (PRInt32 i = 0; i < childCount && *aPermitUnload; ++i) {
+ nsCOMPtr<nsIDocShellTreeItem> item;
+ docShellNode->GetChildAt(i, getter_AddRefs(item));
+
+ nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(item));
+ nsCOMPtr<nsIContentViewer> cv;
+
+ docShell->GetContentViewer(getter_AddRefs(cv));
+
+ if (cv) {
+ cv->PermitUnload(aPermitUnload);
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
DocumentViewerImpl::Unload()
{
mEnableRendering = PR_FALSE;
@@ -971,11 +1075,11 @@ DocumentViewerImpl::Unload()
}
// First, get the script global object from the document...
- nsCOMPtr<nsIScriptGlobalObject> global = mDocument->GetScriptGlobalObject();
+ nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
if (!global) {
// Fail if no ScriptGlobalObject is available...
- NS_ASSERTION(0, "nsIScriptGlobalObject not set for document!");
+ NS_ERROR("nsIScriptGlobalObject not set for document!");
return NS_ERROR_NULL_POINTER;
}
@@ -1121,6 +1225,8 @@ DocumentViewerImpl::Destroy()
mPresShell = nsnull;
}
+ mContainer = nsnull;
+
return NS_OK;
}
View
1 layout/base/nsLayoutAtomList.h
@@ -147,6 +147,7 @@ LAYOUT_ATOM(viewProperty, "ViewProperty")
// Alphabetical list of event handler names
LAYOUT_ATOM(onabort, "onabort")
+LAYOUT_ATOM(onbeforeunload, "onbeforeunload")
LAYOUT_ATOM(onblur, "onblur")
LAYOUT_ATOM(onbroadcast, "onbroadcast")
LAYOUT_ATOM(onchange, "onchange")
View
61 widget/public/nsGUIEvent.h
@@ -44,6 +44,7 @@
#include "nsRect.h"
#include "nsEvent.h"
#include "nsHashtable.h"
+#include "nsString.h"
// nsIDOMEvent contains a long enum which includes a member called ERROR,
// which conflicts with something that Windows defines somewhere.
@@ -60,33 +61,34 @@ class nsIMenuItem;
class nsIAccessible;
class nsIContent;
class nsIURI;
-
+
/**
* Event Struct Types
*/
-#define NS_EVENT 1
-#define NS_GUI_EVENT 2
-#define NS_SIZE_EVENT 3
-#define NS_SIZEMODE_EVENT 4
-#define NS_ZLEVEL_EVENT 5
-#define NS_PAINT_EVENT 6
-#define NS_SCROLLBAR_EVENT 7
-#define NS_INPUT_EVENT 8
-#define NS_KEY_EVENT 9
-#define NS_MOUSE_EVENT 10
-#define NS_MENU_EVENT 11
-#define NS_SCRIPT_ERROR_EVENT 12
-#define NS_TEXT_EVENT 13
-#define NS_COMPOSITION_EVENT 14
-#define NS_RECONVERSION_EVENT 15
-#define NS_MOUSE_SCROLL_EVENT 16
-#define NS_SCROLLPORT_EVENT 18
-#define NS_ACCESSIBLE_EVENT 20
-#define NS_FORM_EVENT 21
-#define NS_FOCUS_EVENT 22
-#define NS_POPUP_EVENT 23
-#define NS_APPCOMMAND_EVENT 24
-#define NS_POPUPBLOCKED_EVENT 25
+#define NS_EVENT 1
+#define NS_GUI_EVENT 2
+#define NS_SIZE_EVENT 3
+#define NS_SIZEMODE_EVENT 4
+#define NS_ZLEVEL_EVENT 5
+#define NS_PAINT_EVENT 6
+#define NS_SCROLLBAR_EVENT 7
+#define NS_INPUT_EVENT 8
+#define NS_KEY_EVENT 9
+#define NS_MOUSE_EVENT 10
+#define NS_MENU_EVENT 11
+#define NS_SCRIPT_ERROR_EVENT 12
+#define NS_TEXT_EVENT 13
+#define NS_COMPOSITION_EVENT 14
+#define NS_RECONVERSION_EVENT 15
+#define NS_MOUSE_SCROLL_EVENT 16
+#define NS_SCROLLPORT_EVENT 18
+#define NS_ACCESSIBLE_EVENT 20
+#define NS_FORM_EVENT 21
+#define NS_FOCUS_EVENT 22
+#define NS_POPUP_EVENT 23
+#define NS_APPCOMMAND_EVENT 24
+#define NS_POPUPBLOCKED_EVENT 25
+#define NS_BEFORE_PAGE_UNLOAD_EVENT 26
#define NS_EVENT_FLAG_NONE 0x0000
@@ -205,6 +207,16 @@ struct nsScriptErrorEvent : public nsEvent
const PRUnichar* fileName;
};
+struct nsBeforePageUnloadEvent : public nsEvent
+{
+ nsBeforePageUnloadEvent(PRUint32 msg)
+ : nsEvent(msg, NS_BEFORE_PAGE_UNLOAD_EVENT)
+ {
+ }
+
+ nsString text;
+};
+
/**
* Window resize event
*/
@@ -723,6 +735,7 @@ enum nsDragDropEventStatus {
#define NS_IMAGE_ABORT (NS_STREAM_EVENT_START + 3)
#define NS_IMAGE_ERROR (NS_STREAM_EVENT_START + 4)
#define NS_SCRIPT_LOAD (NS_STREAM_EVENT_START + 5)
+#define NS_BEFORE_PAGE_UNLOAD (NS_STREAM_EVENT_START + 6)
#define NS_FORM_EVENT_START 1200
#define NS_FORM_SUBMIT (NS_FORM_EVENT_START)
View
37 xpfe/appshell/src/nsWebShellWindow.cpp
@@ -1489,26 +1489,25 @@ PRBool nsWebShellWindow::ExecuteCloseHandler()
than it otherwise would.) */
nsCOMPtr<nsIWebShellWindow> kungFuDeathGrip(this);
- nsresult rv;
- nsCOMPtr<nsIScriptGlobalObjectOwner> globalObjectOwner(do_QueryInterface(mWebShell));
- nsCOMPtr<nsIScriptGlobalObject> globalObject;
+ nsCOMPtr<nsIScriptGlobalObject> globalObject(do_GetInterface(mWebShell));
- if (globalObjectOwner) {
- if (NS_SUCCEEDED(globalObjectOwner->GetScriptGlobalObject(getter_AddRefs(globalObject))) && globalObject) {
- nsCOMPtr<nsIContentViewer> contentViewer;
- if (NS_SUCCEEDED(mDocShell->GetContentViewer(getter_AddRefs(contentViewer)))) {
- nsCOMPtr<nsIDocumentViewer> docViewer;
- nsCOMPtr<nsIPresContext> presContext;
- docViewer = do_QueryInterface(contentViewer);
- if (docViewer && NS_SUCCEEDED(docViewer->GetPresContext(getter_AddRefs(presContext)))) {
- nsEventStatus status = nsEventStatus_eIgnore;
- nsMouseEvent event(NS_XUL_CLOSE);
- rv = globalObject->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
- if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault)
- return PR_TRUE;
- // else fall through and return PR_FALSE
- }
- }
+ if (globalObject) {
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
+ nsCOMPtr<nsIDocumentViewer> docViewer(do_QueryInterface(contentViewer));
+
+ if (docViewer) {
+ nsCOMPtr<nsIPresContext> presContext;
+ docViewer->GetPresContext(getter_AddRefs(presContext));
+
+ nsEventStatus status = nsEventStatus_eIgnore;
+ nsMouseEvent event(NS_XUL_CLOSE);
+
+ nsresult rv = globalObject->HandleDOMEvent(presContext, &event, nsnull,
+ NS_EVENT_FLAG_INIT, &status);
+ if (NS_SUCCEEDED(rv) && status == nsEventStatus_eConsumeNoDefault)
+ return PR_TRUE;
+ // else fall through and return PR_FALSE
}
}
View
11 xpfe/browser/resources/content/navigator.js
@@ -2279,7 +2279,8 @@ function maybeInitPopupContext()
function WindowIsClosing()
{
var browser = getBrowser();
- var numtabs = browser.mTabContainer.childNodes.length;
+ var cn = browser.mTabContainer.childNodes;
+ var numtabs = cn.length;
var reallyClose = true;
if (numtabs > 1) {
@@ -2307,5 +2308,13 @@ function WindowIsClosing()
}
} //if the warn-me pref was true
} //if multiple tabs are open
+
+ for (var i = 0; reallyClose && i < numtabs; ++i) {
+ var ds = browser.getBrowserForTab(cn[i]).docShell;
+
+ if (ds.contentViewer && !ds.contentViewer.permitUnload())
+ reallyClose = false;
+ }
+
return reallyClose;
}
View
15 xpfe/global/resources/content/bindings/tabbrowser.xml
@@ -852,11 +852,11 @@
else
this.mTabContainer.selectedItem = aTab;
- while (this.mTabContainer.lastChild != aTab)
- this.removeTab(this.mTabContainer.lastChild);
-
- while (aTab.previousSibling)
- this.removeTab(aTab.previousSibling);
+ var childNodes = this.mTabContainer.childNodes;
+ for (var i = childNodes.length - 1; i >= 0; --i) {
+ if (childNodes[i] != aTab)
+ this.removeTab(childNodes[i]);
+ }
]]>
</body>
</method>
@@ -884,6 +884,11 @@
return;
}
+ var ds = this.getBrowserForTab(aTab).docShell;
+
+ if (ds.contentViewer && !ds.contentViewer.permitUnload())
+ return;
+
if (l == 2) {
var autohide = this.mPrefs.getBoolPref("browser.tabs.autoHide");
if (autohide)

0 comments on commit 64ad19a

Please sign in to comment.
Something went wrong with that request. Please try again.