зеркало из https://github.com/mozilla/gecko-dev.git
Bug 544642: Make frames report an error event if the frame src is pointed at a local file url. And don't make setAttribute thrown an exception in that scenario. r=smaug
This commit is contained in:
Родитель
44b19b2421
Коммит
963e54b50f
|
@ -77,6 +77,7 @@
|
|||
#include "nsISHistoryInternal.h"
|
||||
#include "nsIDOMNSHTMLDocument.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsPLDOMEvent.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsIURL.h"
|
||||
|
@ -180,8 +181,28 @@ nsFrameLoader::LoadFrame()
|
|||
charset, base_uri);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return LoadURI(uri);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = LoadURI(uri);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
FireErrorEvent();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::FireErrorEvent()
|
||||
{
|
||||
if (mOwnerContent) {
|
||||
nsRefPtr<nsPLDOMEvent> event =
|
||||
new nsLoadBlockingPLDOMEvent(mOwnerContent, NS_LITERAL_STRING("error"),
|
||||
PR_FALSE, PR_FALSE);
|
||||
event->PostDOMEvent();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -209,6 +230,17 @@ nsFrameLoader::LoadURI(nsIURI* aURI)
|
|||
|
||||
nsresult
|
||||
nsFrameLoader::ReallyStartLoading()
|
||||
{
|
||||
nsresult rv = ReallyStartLoadingInternal();
|
||||
if (NS_FAILED(rv)) {
|
||||
FireErrorEvent();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::ReallyStartLoadingInternal()
|
||||
{
|
||||
NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInDoc());
|
||||
// Just to be safe, recheck uri.
|
||||
|
@ -240,11 +272,8 @@ nsFrameLoader::ReallyStartLoading()
|
|||
nsIWebNavigation::LOAD_FLAGS_NONE, PR_FALSE);
|
||||
mNeedsAsyncDestroy = tmpState;
|
||||
mURIToLoad = nsnull;
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to load the URL");
|
||||
}
|
||||
#endif
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,8 @@ private:
|
|||
NS_HIDDEN_(nsresult) EnsureDocShell();
|
||||
NS_HIDDEN_(void) GetURL(nsString& aURL);
|
||||
nsresult CheckURILoad(nsIURI* aURI);
|
||||
void FireErrorEvent();
|
||||
nsresult ReallyStartLoadingInternal();
|
||||
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
nsCOMPtr<nsIURI> mURIToLoad;
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "imgILoader.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPLDOMEvent.h"
|
||||
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
|
@ -884,58 +885,6 @@ nsImageLoadingContent::StringToURI(const nsAString& aSpec,
|
|||
nsContentUtils::GetIOService());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class used to dispatch events
|
||||
*/
|
||||
|
||||
class nsImageLoadingContent::Event : public nsRunnable
|
||||
{
|
||||
public:
|
||||
Event(nsPresContext* aPresContext, nsImageLoadingContent* aContent,
|
||||
const nsAString& aMessage, nsIDocument* aDocument)
|
||||
: mPresContext(aPresContext),
|
||||
mContent(aContent),
|
||||
mMessage(aMessage),
|
||||
mDocument(aDocument)
|
||||
{
|
||||
}
|
||||
~Event()
|
||||
{
|
||||
mDocument->UnblockOnload(PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
nsCOMPtr<nsPresContext> mPresContext;
|
||||
nsRefPtr<nsImageLoadingContent> mContent;
|
||||
nsString mMessage;
|
||||
// Need to hold on to the document in case our event outlives document
|
||||
// teardown... Wantto be able to get back to the document even if the
|
||||
// prescontext and content can't.
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::Event::Run()
|
||||
{
|
||||
PRUint32 eventMsg;
|
||||
|
||||
if (mMessage.EqualsLiteral("load")) {
|
||||
eventMsg = NS_LOAD;
|
||||
} else {
|
||||
eventMsg = NS_LOAD_ERROR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> ourContent = do_QueryInterface(mContent);
|
||||
|
||||
nsEvent event(PR_TRUE, eventMsg);
|
||||
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
|
||||
nsEventDispatcher::Dispatch(ourContent, mPresContext, &event);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::FireEvent(const nsAString& aEventType)
|
||||
{
|
||||
|
@ -943,27 +892,13 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType)
|
|||
// loops in cases when onLoad handlers reset the src and the new src is in
|
||||
// cache.
|
||||
|
||||
nsCOMPtr<nsIDocument> document = GetOurDocument();
|
||||
if (!document) {
|
||||
// no use to fire events if there is no document....
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsINode> thisNode = do_QueryInterface(this);
|
||||
|
||||
// We should not be getting called from off the UI thread...
|
||||
NS_ASSERTION(NS_IsMainThread(), "should be on the main thread");
|
||||
nsRefPtr<nsPLDOMEvent> event =
|
||||
new nsLoadBlockingPLDOMEvent(thisNode, aEventType, PR_FALSE, PR_FALSE);
|
||||
event->PostDOMEvent();
|
||||
|
||||
nsIPresShell *shell = document->GetPrimaryShell();
|
||||
nsPresContext *presContext = shell ? shell->GetPresContext() : nsnull;
|
||||
|
||||
nsCOMPtr<nsIRunnable> evt =
|
||||
new nsImageLoadingContent::Event(presContext, this, aEventType, document);
|
||||
NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Block onload for our event. Since we unblock in the event destructor, we
|
||||
// want to block now, even if posting will fail.
|
||||
document->BlockOnload();
|
||||
|
||||
return NS_DispatchToCurrentThread(evt);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -245,8 +245,6 @@ private:
|
|||
* @param aEventType "load" or "error" depending on how things went
|
||||
*/
|
||||
nsresult FireEvent(const nsAString& aEventType);
|
||||
class Event;
|
||||
friend class Event;
|
||||
protected:
|
||||
void CreateStaticImageClone(nsImageLoadingContent* aDest) const;
|
||||
|
||||
|
|
|
@ -327,6 +327,7 @@ _TEST_FILES = test_bug5141.html \
|
|||
test_range_bounds.html \
|
||||
test_bug475156.html \
|
||||
bug475156.sjs \
|
||||
test_bug544642.html \
|
||||
test_copypaste.html \
|
||||
test_bug503481.html \
|
||||
file_bug503481.sjs \
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for bug 544642</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=544642"
|
||||
target="_blank" >Mozilla Bug 544642</a>
|
||||
<p id="display"></p>
|
||||
<iframe id=iframe></iframe>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var gen = runTest();
|
||||
|
||||
addLoadEvent(function() { gen.next(); });
|
||||
|
||||
function runTest() {
|
||||
var iframe = $('iframe');
|
||||
iframe.onerror = function() { gen.send("error"); };
|
||||
iframe.onload = function() { gen.send("load"); };
|
||||
|
||||
iframe.src = "data:text/plain,hello";
|
||||
is((yield), "load", "plaintext data");
|
||||
|
||||
iframe.src = "file://foo/bar";
|
||||
is((yield), "error", "file");
|
||||
|
||||
// We should do this test too, however it brings up a modal dialog which
|
||||
// we can't dismiss.
|
||||
//iframe.src = "http:////";
|
||||
//is((yield), "error", "invalid http");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -43,6 +43,7 @@
|
|||
#include "nsINode.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
/**
|
||||
* Use nsPLDOMEvent to fire a DOM event that requires safe a stable DOM.
|
||||
|
@ -58,8 +59,9 @@
|
|||
class nsPLDOMEvent : public nsRunnable {
|
||||
public:
|
||||
nsPLDOMEvent(nsINode *aEventNode, const nsAString& aEventType,
|
||||
PRBool aDispatchChromeOnly)
|
||||
PRBool aBubbles, PRBool aDispatchChromeOnly)
|
||||
: mEventNode(aEventNode), mEventType(aEventType),
|
||||
mBubbles(aBubbles),
|
||||
mDispatchChromeOnly(aDispatchChromeOnly)
|
||||
{ }
|
||||
|
||||
|
@ -74,7 +76,34 @@ public:
|
|||
nsCOMPtr<nsINode> mEventNode;
|
||||
nsCOMPtr<nsIDOMEvent> mEvent;
|
||||
nsString mEventType;
|
||||
PRBool mDispatchChromeOnly;
|
||||
PRPackedBool mBubbles;
|
||||
PRPackedBool mDispatchChromeOnly;
|
||||
};
|
||||
|
||||
class nsLoadBlockingPLDOMEvent : public nsPLDOMEvent {
|
||||
public:
|
||||
nsLoadBlockingPLDOMEvent(nsINode *aEventNode, const nsAString& aEventType,
|
||||
PRBool aBubbles, PRBool aDispatchChromeOnly)
|
||||
: nsPLDOMEvent(aEventNode, aEventType, aBubbles, aDispatchChromeOnly),
|
||||
mBlockedDoc(aEventNode->GetOwnerDoc())
|
||||
{
|
||||
if (mBlockedDoc) {
|
||||
mBlockedDoc->BlockOnload();
|
||||
}
|
||||
}
|
||||
|
||||
nsLoadBlockingPLDOMEvent(nsINode *aEventNode, nsIDOMEvent *aEvent)
|
||||
: nsPLDOMEvent(aEventNode, aEvent),
|
||||
mBlockedDoc(aEventNode->GetOwnerDoc())
|
||||
{
|
||||
if (mBlockedDoc) {
|
||||
mBlockedDoc->BlockOnload();
|
||||
}
|
||||
}
|
||||
|
||||
~nsLoadBlockingPLDOMEvent();
|
||||
|
||||
nsCOMPtr<nsIDocument> mBlockedDoc;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,10 +59,10 @@ NS_IMETHODIMP nsPLDOMEvent::Run()
|
|||
if (doc) {
|
||||
if (mDispatchChromeOnly) {
|
||||
nsContentUtils::DispatchChromeEvent(doc, mEventNode, mEventType,
|
||||
PR_TRUE, PR_TRUE);
|
||||
mBubbles, PR_FALSE);
|
||||
} else {
|
||||
nsContentUtils::DispatchTrustedEvent(doc, mEventNode, mEventType,
|
||||
PR_TRUE, PR_TRUE);
|
||||
mBubbles, PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,3 +79,10 @@ nsresult nsPLDOMEvent::RunDOMEventWhenSafe()
|
|||
{
|
||||
return nsContentUtils::AddScriptRunner(this) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsLoadBlockingPLDOMEvent::~nsLoadBlockingPLDOMEvent()
|
||||
{
|
||||
if (mBlockedDoc) {
|
||||
mBlockedDoc->UnblockOnload(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2822,13 +2822,16 @@ nsGenericHTMLFrameElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
{
|
||||
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
|
||||
aValue, aNotify);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None &&
|
||||
if (aNameSpaceID == kNameSpaceID_None &&
|
||||
aName == nsGkAtoms::src) {
|
||||
return LoadSrc();
|
||||
// Don't propagate error here. The attribute was successfully set, that's
|
||||
// what we should reflect.
|
||||
LoadSrc();
|
||||
}
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -272,7 +272,8 @@ nsHTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
|
|||
strings, eIgnoreCase) != ATTR_VALUE_NO_MATCH)
|
||||
return;
|
||||
|
||||
nsRefPtr<nsPLDOMEvent> event = new nsPLDOMEvent(this, aEventName, PR_TRUE);
|
||||
nsRefPtr<nsPLDOMEvent> event = new nsPLDOMEvent(this, aEventName, PR_TRUE,
|
||||
PR_TRUE);
|
||||
if (event) {
|
||||
// Always run async in order to avoid running script when the content
|
||||
// sink isn't expecting it.
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPLDOMEvent.h"
|
||||
|
||||
class nsHTMLTitleElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLTitleElement,
|
||||
|
|
|
@ -1450,8 +1450,9 @@ nsComboboxControlFrame::OnOptionSelected(PRInt32 aIndex, PRBool aSelected)
|
|||
void nsComboboxControlFrame::FireValueChangeEvent()
|
||||
{
|
||||
// Fire ValueChange event to indicate data value of combo box has changed
|
||||
nsContentUtils::AddScriptRunner(new nsPLDOMEvent(mContent,
|
||||
NS_LITERAL_STRING("ValueChange"), PR_FALSE));
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new nsPLDOMEvent(mContent, NS_LITERAL_STRING("ValueChange"), PR_TRUE,
|
||||
PR_FALSE));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1616,7 +1616,7 @@ nsFrame::FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent)
|
|||
|
||||
if (target) {
|
||||
nsRefPtr<nsPLDOMEvent> event =
|
||||
new nsPLDOMEvent(target, aDOMEventName, PR_FALSE);
|
||||
new nsPLDOMEvent(target, aDOMEventName, PR_TRUE, PR_FALSE);
|
||||
if (!event || NS_FAILED(event->PostDOMEvent()))
|
||||
NS_WARNING("Failed to dispatch nsPLDOMEvent");
|
||||
}
|
||||
|
|
|
@ -660,7 +660,7 @@ NS_IMETHODIMP nsTreeSelection::SetCurrentIndex(PRInt32 aIndex)
|
|||
|
||||
nsRefPtr<nsPLDOMEvent> event =
|
||||
new nsPLDOMEvent(treeDOMNode, NS_LITERAL_STRING("DOMMenuItemActive"),
|
||||
PR_FALSE);
|
||||
PR_TRUE, PR_FALSE);
|
||||
if (!event)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
@ -845,7 +845,7 @@ nsTreeSelection::FireOnSelectHandler()
|
|||
NS_ENSURE_STATE(node);
|
||||
|
||||
nsRefPtr<nsPLDOMEvent> event =
|
||||
new nsPLDOMEvent(node, NS_LITERAL_STRING("select"), PR_FALSE);
|
||||
new nsPLDOMEvent(node, NS_LITERAL_STRING("select"), PR_TRUE, PR_FALSE);
|
||||
event->RunDOMEventWhenSafe();
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче