зеркало из https://github.com/mozilla/pjs.git
Fixing bug 68215. Adding support for the onbeforeunload event. r=peterv@propagandism.org, sr=brendan@mozilla.org
This commit is contained in:
Родитель
6cca3beefc
Коммит
6ca4c1a78e
|
@ -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 @@ protected:
|
|||
|
||||
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
|
||||
|
@ -961,6 +967,104 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
|
|||
return rv;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
|
||||
// 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 @@ public:
|
|||
|
||||
// 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);
|
||||
|
@ -200,6 +202,18 @@ txLoadListenerProxy::Load(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -465,6 +479,14 @@ nsSyncLoader::Load(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSyncLoader::BeforeUnload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
// Like, whatever.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSyncLoader::Unload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ public:
|
|||
eDOMEvents_focus,
|
||||
eDOMEvents_blur,
|
||||
eDOMEvents_load,
|
||||
eDOMEvents_beforeunload,
|
||||
eDOMEvents_unload,
|
||||
eDOMEvents_abort,
|
||||
eDOMEvents_error,
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -292,11 +292,12 @@ protected:
|
|||
#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
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -232,6 +232,7 @@ public:
|
|||
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; };
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -149,10 +149,9 @@ public:
|
|||
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
PRBool mRepeat;
|
||||
PRInt32 mDelay;
|
||||
PRBool mMetaRefresh;
|
||||
|
||||
PRPackedBool mRepeat;
|
||||
PRPackedBool mMetaRefresh;
|
||||
|
||||
protected:
|
||||
virtual ~nsRefreshTimer();
|
||||
|
@ -359,31 +358,34 @@ protected:
|
|||
// 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 @@ protected:
|
|||
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 {
|
||||
|
|
|
@ -25,6 +25,7 @@ interface nsIContentViewer : nsISupports
|
|||
|
||||
void loadStart(in nsISupports aDoc);
|
||||
void loadComplete(in unsigned long aStatus);
|
||||
boolean permitUnload();
|
||||
void unload();
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,6 +63,13 @@ public:
|
|||
*/
|
||||
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
|
||||
|
|
|
@ -195,9 +195,9 @@ public:
|
|||
* @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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -240,6 +240,7 @@ protected:
|
|||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,9 +94,8 @@ public:
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
||||
rv = StopAll();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -301,6 +301,12 @@ nsDOMParser::Load(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMParser::BeforeUnload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMParser::Unload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
|
||||
// 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);
|
||||
|
|
|
@ -74,6 +74,18 @@ nsLoadListenerProxy::Load(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,7 @@ public:
|
|||
|
||||
// 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);
|
||||
|
|
|
@ -1435,6 +1435,12 @@ nsXMLHttpRequest::Unload(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::BeforeUnload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::Abort(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
|
|
@ -89,6 +89,7 @@ public:
|
|||
|
||||
// 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);
|
||||
|
|
|
@ -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 @@ protected:
|
|||
|
||||
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
|
||||
|
@ -961,6 +967,104 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
|
|||
return rv;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче