Backed out 10 changesets (bug 1614462) for causing xpcshell failures CLOSED TREE

Backed out changeset 34d4a86530b4 (bug 1614462)
Backed out changeset dbc2e2556d08 (bug 1614462)
Backed out changeset 512bbab4730c (bug 1614462)
Backed out changeset cd6b8d630f4c (bug 1614462)
Backed out changeset e4ad5037658f (bug 1614462)
Backed out changeset 0ffed1dc4296 (bug 1614462)
Backed out changeset 90ed81cbfe34 (bug 1614462)
Backed out changeset 6d2137eb1d52 (bug 1614462)
Backed out changeset b4819c99e16e (bug 1614462)
Backed out changeset b7deaed376ed (bug 1614462)
This commit is contained in:
Ciure Andrei 2020-04-17 02:26:14 +03:00
parent dee341d82a
commit c15dcac93b
260 changed files with 9434 additions and 1507 deletions

View File

@ -57,7 +57,7 @@
frame1.docShell.chromeEventHandler.removeAttribute("crashedPageTitle");
SimpleTest.is(frame1.contentDocument.documentURI,
"about:tabcrashed?e=tabcrashed&u=http%3A//www.example.com/1&c=UTF-8&d=pageTitle",
"about:tabcrashed?e=tabcrashed&u=http%3A//www.example.com/1&c=UTF-8&f=regular&d=pageTitle",
"Correct about:tabcrashed displayed for page with title.");
errorPageReady = waitForErrorPage(frame2);
@ -66,7 +66,7 @@
await errorPageReady;
SimpleTest.is(frame2.contentDocument.documentURI,
"about:tabcrashed?e=tabcrashed&u=http%3A//www.example.com/2&c=UTF-8&d=%20",
"about:tabcrashed?e=tabcrashed&u=http%3A//www.example.com/2&c=UTF-8&f=regular&d=%20",
"Correct about:tabcrashed displayed for page with no title.");
SimpleTest.finish();

View File

@ -55,7 +55,7 @@
frame1.docShell.chromeEventHandler.removeAttribute("crashedPageTitle");
SimpleTest.is(frame1.contentDocument.documentURI,
"about:restartrequired?e=restartrequired&u=http%3A//www.example.com/1&c=UTF-8&d=%20",
"about:restartrequired?e=restartrequired&u=http%3A//www.example.com/1&c=UTF-8&f=regular&d=%20",
"Correct about:restartrequired displayed for page with title.");
errorPageReady = waitForErrorPage(frame2);
@ -64,7 +64,7 @@
await errorPageReady;
SimpleTest.is(frame2.contentDocument.documentURI,
"about:restartrequired?e=restartrequired&u=http%3A//www.example.com/2&c=UTF-8&d=%20",
"about:restartrequired?e=restartrequired&u=http%3A//www.example.com/2&c=UTF-8&f=regular&d=%20",
"Correct about:restartrequired displayed for page with no title.");
SimpleTest.finish();

View File

@ -18,6 +18,48 @@ async function openTabInUserContext(uri, userContextId) {
return { tab, browser };
}
// Opens `uri' in a new <iframe mozbrowser> with the provided userContextId.
// Returns the newly opened browser.
async function addBrowserFrameInUserContext(uri, userContextId) {
// Create a browser frame with the user context and uri
const browser = document.createElementNS(
"http://www.w3.org/1999/xhtml",
"iframe"
);
browser.setAttribute("remote", "true");
browser.setAttribute("usercontextid", userContextId);
browser.setAttribute("mozbrowser", "true");
// `noisolation = true` means `OA.mInIsolatedMozBrowser = false` which matches
// the default for a XUL browser. It is indepedent from user contexts.
browser.setAttribute("noisolation", "true");
browser.setAttribute("src", uri);
gBrowser.tabpanels.appendChild(browser);
// Create a XUL browser-like API expected by test helpers
Object.defineProperty(browser, "messageManager", {
get() {
return browser.frameLoader.messageManager;
},
configurable: true,
enumerable: true,
});
await browserFrameLoaded(browser);
return { browser };
}
function browserFrameLoaded(browser) {
let event = "BrowserTestUtils:ContentEvent:load";
return BrowserTestUtils.waitForEvent(browser, event);
}
function removeBrowserFrame({ browser }) {
browser.remove();
// Clean up Browser API parent-side data
delete window._browserElementParents;
}
async function runTestForReceiver(receiver) {
let channelName = "contextualidentity-broadcastchannel";
@ -81,3 +123,13 @@ add_task(async function test() {
await runTestForReceiver(receiver);
gBrowser.removeTab(receiver.tab);
});
add_task(async function test() {
info("Checking broadcast channel with <iframe mozbrowser> receiver");
await SpecialPowers.pushPrefEnv({
set: [["dom.mozBrowserFramesEnabled", true]],
});
let receiver = await addBrowserFrameInUserContext(URI, 2);
await runTestForReceiver(receiver);
removeBrowserFrame(receiver);
});

View File

@ -354,6 +354,7 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mLoadType(0),
mDefaultLoadFlags(nsIRequest::LOAD_NORMAL),
mFailedLoadType(0),
mFrameType(FRAME_TYPE_REGULAR),
mDisplayMode(nsIDocShell::DISPLAY_MODE_BROWSER),
mJSRunToCompletionDepth(0),
mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE),
@ -1841,6 +1842,21 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed) {
return parent->GetFullscreenAllowed(aFullscreenAllowed);
}
NS_IMETHODIMP
nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed) {
if (!nsIDocShell::GetIsMozBrowser()) {
// Only allow setting of fullscreenAllowed on content/process boundaries.
// At non-boundaries the fullscreenAllowed attribute is calculated based on
// whether all enclosing frames have the "mozFullscreenAllowed" attribute
// set to "true". fullscreenAllowed is set at the process boundaries to
// propagate the value of the parent's "mozFullscreenAllowed" attribute
// across process boundaries.
return NS_ERROR_UNEXPECTED;
}
mFullscreenAllowed = (aFullscreenAllowed ? PARENT_ALLOWS : PARENT_PROHIBITS);
return NS_OK;
}
hal::ScreenOrientation nsDocShell::OrientationLock() {
return mOrientationLock;
}
@ -2622,8 +2638,21 @@ void nsDocShell::MaybeClearStorageAccessFlag() {
NS_IMETHODIMP
nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
*aParent = do_AddRef(parentBC->GetDocShell()).take();
NS_ENSURE_ARG_POINTER(aParent);
*aParent = nullptr;
if (nsIDocShell::GetIsMozBrowser()) {
return NS_OK;
}
nsCOMPtr<nsIDocShellTreeItem> parent =
do_QueryInterface(GetAsSupports(mParent));
if (!parent) {
return NS_OK;
}
if (parent->ItemType() == mItemType) {
parent.swap(*aParent);
}
return NS_OK;
}
@ -3867,6 +3896,10 @@ nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
}
errorPageUrl.AppendLiteral("&c=UTF-8");
nsAutoCString frameType(FrameTypeToString(mFrameType));
errorPageUrl.AppendLiteral("&f=");
errorPageUrl.AppendASCII(frameType.get());
nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
int32_t cpsState;
if (cps && NS_SUCCEEDED(cps->GetState(&cpsState)) &&
@ -4698,7 +4731,9 @@ nsDocShell::SetIsActive(bool aIsActive) {
continue;
}
docshell->SetIsActive(aIsActive);
if (!docshell->GetIsMozBrowser()) {
docshell->SetIsActive(aIsActive);
}
}
// Restart or stop meta refresh timers if necessary
@ -8987,7 +9022,8 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
}
}
bool isTopLevelDoc = mBrowsingContext->IsTopContent();
bool isTopLevelDoc =
mItemType == typeContent && (!IsFrame() || GetIsMozBrowser());
OriginAttributes attrs = GetOriginAttributes();
attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
@ -12367,6 +12403,46 @@ nsDocShell::GetCanExecuteScripts(bool* aResult) {
return NS_OK;
}
/* [infallible] */
NS_IMETHODIMP nsDocShell::SetFrameType(FrameType aFrameType) {
mFrameType = aFrameType;
return NS_OK;
}
/* [infallible] */
NS_IMETHODIMP nsDocShell::GetFrameType(FrameType* aFrameType) {
*aFrameType = mFrameType;
return NS_OK;
}
/* [infallible] */
NS_IMETHODIMP nsDocShell::GetIsMozBrowser(bool* aIsMozBrowser) {
*aIsMozBrowser = (mFrameType == FRAME_TYPE_BROWSER);
return NS_OK;
}
uint32_t nsDocShell::GetInheritedFrameType() {
if (mFrameType != FRAME_TYPE_REGULAR) {
return mFrameType;
}
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
if (!parent) {
return FRAME_TYPE_REGULAR;
}
return static_cast<nsDocShell*>(parent.get())->GetInheritedFrameType();
}
/* [infallible] */
NS_IMETHODIMP nsDocShell::GetIsInMozBrowser(bool* aIsInMozBrowser) {
*aIsInMozBrowser = (GetInheritedFrameType() == FRAME_TYPE_BROWSER);
return NS_OK;
}
/* [infallible] */
NS_IMETHODIMP nsDocShell::GetIsTopLevelContentDocShell(
bool* aIsTopLevelContentDocShell) {

View File

@ -569,6 +569,18 @@ class nsDocShell final : public nsDocLoader,
return uint32_t(aTimeUsec / PR_USEC_PER_SEC);
}
static const nsCString FrameTypeToString(uint32_t aFrameType) {
switch (aFrameType) {
case FRAME_TYPE_BROWSER:
return NS_LITERAL_CSTRING("browser");
case FRAME_TYPE_REGULAR:
return NS_LITERAL_CSTRING("regular");
default:
NS_ERROR("Unknown frame type");
return EmptyCString();
}
}
virtual ~nsDocShell();
//
@ -997,6 +1009,7 @@ class nsDocShell final : public nsDocLoader,
bool IsPrintingOrPP(bool aDisplayErrorDialog = true);
bool IsNavigationAllowed(bool aDisplayPrintErrorDialog = true,
bool aCheckIfUnloadFired = true);
uint32_t GetInheritedFrameType();
nsIScrollableFrame* GetRootScrollFrame();
nsIChannel* GetCurrentDocChannel();
nsresult EnsureScriptEnvironment();
@ -1216,6 +1229,9 @@ class nsDocShell final : public nsDocLoader,
uint32_t mDefaultLoadFlags;
uint32_t mFailedLoadType;
// Are we a regular frame, a browser frame, or an app frame?
FrameType mFrameType;
// This represents the CSS display-mode we are currently using. This is mostly
// used for media queries.
DisplayMode mDisplayMode;

View File

@ -684,6 +684,32 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
[noscript] void notifyScrollObservers();
/**
* The type of iframe that this docshell lives.
*/
cenum FrameType : 8 {
FRAME_TYPE_REGULAR = 0,
FRAME_TYPE_BROWSER = 1,
};
[infallible] attribute nsIDocShell_FrameType frameType;
/**
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
* <xul:browser> returns false here.
*/
[infallible] readonly attribute boolean isMozBrowser;
/**
* Returns true if this docshell corresponds to an <iframe mozbrowser>, or
* if this docshell is contained in an <iframe mozbrowser>. <xul:browser>
* returns false here.
*
* To compute this value, we walk up the docshell hierarchy. If we encounter
* a docshell with isMozBrowser before we hit the end of the hierarchy,
* we return true. Otherwise, we return false.
*/
[infallible] readonly attribute boolean isInMozBrowser;
/**
* Returns true if this docshell is the top level content docshell.
*/
@ -691,7 +717,7 @@ interface nsIDocShell : nsIDocShellTreeItem
/**
* Like nsIDocShellTreeItem::GetSameTypeParent, except this ignores <iframe
* mozbrowser> boundaries. Which no longer exist.
* mozbrowser> boundaries.
*
* @deprecated: Use `BrowsingContext::GetParent()` in the future.
*/
@ -753,6 +779,8 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
[infallible] readonly attribute boolean fullscreenAllowed;
void setFullscreenAllowed(in boolean allowed);
[notxpcom] uint32_t orientationLock();
[notxpcom] void setOrientationLock(in uint32_t orientationLock);

View File

@ -46,8 +46,8 @@ InProcessBrowserChildMessageManager::Create(nsDocShell* aShell,
bool InProcessBrowserChildMessageManager::DoSendBlockingMessage(
JSContext* aCx, const nsAString& aMessage, StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows, nsTArray<StructuredCloneData>* aRetVal,
bool aIsSync) {
JS::Handle<JSObject*> aCpows, nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal, bool aIsSync) {
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
queue->Flush();
@ -55,8 +55,8 @@ bool InProcessBrowserChildMessageManager::DoSendBlockingMessage(
SameProcessCpowHolder cpows(JS::RootingContext::get(aCx), aCpows);
RefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
RefPtr<nsFrameLoader> fl = GetFrameLoader();
mm->ReceiveMessage(mOwner, fl, aMessage, true, &aData, &cpows, aRetVal,
IgnoreErrors());
mm->ReceiveMessage(mOwner, fl, aMessage, true, &aData, &cpows, aPrincipal,
aRetVal, IgnoreErrors());
}
return true;
}
@ -81,13 +81,13 @@ class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
nsresult InProcessBrowserChildMessageManager::DoSendAsyncMessage(
JSContext* aCx, const nsAString& aMessage, StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) {
JS::Handle<JSObject*> aCpows, nsIPrincipal* aPrincipal) {
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
RefPtr<nsAsyncMessageToParent> ev =
new nsAsyncMessageToParent(rcx, aCpows, this);
nsresult rv = ev->Init(aMessage, aData);
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}

View File

@ -76,11 +76,13 @@ class InProcessBrowserChildMessageManager final
virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
bool aIsSync) override;
virtual nsresult DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) override;
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal) override;
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;

View File

@ -30,7 +30,7 @@ class MessageBroadcaster : public MessageListenerManager {
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
mozilla::ErrorResult& aError) {
DispatchAsyncMessage(aCx, aMessageName, aObj, aObjects,
DispatchAsyncMessage(aCx, aMessageName, aObj, aObjects, nullptr,
JS::UndefinedHandleValue, aError);
}
uint32_t ChildCount() { return mChildManagers.Length(); }

View File

@ -37,6 +37,14 @@ void MessageManagerGlobal::Dump(const nsAString& aStr) {
fflush(stdout);
}
void MessageManagerGlobal::PrivateNoteIntentionalCrash(ErrorResult& aError) {
if (XRE_IsContentProcess()) {
NoteIntentionalCrash("tab");
return;
}
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
void MessageManagerGlobal::Atob(const nsAString& aAsciiString,
nsAString& aBase64Data, ErrorResult& aError) {
aError = nsContentUtils::Atob(aAsciiString, aBase64Data);

View File

@ -59,13 +59,14 @@ class MessageManagerGlobal {
void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
nsIPrincipal* aPrincipal,
JS::Handle<JS::Value> aTransfers, ErrorResult& aError) {
if (!mMessageManager) {
aError.Throw(NS_ERROR_NOT_INITIALIZED);
return;
}
mMessageManager->SendAsyncMessage(aCx, aMessageName, aObj, aObjects,
aTransfers, aError);
aPrincipal, aTransfers, aError);
}
already_AddRefed<ProcessMessageManager> GetProcessMessageManager(
mozilla::ErrorResult& aError) {
@ -87,29 +88,30 @@ class MessageManagerGlobal {
// SyncMessageSender
void SendSyncMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal,
nsTArray<JS::Value>& aResult, ErrorResult& aError) {
if (!mMessageManager) {
aError.Throw(NS_ERROR_NOT_INITIALIZED);
return;
}
mMessageManager->SendSyncMessage(aCx, aMessageName, aObj, aObjects, aResult,
aError);
mMessageManager->SendSyncMessage(aCx, aMessageName, aObj, aObjects,
aPrincipal, aResult, aError);
}
void SendRpcMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal,
nsTArray<JS::Value>& aResult, ErrorResult& aError) {
if (!mMessageManager) {
aError.Throw(NS_ERROR_NOT_INITIALIZED);
return;
}
mMessageManager->SendRpcMessage(aCx, aMessageName, aObj, aObjects, aResult,
aError);
mMessageManager->SendRpcMessage(aCx, aMessageName, aObj, aObjects,
aPrincipal, aResult, aError);
}
// MessageManagerGlobal
void Dump(const nsAString& aStr);
void PrivateNoteIntentionalCrash(ErrorResult& aError);
void Atob(const nsAString& aAsciiString, nsAString& aBase64Data,
ErrorResult& aError);
void Btoa(const nsAString& aBase64Data, nsAString& aAsciiString,

View File

@ -236,30 +236,25 @@ static void GetFrameName(Element* aOwnerContent, nsAString& aFrameName) {
// manner, they are no longer handled by typeContent and typeChrome. Instead,
// the actual BrowsingContext tree is broken at these edges.
static bool IsTopContent(BrowsingContext* aParent, Element* aOwner) {
if (XRE_IsContentProcess()) {
return false;
}
// If we have a (deprecated) mozbrowser element, we want to start a new
// BrowsingContext tree regardless of whether the parent is chrome or content.
nsCOMPtr<nsIMozBrowserFrame> mozbrowser = aOwner->GetAsMozBrowserFrame();
if (mozbrowser && mozbrowser->GetReallyIsBrowser()) {
return true;
}
if (aParent->IsContent()) {
// If we're already in content, we may still want to create a new
// BrowsingContext tree if our element is a xul browser element with a
// `remote="true"` marker.
return aOwner->IsXULElement() &&
aOwner->AttrValueIs(kNameSpaceID_None, nsGkAtoms::remote,
nsGkAtoms::_true, eCaseMatters);
// BrowsingContext tree if our element is either:
// a) a real <iframe mozbrowser> frame, or
// b) a xul browser element with a `remote="true"` marker.
return (mozbrowser && mozbrowser->GetReallyIsBrowser()) ||
(aOwner->IsXULElement() &&
aOwner->AttrValueIs(kNameSpaceID_None, nsGkAtoms::remote,
nsGkAtoms::_true, eCaseMatters));
}
// If we're in a chrome context, we want to start a new tree if we are an
// element with a `type="content"` marker.
return aOwner->AttrValueIs(kNameSpaceID_None, TypeAttrName(aOwner),
nsGkAtoms::content, eIgnoreCase);
// If we're in a chrome context, we want to start a new tree if:
// a) we have any mozbrowser frame (even if disabled), or
// b) we are an element with a `type="content"` marker.
return (mozbrowser && mozbrowser->GetMozbrowser()) ||
(aOwner->AttrValueIs(kNameSpaceID_None, TypeAttrName(aOwner),
nsGkAtoms::content, eIgnoreCase));
}
static already_AddRefed<BrowsingContext> CreateBrowsingContext(
@ -308,8 +303,19 @@ static already_AddRefed<BrowsingContext> CreateBrowsingContext(
// for the BrowsingContext, and cause no end of trouble.
if (IsTopContent(parentContext, aOwner)) {
// Create toplevel content without a parent & as Type::Content.
return BrowsingContext::CreateDetached(nullptr, opener, frameName,
BrowsingContext::Type::Content);
RefPtr<BrowsingContext> bc = BrowsingContext::CreateDetached(
nullptr, opener, frameName, BrowsingContext::Type::Content);
// If this is a mozbrowser frame, pretend it's windowless so that it gets
// ownership of its BrowsingContext even though it's a top-level content
// frame. This is horrible, but will fortunately go away soon.
if (nsCOMPtr<nsIMozBrowserFrame> mozbrowser =
aOwner->GetAsMozBrowserFrame()) {
if (mozbrowser->GetReallyIsBrowser()) {
bc->SetWindowless();
}
}
return bc.forget();
}
MOZ_ASSERT(!aOpenWindowInfo,
@ -2139,9 +2145,13 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
NS_ENSURE_SUCCESS(rv, rv);
}
if (OwnerIsMozBrowserFrame()) {
docShell->SetFrameType(nsIDocShell::FRAME_TYPE_BROWSER);
}
// Apply sandbox flags even if our owner is not an iframe, as this copies
// flags from our owning content's owning document.
// Note: ApplySandboxFlags should be called after docShell->SetIsFrame
// Note: ApplySandboxFlags should be called after docShell->SetFrameType
// because we need to get the correct presentation URL in ApplySandboxFlags.
uint32_t sandboxFlags = 0;
HTMLIFrameElement* iframe = HTMLIFrameElement::FromNode(mOwnerContent);
@ -2156,6 +2166,10 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
if (mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
docShell->SetName(name);
}
docShell->SetFullscreenAllowed(
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
mOwnerContent->HasAttr(kNameSpaceID_None,
nsGkAtoms::mozallowfullscreen));
}
// Typically there will be a window, however for some cases such as printing
@ -2163,7 +2177,8 @@ nsresult nsFrameLoader::MaybeCreateDocShell() {
// that the window exists to ensure we don't try to gather ancestors for
// those cases.
nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
if (parentDocShell->ItemType() == docShell->ItemType() &&
if (!docShell->GetIsMozBrowser() &&
parentDocShell->ItemType() == docShell->ItemType() &&
!doc->IsStaticDocument() && win) {
// Propagate through the ancestor principals.
nsTArray<nsCOMPtr<nsIPrincipal>> ancestorPrincipals;
@ -2804,7 +2819,8 @@ class nsAsyncMessageToChild : public nsSameProcessAsyncMessageBase,
nsresult nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) {
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal) {
auto* browserParent = GetBrowserParent();
if (browserParent) {
ClonedMessageData data;
@ -2818,7 +2834,8 @@ nsresult nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
return NS_ERROR_UNEXPECTED;
}
if (browserParent->SendAsyncMessage(nsString(aMessage), cpows, data)) {
if (browserParent->SendAsyncMessage(nsString(aMessage), cpows, aPrincipal,
data)) {
return NS_OK;
} else {
return NS_ERROR_UNEXPECTED;
@ -2829,7 +2846,7 @@ nsresult nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
RefPtr<nsAsyncMessageToChild> ev =
new nsAsyncMessageToChild(rcx, aCpows, this);
nsresult rv = ev->Init(aMessage, aData);
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
@ -3329,9 +3346,9 @@ nsresult nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
uint32_t maxTouchPoints = BrowserParent::GetMaxTouchPoints(mOwnerContent);
bool tabContextUpdated =
aTabContext->SetTabContext(chromeOuterWindowID, showFocusRings, attrs,
presentationURLStr, maxTouchPoints);
bool tabContextUpdated = aTabContext->SetTabContext(
OwnerIsMozBrowserFrame(), chromeOuterWindowID, showFocusRings, attrs,
presentationURLStr, maxTouchPoints);
NS_ENSURE_STATE(tabContextUpdated);
return NS_OK;

View File

@ -256,7 +256,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
virtual nsresult DoSendAsyncMessage(
JSContext* aCx, const nsAString& aMessage,
mozilla::dom::ipc::StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) override;
JS::Handle<JSObject*> aCpows, nsIPrincipal* aPrincipal) override;
/**
* Called from the layout frame associated with this frame loader;

View File

@ -446,8 +446,8 @@ static bool AllowMessage(size_t aDataLength, const nsAString& aMessageName) {
void nsFrameMessageManager::SendMessage(
JSContext* aCx, const nsAString& aMessageName, JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects, bool aIsSync, nsTArray<JS::Value>& aResult,
ErrorResult& aError) {
JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal, bool aIsSync,
nsTArray<JS::Value>& aResult, ErrorResult& aError) {
NS_ASSERTION(!IsGlobal(), "Should not call SendSyncMessage in chrome");
NS_ASSERTION(!IsBroadcaster(), "Should not call SendSyncMessage in chrome");
NS_ASSERTION(!GetParentManager(),
@ -491,7 +491,7 @@ void nsFrameMessageManager::SendMessage(
TimeStamp start = TimeStamp::Now();
sSendingSyncMessage |= aIsSync;
bool ok = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, aObjects,
&retval, aIsSync);
aPrincipal, &retval, aIsSync);
if (aIsSync) {
sSendingSyncMessage = false;
}
@ -526,12 +526,12 @@ void nsFrameMessageManager::SendMessage(
nsresult nsFrameMessageManager::DispatchAsyncMessageInternal(
JSContext* aCx, const nsAString& aMessage, StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) {
JS::Handle<JSObject*> aCpows, nsIPrincipal* aPrincipal) {
if (mIsBroadcaster) {
uint32_t len = mChildManagers.Length();
for (uint32_t i = 0; i < len; ++i) {
mChildManagers[i]->DispatchAsyncMessageInternal(aCx, aMessage, aData,
aCpows);
aCpows, aPrincipal);
}
return NS_OK;
}
@ -540,7 +540,8 @@ nsresult nsFrameMessageManager::DispatchAsyncMessageInternal(
return NS_ERROR_NOT_INITIALIZED;
}
nsresult rv = mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows);
nsresult rv =
mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
@ -549,8 +550,8 @@ nsresult nsFrameMessageManager::DispatchAsyncMessageInternal(
void nsFrameMessageManager::DispatchAsyncMessage(
JSContext* aCx, const nsAString& aMessageName, JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects, JS::Handle<JS::Value> aTransfers,
ErrorResult& aError) {
JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal,
JS::Handle<JS::Value> aTransfers, ErrorResult& aError) {
StructuredCloneData data;
if (!aObj.isUndefined() &&
!GetParamsForMessage(aCx, aObj, aTransfers, data)) {
@ -569,7 +570,8 @@ void nsFrameMessageManager::DispatchAsyncMessage(
return;
}
aError = DispatchAsyncMessageInternal(aCx, aMessageName, data, aObjects);
aError = DispatchAsyncMessageInternal(aCx, aMessageName, data, aObjects,
aPrincipal);
}
class MMListenerRemover {
@ -594,8 +596,8 @@ class MMListenerRemover {
void nsFrameMessageManager::ReceiveMessage(
nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader, bool aTargetClosed,
const nsAString& aMessage, bool aIsSync, StructuredCloneData* aCloneData,
mozilla::jsipc::CpowHolder* aCpows, nsTArray<StructuredCloneData>* aRetVal,
ErrorResult& aError) {
mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal, ErrorResult& aError) {
MOZ_ASSERT(aTarget);
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
@ -694,6 +696,7 @@ void nsFrameMessageManager::ReceiveMessage(
}
argument.mName = aMessage;
argument.mPrincipal = aPrincipal;
argument.mSync = aIsSync;
argument.mTarget = aTarget;
if (aTargetFrameLoader) {
@ -801,7 +804,7 @@ void nsFrameMessageManager::ReceiveMessage(
if (kungFuDeathGrip) {
kungFuDeathGrip->ReceiveMessage(aTarget, aTargetFrameLoader, aTargetClosed,
aMessage, aIsSync, aCloneData, aCpows,
aRetVal, aError);
aPrincipal, aRetVal, aError);
}
}
@ -1380,12 +1383,13 @@ class SameParentProcessMessageManagerCallback : public MessageManagerCallback {
nsresult DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) override {
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal) override {
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
RefPtr<nsAsyncMessageToSameProcessChild> ev =
new nsAsyncMessageToSameProcessChild(rcx, aCpows);
nsresult rv = ev->Init(aMessage, aData);
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
@ -1412,6 +1416,7 @@ class ChildProcessMessageManagerCallback : public MessageManagerCallback {
bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
bool aIsSync) override {
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
@ -1428,15 +1433,16 @@ class ChildProcessMessageManagerCallback : public MessageManagerCallback {
}
if (aIsSync) {
return cc->SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
aRetVal);
IPC::Principal(aPrincipal), aRetVal);
}
return cc->SendRpcMessage(PromiseFlatString(aMessage), data, cpows,
aRetVal);
IPC::Principal(aPrincipal), aRetVal);
}
nsresult DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) override {
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal) override {
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
if (!cc) {
return NS_OK;
@ -1449,7 +1455,8 @@ class ChildProcessMessageManagerCallback : public MessageManagerCallback {
if (aCpows && !cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return NS_ERROR_UNEXPECTED;
}
if (!cc->SendAsyncMessage(PromiseFlatString(aMessage), cpows, data)) {
if (!cc->SendAsyncMessage(PromiseFlatString(aMessage), cpows,
IPC::Principal(aPrincipal), data)) {
return NS_ERROR_UNEXPECTED;
}
@ -1487,6 +1494,7 @@ class SameChildProcessMessageManagerCallback : public MessageManagerCallback {
bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
bool aIsSync) override {
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
@ -1496,20 +1504,21 @@ class SameChildProcessMessageManagerCallback : public MessageManagerCallback {
SameProcessCpowHolder cpows(JS::RootingContext::get(aCx), aCpows);
RefPtr<nsFrameMessageManager> ppm =
nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(ppm, nullptr, aMessage, true, &aData, &cpows, aRetVal,
IgnoreErrors());
ppm->ReceiveMessage(ppm, nullptr, aMessage, true, &aData, &cpows,
aPrincipal, aRetVal, IgnoreErrors());
}
return true;
}
nsresult DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) override {
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal) override {
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
RefPtr<nsAsyncMessageToSameProcessParent> ev =
new nsAsyncMessageToSameProcessParent(rcx, aCpows);
nsresult rv = ev->Init(aMessage, aData);
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
@ -1603,7 +1612,8 @@ nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(
}
nsresult nsSameProcessAsyncMessageBase::Init(const nsAString& aMessage,
StructuredCloneData& aData) {
StructuredCloneData& aData,
nsIPrincipal* aPrincipal) {
if (!mData.Copy(aData)) {
Telemetry::Accumulate(Telemetry::IPC_SAME_PROCESS_MESSAGE_COPY_OOM_KB,
aData.DataLength());
@ -1611,6 +1621,7 @@ nsresult nsSameProcessAsyncMessageBase::Init(const nsAString& aMessage,
}
mMessage = aMessage;
mPrincipal = aPrincipal;
#ifdef DEBUG
mCalledInit = true;
#endif
@ -1628,6 +1639,6 @@ void nsSameProcessAsyncMessageBase::ReceiveMessage(
RefPtr<nsFrameMessageManager> mm = aManager;
mm->ReceiveMessage(aTarget, aTargetFrameLoader, mMessage, false, &mData,
&cpows, nullptr, IgnoreErrors());
&cpows, mPrincipal, nullptr, IgnoreErrors());
}
}

View File

@ -87,6 +87,7 @@ class MessageManagerCallback {
virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
bool aIsSync) {
return true;
@ -94,7 +95,8 @@ class MessageManagerCallback {
virtual nsresult DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows) {
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal) {
return NS_OK;
}
@ -191,9 +193,11 @@ class nsFrameMessageManager : public nsIMessageSender {
void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
nsIPrincipal* aPrincipal,
JS::Handle<JS::Value> aTransfers,
mozilla::ErrorResult& aError) {
DispatchAsyncMessage(aCx, aMessageName, aObj, aObjects, aTransfers, aError);
DispatchAsyncMessage(aCx, aMessageName, aObj, aObjects, aPrincipal,
aTransfers, aError);
}
already_AddRefed<mozilla::dom::ProcessMessageManager>
GetProcessMessageManager(mozilla::ErrorResult& aError);
@ -203,17 +207,19 @@ class nsFrameMessageManager : public nsIMessageSender {
// SyncMessageSender
void SendSyncMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal,
nsTArray<JS::Value>& aResult,
mozilla::ErrorResult& aError) {
SendMessage(aCx, aMessageName, aObj, aObjects, true, aResult, aError);
SendMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, true, aResult,
aError);
}
void SendRpcMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal,
nsTArray<JS::Value>& aResult,
mozilla::ErrorResult& aError) {
SendMessage(aCx, aMessageName, aObj, aObjects, false, aResult, aError);
SendMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, false, aResult,
aError);
}
// GlobalProcessScriptLoader
@ -232,10 +238,11 @@ class nsFrameMessageManager : public nsIMessageSender {
const nsAString& aMessage, bool aIsSync,
StructuredCloneData* aCloneData,
mozilla::jsipc::CpowHolder* aCpows,
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
mozilla::ErrorResult& aError) {
ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync,
aCloneData, aCpows, aRetVal, aError);
aCloneData, aCpows, aPrincipal, aRetVal, aError);
}
void Disconnect(bool aRemoveFromParent = true);
@ -248,7 +255,8 @@ class nsFrameMessageManager : public nsIMessageSender {
nsresult DispatchAsyncMessageInternal(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows);
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal);
bool IsGlobal() { return mGlobal; }
bool IsBroadcaster() { return mIsBroadcaster; }
bool IsChrome() { return mChrome; }
@ -287,18 +295,20 @@ class nsFrameMessageManager : public nsIMessageSender {
void DispatchAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj,
JS::Handle<JSObject*> aObjects,
nsIPrincipal* aPrincipal,
JS::Handle<JS::Value> aTransfers,
mozilla::ErrorResult& aError);
void SendMessage(JSContext* aCx, const nsAString& aMessageName,
JS::Handle<JS::Value> aObj, JS::Handle<JSObject*> aObjects,
bool aIsSync, nsTArray<JS::Value>& aResult,
mozilla::ErrorResult& aError);
nsIPrincipal* aPrincipal, bool aIsSync,
nsTArray<JS::Value>& aResult, mozilla::ErrorResult& aError);
void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
bool aTargetClosed, const nsAString& aMessage,
bool aIsSync, StructuredCloneData* aCloneData,
mozilla::jsipc::CpowHolder* aCpows,
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
mozilla::ErrorResult& aError);
@ -366,7 +376,8 @@ class nsSameProcessAsyncMessageBase {
nsSameProcessAsyncMessageBase(JS::RootingContext* aRootingCx,
JS::Handle<JSObject*> aCpows);
nsresult Init(const nsAString& aMessage, StructuredCloneData& aData);
nsresult Init(const nsAString& aMessage, StructuredCloneData& aData,
nsIPrincipal* aPrincipal);
void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
nsFrameMessageManager* aManager);
@ -377,6 +388,7 @@ class nsSameProcessAsyncMessageBase {
nsString mMessage;
StructuredCloneData mData;
JS::PersistentRooted<JSObject*> mCpows;
nsCOMPtr<nsIPrincipal> mPrincipal;
#ifdef DEBUG
bool mCalledInit;
#endif
@ -419,6 +431,7 @@ class nsMessageManagerScriptExecutor {
bool Init();
void Trace(const TraceCallbacks& aCallbacks, void* aClosure);
void Unlink();
nsCOMPtr<nsIPrincipal> mPrincipal;
AutoTArray<JS::Heap<JSObject*>, 2> mAnonymousGlobalScopes;
// Returns true if this is a process message manager. There should only be a

View File

@ -3162,12 +3162,12 @@ nsPIDOMWindowOuter* nsGlobalWindowOuter::GetInProcessScriptableParent() {
return nullptr;
}
if (BrowsingContext* parentBC = GetBrowsingContext()->GetParent()) {
if (nsCOMPtr<nsPIDOMWindowOuter> parent = parentBC->GetDOMWindow()) {
return parent;
}
if (mDocShell->GetIsMozBrowser()) {
return this;
}
return this;
nsCOMPtr<nsPIDOMWindowOuter> parent = GetInProcessParent();
return parent;
}
/**
@ -3340,6 +3340,13 @@ already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetContentInternal(
return content.forget();
}
// If we're contained in <iframe mozbrowser>, then GetContent is the same as
// window.top.
if (mDocShell && mDocShell->GetIsInMozBrowser()) {
nsCOMPtr<nsPIDOMWindowOuter> domWindow(GetInProcessScriptableTop());
return domWindow.forget();
}
nsCOMPtr<nsIDocShellTreeItem> primaryContent;
if (aCallerType != CallerType::System) {
if (mDoc) {
@ -5374,6 +5381,19 @@ nsresult nsGlobalWindowOuter::MoveBy(int32_t aXDif, int32_t aYDif) {
void nsGlobalWindowOuter::ResizeToOuter(int32_t aWidth, int32_t aHeight,
CallerType aCallerType,
ErrorResult& aError) {
/*
* If caller is a browser-element then dispatch a resize event to
* the embedder.
*/
if (mDocShell && mDocShell->GetIsMozBrowser()) {
CSSIntSize size(aWidth, aHeight);
if (!DispatchResizeEvent(size)) {
// The embedder chose to prevent the default action for this
// event, so let's not resize this window after all...
return;
}
}
/*
* If caller is not chrome and the user has not explicitly exempted the site,
* prevent window.resizeTo() by exiting early
@ -5402,6 +5422,26 @@ void nsGlobalWindowOuter::ResizeToOuter(int32_t aWidth, int32_t aHeight,
void nsGlobalWindowOuter::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
CallerType aCallerType,
ErrorResult& aError) {
/*
* If caller is a browser-element then dispatch a resize event to
* parent.
*/
if (mDocShell && mDocShell->GetIsMozBrowser()) {
CSSIntSize size;
if (NS_FAILED(GetInnerSize(size))) {
return;
}
size.width += aWidthDif;
size.height += aHeightDif;
if (!DispatchResizeEvent(size)) {
// The embedder chose to prevent the default action for this
// event, so let's not resize this window after all...
return;
}
}
/*
* If caller is not chrome and the user has not explicitly exempted the site,
* prevent window.resizeBy() by exiting early
@ -6069,7 +6109,8 @@ bool nsGlobalWindowOuter::CanClose() {
}
void nsGlobalWindowOuter::CloseOuter(bool aTrustedCaller) {
if (!mDocShell || IsInModalState() || IsFrame()) {
if (!mDocShell || IsInModalState() ||
(IsFrame() && !mDocShell->GetIsMozBrowser())) {
// window.close() is called on a frame in a frameset, on a window
// that's already closed, or on a window for which there's
// currently a modal dialog open. Ignore such calls.

View File

@ -13,6 +13,7 @@ support-files =
file_script.js
referrer_helper.js
referrer_testserver.sjs
mozbrowser_api_utils.js
!/image/test/mochitest/shaver.png
[test_anonymousContent_xul_window.xhtml]
@ -25,7 +26,9 @@ support-files =
[test_anchor_target_blank_referrer.html]
[test_domrequesthelper.xhtml]
[test_fragment_sanitization.xhtml]
[test_messagemanager_principal.html]
[test_messagemanager_send_principal.html]
[test_mozbrowser_apis_allowed.html]
[test_navigator_resolve_identity_xrays.xhtml]
support-files = file_navigator_resolve_identity_xrays.xhtml
[test_sandboxed_blob_uri.html]

View File

@ -99,7 +99,8 @@ Test swapFrameLoaders with different frame types and remoteness
add_task(async function() {
await SpecialPowers.pushPrefEnv(
{ "set": [["network.disable.ipc.security", true]] });
{ "set": [["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true]] });
});
add_task(async function() {
@ -220,6 +221,35 @@ Test swapFrameLoaders with different frame types and remoteness
is(pongB, "A", "Frame B message manager acquired after swap gets reply A after swap");
}
// Verify browser API frame scripts destroyed if swapped out of browser frame
if (frameA.hasAttribute("mozbrowser") != frameB.hasAttribute("mozbrowser")) {
let mmA = frameA.frameLoader.messageManager;
let mmB = frameB.frameLoader.messageManager;
let inflightA = once(mmA, "check-browser-api");
let inflightB = once(mmB, "check-browser-api");
info("Check browser API for frame A");
mmA.sendAsyncMessage("check-browser-api");
let [ { data: apiA } ] = await inflightA;
if (frameA.hasAttribute("mozbrowser")) {
ok(apiA.exists && apiA.running, "Frame A browser API exists and is running");
} else {
ok(apiA.exists && !apiA.running, "Frame A browser API did exist but is now destroyed");
}
info("Check browser API for frame B");
mmB.sendAsyncMessage("check-browser-api");
let [ { data: apiB } ] = await inflightB;
if (frameB.hasAttribute("mozbrowser")) {
ok(apiB.exists && apiB.running, "Frame B browser API exists and is running");
} else {
ok(apiB.exists && !apiB.running, "Frame B browser API did exist but is now destroyed");
}
} else {
info("Frames have matching mozbrowser state, skipping browser API destruction check");
}
frameA.remove();
frameB.remove();
}

View File

@ -2,6 +2,13 @@
<html>
<head>
<script>
// Uncomment this definition of SimpleTest (and comment out the one below) to
// debug in mozBrowser mode.
/*
var SimpleTest = { ok: function(c, m) { dump(m + ": " + c + "\n"); },
info: function(m) { dump(m + "\n"); },
finish: function() { dump("Test done\n");} };
*/
var SimpleTest = parent.SimpleTest;
var ok = SimpleTest.ok;

View File

@ -218,6 +218,7 @@ support-files =
file_bug1250148.sjs
file_bug1268962.sjs
iframe_meta_refresh.sjs
mozbrowser_api_utils.js
!/dom/security/test/cors/file_CrossSiteXHR_server.sjs
!/image/test/mochitest/blue.png
script_bug1238440.js
@ -697,6 +698,7 @@ skip-if = !e10s # Track Bug 1281415
[test_link_stylesheet.html]
[test_location_href_unknown_protocol.html]
support-files = file_location_href_unknown_protocol.html
[test_messagemanager_targetchain.html]
[test_meta_refresh_referrer.html]
[test_meta_viewport0.html]
[test_meta_viewport1.html]
@ -745,6 +747,7 @@ support-files = file_location_href_unknown_protocol.html
[test_meta_viewport_tiny_display_size.html]
[test_meta_viewport_initial_scale_with_trailing_characters.html]
[test_meta_viewport_width_with_trailing_characters.html]
[test_mozbrowser_apis_blocked.html]
[test_mozMatchesSelector.html]
[test_mutationobserver_anonymous.html]
[test_mutationobservers.html]

View File

@ -0,0 +1,53 @@
const FRAME_URL = "http://example.org/";
const METHODS = {
sendMouseEvent: {},
goBack: {},
goForward: {},
reload: {},
stop: {},
getCanGoBack: {},
getCanGoForward: {},
};
const ATTRIBUTES = [];
function once(target, eventName, useCapture = false) {
info(
"Waiting for event: '" + JSON.stringify(eventName) + "' on " + target + "."
);
return new Promise(resolve => {
for (let [add, remove] of [
["addEventListener", "removeEventListener"],
["addMessageListener", "removeMessageListener"],
]) {
if (add in target && remove in target) {
eventName.forEach(evName => {
target[add](
evName,
function onEvent(...aArgs) {
info("Got event: '" + evName + "' on " + target + ".");
target[remove](evName, onEvent, useCapture);
resolve(aArgs);
},
useCapture
);
});
break;
}
}
});
}
async function loadFrame(attributes = {}) {
let iframe = document.createElement("iframe");
iframe.setAttribute("src", FRAME_URL);
for (let key in attributes) {
iframe.setAttribute(key, attributes[key]);
}
let loaded = once(iframe, ["load", "mozbrowserloadend"]);
document.body.appendChild(iframe);
await loaded;
return iframe;
}

View File

@ -11,11 +11,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1022229
<script type="application/javascript">
/** Test for postMessage between sandboxed iframe and non-sandboxed window.
This test is particularly interesting on b2g where we're in a mozBrowser.
We set the test up with an extra iframe so that we can easily run it in
an artificial mozbrowser for desktop builds.
**/
SimpleTest.waitForExplicitFinish();
function go() {
var ifr = document.createElement('iframe');
/* Uncomment this chunk to run in a mozBrowser. Make sure to uncomment the
chunk in iframe_main as well. */
/*
SpecialPowers.Services.prefs.setBoolPref("dom.mozBrowserFramesEnabled", true);
SpecialPowers.Services.prefs.setBoolPref("network.disable.ipc.security", true);
SpecialPowers.Services.prefs.setBoolPref("dom.ipc.browser_frames.oop_by_default", false);
SpecialPowers.addPermission("browser", true, document);
SpecialPowers.wrap(ifr).mozbrowser = true;
*/
ifr.setAttribute('src', 'iframe_main_bug1022229.html');
document.body.appendChild(ifr);
}

View File

@ -0,0 +1,88 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Principal in MessageManager</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
</head>
<body>
<script type="application/javascript">
"use strict";
var permManager = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
SimpleTest.waitForExplicitFinish();
const childFrameURL =
"data:text/html,<!DOCTYPE HTML><html><body></body></html>";
function childFrameScript() {
"use strict";
addMessageListener("test:ipcMessage", function(message) {
sendAsyncMessage(message.name, "principal: " + (message.principal ? "OK" : "KO"));
sendAsyncMessage(message.name, "principal.origin: " +
("origin" in message.principal ? "OK" : "KO"));
sendAsyncMessage(message.name, "principal.isInIsolatedMozBrowserElement: " +
("isInIsolatedMozBrowserElement" in message.principal ? "OK" : "KO"));
sendAsyncMessage(message.name, "DONE");
});
}
function runTests() {
ok("Browser prefs set.");
let iframe = document.createElement("iframe");
SpecialPowers.wrap(iframe).mozbrowser = true;
iframe.id = "iframe";
iframe.src = childFrameURL;
iframe.addEventListener("mozbrowserloadend", function() {
ok(true, "Got iframe load event.");
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.addMessageListener("test:ipcMessage", function(message) {
// We need to wrap to access message.json, and unwrap to do the
// identity check.
var msg = SpecialPowers.unwrap(SpecialPowers.wrap(message).json);
if (/OK$/.exec(msg)) {
ok(true, msg);
} else if(/KO$/.exec(msg)) {
ok(true, false);
} else if (/DONE/.exec(msg)) {
permManager.removeFromPrincipal(window.document.nodePrincipal, "browser",
Ci.nsIPermissionManager.ALLOW_ACTION);
SimpleTest.finish();
}
});
mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
false);
mm.sendAsyncMessage("test:ipcMessage", 42, null, window.document.nodePrincipal);
});
document.body.appendChild(iframe);
}
addEventListener("load", function() {
info("Got load event.");
permManager.addFromPrincipal(window.document.nodePrincipal, "browser",
Ci.nsIPermissionManager.ALLOW_ACTION);
SpecialPowers.pushPrefEnv({
"set": [
["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true],
["browser.pagethumbnails.capturing_disabled", true]
]
}, runTests);
});
</script>
</body>
</html>

View File

@ -28,6 +28,9 @@
sendAsyncMessage("test:result", "principal.origin: " +
("origin" in message.data ? "OK" : "KO"));
sendAsyncMessage("test:result", "principal.isInIsolatedMozBrowserElement: " +
("isInIsolatedMozBrowserElement" in message.data ? "OK" : "KO"));
});
addMessageListener("test:system", function(message) {
@ -55,19 +58,18 @@
function runTests() {
ok("Browser prefs set.");
let iframe = document.createXULElement("browser");
iframe.setAttribute("type", "content");
iframe.setAttribute("forcemessagemanager", "true");
let iframe = document.createElement("iframe");
SpecialPowers.wrap(iframe).mozbrowser = true;
iframe.id = "iframe";
iframe.src = childFrameURL;
let sb = new Cu.Sandbox(['http://foo.example.com', 'http://bar.example.com']);
let ep = Cu.getObjectPrincipal(sb);
iframe.addEventListener("load", function() {
iframe.addEventListener("mozbrowserloadend", function() {
ok(true, "Got iframe load event.");
let mm = iframe.messageManager;
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.addMessageListener("test:result", function(message) {
// We need to wrap to access message.json, and unwrap to do the
// identity check.
@ -77,6 +79,8 @@
} else if(/KO$/.exec(msg)) {
ok(true, false);
} else if (/DONE/.exec(msg)) {
permManager.removeFromPrincipal(window.document.nodePrincipal, "browser",
Ci.nsIPermissionManager.ALLOW_ACTION);
SimpleTest.finish();
}
});
@ -102,8 +106,13 @@
addEventListener("load", function() {
info("Got load event.");
permManager.addFromPrincipal(window.document.nodePrincipal, "browser",
Ci.nsIPermissionManager.ALLOW_ACTION);
SpecialPowers.pushPrefEnv({
"set": [
["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true],
["browser.pagethumbnails.capturing_disabled", true]
]
}, runTests);

View File

@ -0,0 +1,121 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for EventTarget chain of MessageManagers</title>
<script src="/tests/SimpleTest/SimpleTest.js">
</script>
<script src="/tests/SimpleTest/EventUtils.js">
</script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript">
"use strict";
SimpleTest.waitForExplicitFinish();
const browserFrameURL = "file_empty.html";
const contentFrameURL =
"data:text/html,<!DOCTYPE HTML><html><body><button id=\"target\">target</button></body></html>";
function frameScript() {
"use strict";
addEventListener("test-event", function (e) {
sendSyncMessage("test-event");
}, true);
}
function runTests() {
// messageIndex is incremented for each message/event received
let messageIndex = 0;
let iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", true);
iframe.setAttribute("src", browserFrameURL);
iframe.addEventListener("mozbrowserloadend", function () {
info("First iframe loaded");
// First message manager
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.addMessageListener("test-event", function onEvent(message) {
is(messageIndex, 0,
"first mm should be the first one to receive the test event");
messageIndex++;
});
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false);
// Document in the middle
let doc1 = SpecialPowers.wrap(iframe).contentDocument;
doc1.addEventListener("test-event", function (e) {
ok(false, "content document shouldn't receive test event from child");
}, true);
let iframe2 = doc1.createElement("iframe");
iframe2.setAttribute("mozbrowser", true);
iframe2.setAttribute("src", browserFrameURL);
iframe2.addEventListener("mozbrowserloadend", function () {
info("Second iframe loaded");
// Second message manager
let mm2 = SpecialPowers.getBrowserFrameMessageManager(iframe2);
mm2.addMessageListener("test-event", function onEvent(message) {
is(messageIndex, 1,
"second mm should be the second one to receive the test event");
messageIndex++;
});
mm2.loadFrameScript("data:,(" + frameScript.toString() +")();", false);
// Third is the regular iframe
let doc2 = SpecialPowers.wrap(iframe2).contentDocument;
let iframe3 = doc2.createElement("iframe");
iframe3.setAttribute("src", contentFrameURL);
iframe3.addEventListener("load", function (e) {
info("Third iframe loaded");
let doc3 = SpecialPowers.wrap(iframe3).contentDocument;
let target = doc3.getElementById("target");
target.addEventListener("test-event", function onEvent() {
is(messageIndex, 2,
"target should be the last one to receive the test event");
messageIndex++;
SimpleTest.finish();
});
// Fire test event after load
SimpleTest.executeSoon(function () {
var event = new Event("test-event");
SpecialPowers.dispatchEvent(iframe3.contentWindow, target, event);
});
});
doc2.body.appendChild(iframe3);
});
doc1.body.appendChild(iframe2);
});
document.addEventListener("test-event", function (e) {
ok(false, "top document shouldn't receive test event from child");
}, true);
document.body.appendChild(iframe);
}
addEventListener("load", function() {
var principal = SpecialPowers.wrap(document).nodePrincipal;
SpecialPowers.pushPermissions([
{ type: "browser", allow: 1, context: { url: principal.URI.spec,
originAttributes: {}}},
{ type: "browser", allow: 1, context: { url: principal.URI.spec,
originAttributes: {
inIsolatedMozBrowser: true }}}
], () => {
SpecialPowers.pushPrefEnv({
set: [
["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true],
["dom.ipc.browser_frames.oop_by_default", false],
]
}, runTests);
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Verify mozbrowser APIs are allowed with browser permission</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mozbrowser_api_utils.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<script type="application/javascript">
add_task(async function() {
await SpecialPowers.pushPrefEnv(
{ "set": [["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true]] });
});
add_task(async function() {
// Create <iframe mozbrowser>
let frame = await loadFrame({
mozbrowser: "true",
// FIXME: Bug 1270790
remote: true
});
// Verify that mozbrowser APIs are accessible
for (let method in METHODS) {
let { alwaysFails } = METHODS[method];
if (alwaysFails) {
ok(!(method in frame), `frame does not have method ${method}, ` +
`needs more permissions`);
} else {
ok(method in frame, `frame has method ${method}`);
}
}
for (let attribute of ATTRIBUTES) {
ok(attribute in frame, `frame has attribute ${attribute}`);
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Verify mozbrowser APIs are blocked without browser permission</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mozbrowser_api_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script type="application/javascript">
add_task(async function() {
await SpecialPowers.pushPrefEnv(
{ "set": [["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true]] });
});
add_task(async function() {
// Create <iframe mozbrowser>
let frame = await loadFrame({
mozbrowser: "true"
});
// Verify that mozbrowser APIs are not accessible
for (let method in METHODS) {
ok(!(method in frame), `frame does not have method ${method}`);
}
for (let attribute of ATTRIBUTES) {
ok(!(attribute in frame), `frame does not have attribute ${attribute}`);
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,5 @@
"use strict";
module.exports = {
extends: ["plugin:mozilla/chrome-test", "plugin:mozilla/mochitest-test"],
};

View File

@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This is an approximate implementation of ES7's async-await pattern.
* see: https://github.com/tc39/ecmascript-asyncawait
*
* It allows for simple creation of async function and "tasks".
*
* For example:
*
* var myThinger = {
* doAsynThing: async(function*(url){
* var result = yield fetch(url);
* return process(result);
* });
* }
*
* And Task-like things can be created as follows:
*
* var myTask = async(function*{
* var result = yield fetch(url);
* return result;
* });
* //returns a promise
*
* myTask().then(doSomethingElse);
*
*/
(function(exports) {
"use strict";
function async(func, self) {
return function asyncFunction() {
const functionArgs = Array.from(arguments);
return new Promise(function(resolve, reject) {
var gen;
if (typeof func !== "function") {
reject(new TypeError("Expected a Function."));
}
// not a generator, wrap it.
if (func.constructor.name !== "GeneratorFunction") {
gen = (function*() {
return func.apply(self, functionArgs);
})();
} else {
gen = func.apply(self, functionArgs);
}
try {
step(gen.next(undefined));
} catch (err) {
reject(err);
}
function step({ value, done }) {
if (done) {
return resolve(value);
}
if (value instanceof Promise) {
return value
.then(
result => step(gen.next(result)),
error => {
step(gen.throw(error));
}
)
.catch(err => reject(err));
}
return step(gen.next(value));
}
});
};
}
exports.async = async;
})(this || self);

Binary file not shown.

View File

@ -0,0 +1,300 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Helpers for managing the browser frame preferences.
"use strict";
function _getPath() {
if (window.location.protocol == "chrome:") {
return "/chrome/dom/browser-element/mochitest";
}
return window.location.pathname
.substring(0, window.location.pathname.lastIndexOf("/"))
.replace("/priority", "");
}
const browserElementTestHelpers = {
_getBoolPref(pref) {
try {
return SpecialPowers.getBoolPref(pref);
} catch (e) {
return undefined;
}
},
_setPref(pref, value) {
this.lockTestReady();
if (value !== undefined && value !== null) {
SpecialPowers.pushPrefEnv(
{ set: [[pref, value]] },
this.unlockTestReady.bind(this)
);
} else {
SpecialPowers.pushPrefEnv(
{ clear: [[pref]] },
this.unlockTestReady.bind(this)
);
}
},
_setPrefs() {
this.lockTestReady();
SpecialPowers.pushPrefEnv(
{ set: Array.from(arguments) },
this.unlockTestReady.bind(this)
);
},
_testReadyLockCount: 0,
_firedTestReady: false,
lockTestReady() {
this._testReadyLockCount++;
},
unlockTestReady() {
this._testReadyLockCount--;
if (this._testReadyLockCount == 0 && !this._firedTestReady) {
this._firedTestReady = true;
dispatchEvent(new Event("testready"));
}
},
enableProcessPriorityManager() {
this._setPrefs(
["dom.ipc.processPriorityManager.testMode", true],
["dom.ipc.processPriorityManager.enabled", true]
);
},
setClipboardPlainTextOnlyPref(value) {
this._setPref("clipboard.plainTextOnly", value);
},
setEnabledPref(value) {
this._setPrefs(
["dom.mozBrowserFramesEnabled", value],
["network.disable.ipc.security", value]
);
},
setupAccessibleCaretPref() {
this._setPref("layout.accessiblecaret.enabled", true);
// Disable hide carets for mouse input for select-all tests so that we can
// get mozbrowsercaretstatechanged events.
this._setPref("layout.accessiblecaret.hide_carets_for_mouse_input", false);
},
getOOPByDefaultPref() {
return this._getBoolPref("dom.ipc.browser_frames.oop_by_default");
},
addPermission() {
this.lockTestReady();
SpecialPowers.pushPermissions(
[{ type: "browser", allow: 1, context: document }],
this.unlockTestReady.bind(this)
);
},
allowTopLevelDataURINavigation() {
this._setPref(
"security.data_uri.block_toplevel_data_uri_navigations",
false
);
},
_observers: [],
// This function is a wrapper which lets you register an observer to one of
// the process priority manager's test-only topics. observerFn should be a
// function which takes (subject, topic, data).
//
// We'll clean up any observers you add at the end of the test.
addProcessPriorityObserver(processPriorityTopic, observerFn) {
var topic = "process-priority-manager:TEST-ONLY:" + processPriorityTopic;
// SpecialPowers appears to require that the observer be an object, not a
// function.
var observer = {
observe: observerFn,
};
SpecialPowers.addObserver(observer, topic);
this._observers.push([observer, topic]);
},
cleanUp() {
for (var i = 0; i < this._observers.length; i++) {
SpecialPowers.removeObserver(
this._observers[i][0],
this._observers[i][1]
);
}
},
// Some basically-empty pages from different domains you can load.
emptyPage1: "http://example.com" + _getPath() + "/file_empty.html",
fileEmptyPage1: "file_empty.html",
emptyPage2: "http://example.org" + _getPath() + "/file_empty.html",
emptyPage3: "http://test1.example.org" + _getPath() + "/file_empty.html",
focusPage: "http://example.org" + _getPath() + "/file_focus.html",
};
// Returns a promise which is resolved when a subprocess is created. The
// argument to resolve() is the childID of the subprocess.
function expectProcessCreated(/* optional */ initialPriority) {
return new Promise(function(resolve, reject) {
var observed = false;
browserElementTestHelpers.addProcessPriorityObserver(
"process-created",
function(subject, topic, data) {
// Don't run this observer twice, so we don't ok(true) twice. (It's fine
// to resolve a promise twice; the second resolve() call does nothing.)
if (observed) {
return;
}
observed = true;
var childID = parseInt(data);
ok(true, "Got new process, id=" + childID);
if (initialPriority) {
expectPriorityChange(childID, initialPriority).then(function() {
resolve(childID);
});
} else {
resolve(childID);
}
}
);
});
}
// Just like expectProcessCreated(), except we'll call ok(false) if a second
// process is created.
function expectOnlyOneProcessCreated(/* optional */ initialPriority) {
var p = expectProcessCreated(initialPriority);
p.then(function() {
expectProcessCreated().then(function(childID) {
ok(false, "Got unexpected process creation, childID=" + childID);
});
});
return p;
}
// Returns a promise which is resolved or rejected the next time the process
// childID changes its priority. We resolve if the priority matches
// expectedPriority, and we reject otherwise.
function expectPriorityChange(childID, expectedPriority) {
return new Promise(function(resolve, reject) {
var observed = false;
browserElementTestHelpers.addProcessPriorityObserver(
"process-priority-set",
function(subject, topic, data) {
if (observed) {
return;
}
var [id, priority] = data.split(":");
if (id != childID) {
return;
}
// Make sure we run the is() calls in this observer only once, otherwise
// we'll expect /every/ priority change to match expectedPriority.
observed = true;
is(
priority,
expectedPriority,
"Expected priority of childID " +
childID +
" to change to " +
expectedPriority
);
if (priority == expectedPriority) {
resolve();
} else {
reject();
}
}
);
});
}
// Returns a promise which is resolved the first time the given iframe fires
// the mozbrowser##eventName event.
function expectMozbrowserEvent(iframe, eventName) {
return new Promise(function(resolve, reject) {
iframe.addEventListener("mozbrowser" + eventName, function handler(e) {
iframe.removeEventListener("mozbrowser" + eventName, handler);
resolve(e);
});
});
}
// Set some prefs:
//
// * browser.pagethumbnails.capturing_disabled: true
//
// Disable tab view; it seriously messes us up.
//
// * dom.ipc.browser_frames.oop_by_default
//
// Enable or disable OOP-by-default depending on the test's filename. You
// can still force OOP on or off with <iframe mozbrowser remote=true/false>,
// at least until bug 756376 lands.
//
// * dom.ipc.tabs.disabled: false
//
// Allow us to create OOP frames. Even if they're not the default, some
// "in-process" tests create OOP frames.
//
// * network.disable.ipc.security: true
//
// Disable the networking security checks; our test harness just tests
// browser elements without sticking them in apps, and the security checks
// dislike that.
//
// Unfortunately setting network.disable.ipc.security to false before the
// child process(es) created by this test have shut down can cause us to
// assert and kill the child process. That doesn't cause the tests to fail,
// but it's still scary looking. So we just set the pref to true and never
// pop that value. We'll rely on the tests which test IPC security to set
// it to false.
//
// * security.mixed_content.block_active_content: false
//
// Disable mixed active content blocking, so that tests can confirm that mixed
// content results in a broken security state.
(function() {
var oop = !location.pathname.includes("_inproc_");
browserElementTestHelpers.lockTestReady();
SpecialPowers.setBoolPref("network.disable.ipc.security", true);
SpecialPowers.pushPrefEnv(
{
set: [
["browser.pagethumbnails.capturing_disabled", true],
["dom.ipc.browser_frames.oop_by_default", oop],
["dom.ipc.tabs.disabled", false],
["security.mixed_content.block_active_content", false],
],
},
browserElementTestHelpers.unlockTestReady.bind(browserElementTestHelpers)
);
})();
addEventListener("unload", function() {
browserElementTestHelpers.cleanUp();
});
// Wait for the load event before unlocking the test-ready event.
browserElementTestHelpers.lockTestReady();
addEventListener("load", function() {
SimpleTest.executeSoon(
browserElementTestHelpers.unlockTestReady.bind(browserElementTestHelpers)
);
});

View File

@ -0,0 +1,326 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that alert works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
var numPendingChildTests = 0;
var iframe;
var mm;
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.addMessageListener("test-success", function(msg) {
numPendingChildTests--;
ok(true, SpecialPowers.wrap(msg).json);
});
mm.addMessageListener("test-fail", function(msg) {
numPendingChildTests--;
ok(false, SpecialPowers.wrap(msg).json);
});
// Wait for the initial load to finish, then navigate the page, then wait
// for that load to finish, then start test1.
iframe.addEventListener(
"mozbrowserloadend",
function() {
iframe.src = browserElementTestHelpers.emptyPage1;
iframe.addEventListener(
"mozbrowserloadend",
function() {
SimpleTest.executeSoon(test1);
},
{ once: true }
);
},
{ once: true }
);
}
function test1() {
iframe.addEventListener("mozbrowsershowmodalprompt", test2);
// Do window.alert within the iframe, then modify the global |testState|
// after the alert.
var script =
'data:,\
this.testState = 0; \
content.alert("Hello, world!"); \
this.testState = 1; \
';
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
// Triggers a mozbrowsershowmodalprompt event, which sends us down to test2.
}
// test2 is a mozbrowsershowmodalprompt listener.
function test2(e) {
iframe.removeEventListener("mozbrowsershowmodalprompt", test2);
is(e.detail.message, "Hello, world!");
e.preventDefault(); // cause the alert to block.
SimpleTest.executeSoon(function() {
test2a(e);
});
}
function test2a(e) {
// The iframe should be blocked on the alert call at the moment, so testState
// should still be 0.
var script =
'data:,\
if (this.testState === 0) { \
sendAsyncMessage("test-success", "1: Correct testState"); \
} \
else { \
sendAsyncMessage("test-fail", "1: Wrong testState: " + this.testState); \
}';
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
numPendingChildTests++;
waitForPendingTests(function() {
test3(e);
});
}
function test3(e) {
// Now unblock the iframe and check that the script completed.
e.detail.unblock();
var script2 =
'data:,\
if (this.testState === 1) { \
sendAsyncMessage("test-success", "2: Correct testState"); \
} \
else { \
sendAsyncMessage("test-try-again", "2: Wrong testState (for now): " + this.testState); \
}';
// Urgh. e.unblock() didn't necessarily unblock us immediately, so we have
// to spin and wait.
function onTryAgain() {
SimpleTest.executeSoon(function() {
// dump('onTryAgain\n');
mm.loadFrameScript(script2, /* allowDelayedLoad = */ false);
});
}
mm.addMessageListener("test-try-again", onTryAgain);
numPendingChildTests++;
onTryAgain();
waitForPendingTests(function() {
mm.removeMessageListener("test-try-again", onTryAgain);
test4();
});
}
function test4() {
// Navigate the iframe while an alert is pending. This shouldn't screw
// things up.
iframe.addEventListener("mozbrowsershowmodalprompt", test5);
var script = 'data:,content.alert("test4");';
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
}
// test4 is a mozbrowsershowmodalprompt listener.
function test5(e) {
iframe.removeEventListener("mozbrowsershowmodalprompt", test5);
is(e.detail.message, "test4");
e.preventDefault(); // cause the page to block.
SimpleTest.executeSoon(test5a);
}
function test5a() {
iframe.addEventListener("mozbrowserloadend", test5b);
iframe.src = browserElementTestHelpers.emptyPage2;
}
function test5b() {
iframe.removeEventListener("mozbrowserloadend", test5b);
SimpleTest.executeSoon(test6);
}
// Test nested alerts
var promptBlockers = [];
function test6() {
iframe.addEventListener("mozbrowsershowmodalprompt", test6a);
var script =
"data:,\
this.testState = 0; \
content.alert(1); \
this.testState = 3; \
";
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
}
function test6a(e) {
iframe.removeEventListener("mozbrowsershowmodalprompt", test6a);
is(e.detail.message, "1");
e.preventDefault(); // cause the alert to block.
promptBlockers.push(e);
SimpleTest.executeSoon(test6b);
}
function test6b() {
var script =
'data:,\
if (this.testState === 0) { \
sendAsyncMessage("test-success", "1: Correct testState"); \
} \
else { \
sendAsyncMessage("test-fail", "1: Wrong testState: " + this.testState); \
}';
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
numPendingChildTests++;
waitForPendingTests(test6c);
}
function test6c() {
iframe.addEventListener("mozbrowsershowmodalprompt", test6d);
var script =
"data:,\
this.testState = 1; \
content.alert(2); \
this.testState = 2; \
";
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
}
function test6d(e) {
iframe.removeEventListener("mozbrowsershowmodalprompt", test6d);
is(e.detail.message, "2");
e.preventDefault(); // cause the alert to block.
promptBlockers.push(e);
SimpleTest.executeSoon(test6e);
}
function test6e() {
var script =
'data:,\
if (this.testState === 1) { \
sendAsyncMessage("test-success", "2: Correct testState"); \
} \
else { \
sendAsyncMessage("test-fail", "2: Wrong testState: " + this.testState); \
}';
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
numPendingChildTests++;
waitForPendingTests(test6f);
}
function test6f() {
var e = promptBlockers.pop();
// Now unblock the iframe and check that the script completed.
e.detail.unblock();
var script2 =
'data:,\
if (this.testState === 2) { \
sendAsyncMessage("test-success", "3: Correct testState"); \
} \
else { \
sendAsyncMessage("test-try-again", "3: Wrong testState (for now): " + this.testState); \
}';
// Urgh. e.unblock() didn't necessarily unblock us immediately, so we have
// to spin and wait.
function onTryAgain() {
SimpleTest.executeSoon(function() {
// dump('onTryAgain\n');
mm.loadFrameScript(script2, /* allowDelayedLoad = */ false);
});
}
mm.addMessageListener("test-try-again", onTryAgain);
numPendingChildTests++;
onTryAgain();
waitForPendingTests(function() {
mm.removeMessageListener("test-try-again", onTryAgain);
test6g();
});
}
function test6g() {
var e = promptBlockers.pop();
// Now unblock the iframe and check that the script completed.
e.detail.unblock();
var script2 =
'data:,\
if (this.testState === 3) { \
sendAsyncMessage("test-success", "4: Correct testState"); \
} \
else { \
sendAsyncMessage("test-try-again", "4: Wrong testState (for now): " + this.testState); \
}';
// Urgh. e.unblock() didn't necessarily unblock us immediately, so we have
// to spin and wait.
function onTryAgain() {
SimpleTest.executeSoon(function() {
// dump('onTryAgain\n');
mm.loadFrameScript(script2, /* allowDelayedLoad = */ false);
});
}
mm.addMessageListener("test-try-again", onTryAgain);
numPendingChildTests++;
onTryAgain();
waitForPendingTests(function() {
mm.removeMessageListener("test-try-again", onTryAgain);
test6h();
});
}
function test6h() {
SimpleTest.finish();
}
var prevNumPendingTests = null;
function waitForPendingTests(next) {
if (numPendingChildTests !== prevNumPendingTests) {
dump("Waiting for end; " + numPendingChildTests + " pending tests\n");
prevNumPendingTests = numPendingChildTests;
}
if (numPendingChildTests > 0) {
SimpleTest.executeSoon(function() {
waitForPendingTests(next);
});
return;
}
prevNumPendingTests = null;
next();
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,26 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that alert works from inside an <iframe> inside an <iframe mozbrowser>.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
is(e.detail.message, "Hello");
SimpleTest.finish();
});
iframe.src = "file_browserElement_AlertInFrame.html";
document.body.appendChild(iframe);
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,378 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that auth prompt works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
const { NetUtil } = SpecialPowers.Cu.import(
"resource://gre/modules/NetUtil.jsm"
);
function testFail(msg) {
ok(false, JSON.stringify(msg));
}
var iframe;
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
// Wait for the initial load to finish, then navigate the page, then start test
// by loading SJS with http 401 response.
iframe.addEventListener(
"mozbrowserloadend",
function() {
iframe.addEventListener(
"mozbrowserusernameandpasswordrequired",
testHttpAuthCancel
);
SimpleTest.executeSoon(function() {
// Use absolute path because we need to specify host.
iframe.src =
"http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
});
},
{ once: true }
);
}
function testHttpAuthCancel(e) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
testHttpAuthCancel
);
// Will cancel authentication, but prompt should not be shown again. Instead,
// we will be led to fail message
iframe.addEventListener("mozbrowserusernameandpasswordrequired", testFail);
iframe.addEventListener(
"mozbrowsertitlechange",
function(f) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
testFail
);
is(f.detail, "http auth failed", "expected authentication to fail");
iframe.addEventListener(
"mozbrowserusernameandpasswordrequired",
testHttpAuth
);
SimpleTest.executeSoon(function() {
// Use absolute path because we need to specify host.
iframe.src =
"http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
});
},
{ once: true }
);
is(e.detail.realm, "http_realm", "expected realm matches");
is(e.detail.host, "http://test", "expected host matches");
is(
e.detail.path,
"/tests/dom/browser-element/mochitest/file_http_401_response.sjs",
"expected path matches"
);
e.preventDefault();
SimpleTest.executeSoon(function() {
e.detail.cancel();
});
}
function testHttpAuth(e) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
testHttpAuth
);
// Will authenticate with correct password, prompt should not be
// called again.
iframe.addEventListener("mozbrowserusernameandpasswordrequired", testFail);
iframe.addEventListener(
"mozbrowsertitlechange",
function(f) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
testFail
);
is(f.detail, "http auth success", "expect authentication to succeed");
SimpleTest.executeSoon(testProxyAuth);
},
{ once: true }
);
is(e.detail.realm, "http_realm", "expected realm matches");
is(e.detail.host, "http://test", "expected host matches");
is(
e.detail.path,
"/tests/dom/browser-element/mochitest/file_http_401_response.sjs",
"expected path matches"
);
is(e.detail.isProxy, false, "expected isProxy is false");
e.preventDefault();
SimpleTest.executeSoon(function() {
e.detail.authenticate("httpuser", "httppass");
});
}
function testProxyAuth() {
// The testingSJS simulates the 407 proxy authentication required response
// for proxy server, which will trigger the browser element to send prompt
// event with proxy infomation.
var testingSJS =
"http://test/tests/dom/browser-element/mochitest/file_http_407_response.sjs";
var mozproxy;
function onUserNameAndPasswordRequired(e) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
onUserNameAndPasswordRequired
);
iframe.addEventListener(
"mozbrowsertitlechange",
function(event) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
testFail
);
is(
event.detail,
"http auth success",
"expect authentication to succeed"
);
SimpleTest.executeSoon(testAuthJarNoInterfere);
},
{ once: true }
);
is(e.detail.realm, "http_realm", "expected realm matches");
is(e.detail.host, mozproxy, "expected host matches");
is(
e.detail.path,
"/tests/dom/browser-element/mochitest/file_http_407_response.sjs",
"expected path matches"
);
is(e.detail.isProxy, true, "expected isProxy is true");
e.preventDefault();
SimpleTest.executeSoon(function() {
e.detail.authenticate("proxyuser", "proxypass");
});
}
// Resolve proxy information used by the test suite, we need it to validate
// whether the proxy information delivered with the prompt event is correct.
var resolveCallback = SpecialPowers.wrapCallbackObject({
// eslint-disable-next-line mozilla/use-chromeutils-generateqi
QueryInterface(iid) {
const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
if (
!interfaces.some(function(v) {
return iid.equals(v);
})
) {
throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
}
return this;
},
onProxyAvailable(req, channel, pi, status) {
isnot(pi, null, "expected proxy information available");
if (pi) {
mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
}
iframe.addEventListener(
"mozbrowserusernameandpasswordrequired",
onUserNameAndPasswordRequired
);
iframe.src = testingSJS;
},
});
var channel = NetUtil.newChannel({
uri: testingSJS,
loadUsingSystemPrincipal: true,
});
var pps = SpecialPowers.Cc[
"@mozilla.org/network/protocol-proxy-service;1"
].getService();
pps.asyncResolve(channel, 0, resolveCallback);
}
function testAuthJarNoInterfere(e) {
let authMgr = SpecialPowers.Cc[
"@mozilla.org/network/http-auth-manager;1"
].getService(SpecialPowers.Ci.nsIHttpAuthManager);
let secMan = SpecialPowers.Services.scriptSecurityManager;
let ioService = SpecialPowers.Services.io;
var uri = ioService.newURI(
"http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs"
);
// Set a bunch of auth data that should not conflict with the correct auth data already
// stored in the cache.
var attrs = { userContextId: 1 };
var principal = secMan.createContentPrincipal(uri, attrs);
authMgr.setAuthIdentity(
"http",
"test",
-1,
"basic",
"http_realm",
"tests/dom/browser-element/mochitest/file_http_401_response.sjs",
"",
"httpuser",
"wrongpass",
false,
principal
);
attrs = { userContextId: 1, inIsolatedMozBrowser: true };
principal = secMan.createContentPrincipal(uri, attrs);
authMgr.setAuthIdentity(
"http",
"test",
-1,
"basic",
"http_realm",
"tests/dom/browser-element/mochitest/file_http_401_response.sjs",
"",
"httpuser",
"wrongpass",
false,
principal
);
principal = secMan.createContentPrincipal(uri, {});
authMgr.setAuthIdentity(
"http",
"test",
-1,
"basic",
"http_realm",
"tests/dom/browser-element/mochitest/file_http_401_response.sjs",
"",
"httpuser",
"wrongpass",
false,
principal
);
// Will authenticate with correct password, prompt should not be
// called again.
iframe.addEventListener("mozbrowserusernameandpasswordrequired", testFail);
iframe.addEventListener(
"mozbrowsertitlechange",
function(f) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
testFail
);
is(f.detail, "http auth success", "expected authentication success");
SimpleTest.executeSoon(testAuthJarInterfere);
},
{ once: true }
);
// Once more with feeling. Ensure that our new auth data doesn't interfere with this mozbrowser's
// auth data.
iframe.src =
"http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
}
function testAuthJarInterfere(e) {
let authMgr = SpecialPowers.Cc[
"@mozilla.org/network/http-auth-manager;1"
].getService(SpecialPowers.Ci.nsIHttpAuthManager);
let secMan = SpecialPowers.Services.scriptSecurityManager;
let ioService = SpecialPowers.Services.io;
var uri = ioService.newURI(
"http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs"
);
// Set some auth data that should overwrite the successful stored details.
var principal = secMan.createContentPrincipal(uri, {
inIsolatedMozBrowser: true,
});
authMgr.setAuthIdentity(
"http",
"test",
-1,
"basic",
"http_realm",
"tests/dom/browser-element/mochitest/file_http_401_response.sjs",
"",
"httpuser",
"wrongpass",
false,
principal
);
// Will authenticate with correct password, prompt should not be
// called again.
var gotusernamepasswordrequired = false;
function onUserNameAndPasswordRequired() {
gotusernamepasswordrequired = true;
}
iframe.addEventListener(
"mozbrowserusernameandpasswordrequired",
onUserNameAndPasswordRequired
);
iframe.addEventListener(
"mozbrowsertitlechange",
function(f) {
iframe.removeEventListener(
"mozbrowserusernameandpasswordrequired",
onUserNameAndPasswordRequired
);
ok(
gotusernamepasswordrequired,
"Should have dispatched mozbrowserusernameandpasswordrequired event"
);
testFinish();
},
{ once: true }
);
// Once more with feeling. Ensure that our new auth data interferes with this mozbrowser's
// auth data.
iframe.src =
"http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
}
function testFinish() {
// Clear login information stored in password manager.
let authMgr = SpecialPowers.Cc[
"@mozilla.org/network/http-auth-manager;1"
].getService(SpecialPowers.Ci.nsIHttpAuthManager);
authMgr.clearAll();
SpecialPowers.Services.logins.removeAllLogins();
SimpleTest.finish();
}
addEventListener("testready", function() {
// Enable http authentiication.
SpecialPowers.pushPrefEnv(
{
set: [
[
"network.auth.non-web-content-triggered-resources-http-auth-allow",
true,
],
],
},
runTest
);
});

View File

@ -0,0 +1,115 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 741755 - Test that canGo{Back,Forward} and go{Forward,Back} work with
// <iframe mozbrowser>.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
var iframe;
function addOneShotIframeEventListener(event, fn) {
function wrapper(e) {
iframe.removeEventListener(event, wrapper);
fn(e);
}
iframe.addEventListener(event, wrapper);
}
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
addOneShotIframeEventListener("mozbrowserloadend", function() {
SimpleTest.executeSoon(test2);
});
iframe.src = browserElementTestHelpers.emptyPage1;
document.body.appendChild(iframe);
}
function checkCanGoBackAndForward(canGoBack, canGoForward, nextTest) {
var seenCanGoBackResult = false;
iframe.getCanGoBack().then(function(result) {
is(
seenCanGoBackResult,
false,
"onsuccess handler shouldn't be called twice."
);
seenCanGoBackResult = true;
is(result, canGoBack);
maybeRunNextTest();
});
var seenCanGoForwardResult = false;
iframe.getCanGoForward().then(function(result) {
is(
seenCanGoForwardResult,
false,
"onsuccess handler shouldn't be called twice."
);
seenCanGoForwardResult = true;
is(result, canGoForward);
maybeRunNextTest();
});
function maybeRunNextTest() {
if (seenCanGoBackResult && seenCanGoForwardResult) {
nextTest();
}
}
}
function test2() {
checkCanGoBackAndForward(false, false, test3);
}
function test3() {
addOneShotIframeEventListener("mozbrowserloadend", function() {
checkCanGoBackAndForward(true, false, test4);
});
SimpleTest.executeSoon(function() {
iframe.src = browserElementTestHelpers.emptyPage2;
});
}
function test4() {
addOneShotIframeEventListener("mozbrowserlocationchange", function(e) {
is(e.detail.url, browserElementTestHelpers.emptyPage3);
is(e.detail.canGoBack, true);
is(e.detail.canGoForward, false);
checkCanGoBackAndForward(true, false, test5);
});
SimpleTest.executeSoon(function() {
iframe.src = browserElementTestHelpers.emptyPage3;
});
}
function test5() {
addOneShotIframeEventListener("mozbrowserlocationchange", function(e) {
is(e.detail.url, browserElementTestHelpers.emptyPage2);
is(e.detail.canGoBack, true);
is(e.detail.canGoForward, true);
checkCanGoBackAndForward(true, true, test6);
});
iframe.goBack();
}
function test6() {
addOneShotIframeEventListener("mozbrowserlocationchange", function(e) {
is(e.detail.url, browserElementTestHelpers.emptyPage1);
is(e.detail.canGoBack, false);
is(e.detail.canGoForward, true);
checkCanGoBackAndForward(false, true, SimpleTest.finish);
});
iframe.goBack();
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,56 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 891763 - Test the mozbrowserresize event
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var srcResizeTo =
"data:text/html, \
<script type='application/javascript'> \
window.resizeTo(300, 300); \
</script> \
";
var srcResizeBy =
"data:text/html, \
<script type='application/javascript'> \
window.resizeBy(-100, -100); \
</script> \
";
var count = 0;
function checkSize(iframe) {
count++;
is(iframe.clientWidth, 400, "iframe width does not change");
is(iframe.clientHeight, 400, "iframe height does not change");
if (count == 2) {
SimpleTest.finish();
}
}
function testIFrameWithSrc(src) {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.style = "border:none; width:400px; height:400px;";
iframe.src = src;
iframe.addEventListener("mozbrowserresize", function(e) {
is(e.detail.width, 300, "Received correct resize event width");
is(e.detail.height, 300, "Received correct resize event height");
SimpleTest.executeSoon(checkSize.bind(undefined, iframe));
});
document.body.appendChild(iframe);
}
testIFrameWithSrc(srcResizeTo);
testIFrameWithSrc(srcResizeBy);
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,28 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that window.close() works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
iframe.addEventListener("mozbrowserclose", function(e) {
ok(true, "got mozbrowserclose event.");
SimpleTest.finish();
});
iframe.src =
"data:text/html,<html><body><script>window.close()</script></body></html>";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,474 @@
"use strict";
/* global browserElementTestHelpers */
/* eslint-env mozilla/frame-script */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.setClipboardPlainTextOnlyPref(false);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
var audioUrl =
"http://mochi.test:8888/tests/dom/browser-element/mochitest/audio.ogg";
var videoUrl =
"http://mochi.test:8888/tests/dom/browser-element/mochitest/short-video.ogv";
function runTests() {
createIframe(function onIframeLoaded() {
checkEmptyContextMenu();
});
}
function checkEmptyContextMenu() {
sendContextMenuTo("body", function onContextMenu(detail) {
is(detail.contextmenu, null, "Body context clicks have no context menu");
checkInnerContextMenu();
});
}
function checkInnerContextMenu() {
sendContextMenuTo("#inner-link", function onContextMenu(detail) {
is(detail.systemTargets.length, 1, "Includes anchor data");
is(
detail.contextmenu.items.length,
3,
"Inner clicks trigger correct customized menu"
);
is(
detail.contextmenu.items[0].label,
"foo",
'Customized menu has a "foo" menu item'
);
is(
detail.contextmenu.items[1].label,
"bar",
'Customized menu has a "bar" menu item'
);
is(
detail.contextmenu.items[2].id,
"copy-link",
"#inner-link has a copy-link menu item"
);
is(
detail.contextmenu.customized,
true,
"Make sure contextmenu has customized items"
);
var target = detail.systemTargets[0];
is(target.nodeName, "A", "Reports correct nodeName");
is(target.data.uri, "foo.html", "Reports correct uri");
is(target.data.text, "Menu 1", "Reports correct link text");
checkCustomContextMenu();
});
}
function checkCustomContextMenu() {
sendContextMenuTo("#menu1-trigger", function onContextMenu(detail) {
is(detail.contextmenu.items.length, 2, "trigger custom contextmenu");
checkNestedContextMenu();
});
}
function checkNestedContextMenu() {
sendContextMenuTo("#menu2-trigger", function onContextMenu(detail) {
var innerMenu = detail.contextmenu.items.filter(function(x) {
return x.type === "menu";
});
is(detail.systemTargets.length, 2, "Includes two systemTargets");
is(detail.systemTargets[0].nodeName, "IMG", 'Includes "IMG" node');
is(
detail.systemTargets[0].data.uri,
"example.png",
"Img data has the correct uri"
);
is(detail.systemTargets[1].nodeName, "A", 'Includes "A" node');
is(
detail.systemTargets[1].data.uri,
"bar.html",
"Anchor has the correct uri"
);
ok(innerMenu.length > 0, "Menu contains a nested menu");
is(detail.contextmenu.items.length, 4, "We have correct # of menu items");
is(
detail.contextmenu.customized,
true,
"Make sure contextmenu has customized items"
);
is(
detail.contextmenu.items[0].label,
"outer",
'Customized menu has an "outer" menu item'
);
is(
detail.contextmenu.items[1].label,
"submenu",
'Customized menu has an "submenu" menu item'
);
is(
detail.contextmenu.items[2].id,
"copy-link",
"Has a copy-link menu item"
);
is(
detail.contextmenu.items[3].id,
"copy-image",
"Has a copy-image menu item"
);
checkPreviousContextMenuHandler();
});
}
// Finished testing the data passed to the contextmenu handler,
// now we start selecting contextmenu items
function checkPreviousContextMenuHandler() {
// This is previously triggered contextmenu data, since we have
// fired subsequent contextmenus this should not be mistaken
// for a current menuitem
var detail = previousContextMenuDetail;
var previousId = detail.contextmenu.items[0].id;
checkContextMenuCallbackForId(detail, previousId, function onCallbackFired(
label
) {
is(label, null, "Callback label should be empty since this handler is old");
checkCurrentContextMenuHandler();
});
}
function checkCurrentContextMenuHandler() {
// This triggers a current menuitem
var detail = currentContextMenuDetail;
var innerMenu = detail.contextmenu.items.filter(function(x) {
return x.type === "menu";
});
var currentId = innerMenu[0].items[1].id;
checkContextMenuCallbackForId(detail, currentId, function onCallbackFired(
label
) {
is(label, "inner 2", "Callback label should be set correctly");
checkAgainCurrentContextMenuHandler();
});
}
function checkAgainCurrentContextMenuHandler() {
// Once an item it selected, subsequent selections are ignored
var detail = currentContextMenuDetail;
var innerMenu = detail.contextmenu.items.filter(function(x) {
return x.type === "menu";
});
var currentId = innerMenu[0].items[1].id;
checkContextMenuCallbackForId(detail, currentId, function onCallbackFired(
label
) {
is(
label,
null,
"Callback label should be empty since this handler has already been used"
);
checkCallbackWithPreventDefault();
});
}
// Finished testing callbacks if the embedder calls preventDefault() on the
// mozbrowsercontextmenu event, now we start checking for some cases where the embedder
// does not want to call preventDefault() for some reasons.
function checkCallbackWithPreventDefault() {
sendContextMenuTo("#menu1-trigger", function onContextMenu(detail) {
var id = detail.contextmenu.items[0].id;
checkContextMenuCallbackForId(detail, id, function onCallbackFired(label) {
is(label, "foo", "Callback label should be set correctly");
checkCallbackWithoutPreventDefault();
});
});
}
function checkCallbackWithoutPreventDefault() {
sendContextMenuTo(
"#menu1-trigger",
function onContextMenu(detail) {
var id = detail.contextmenu.items[0].id;
checkContextMenuCallbackForId(detail, id, function onCallbackFired(
label
) {
is(label, null, "Callback label should be null");
checkImageContextMenu();
});
},
/* ignorePreventDefault */ true
);
}
function checkImageContextMenu() {
sendContextMenuTo(
"#menu3-trigger",
function onContextMenu(detail) {
var target = detail.systemTargets[0];
is(target.nodeName, "IMG", "Reports correct nodeName");
is(target.data.uri, "example.png", "Reports correct uri");
is(detail.contextmenu.items.length, 1, "Reports correct # of menu items");
is(
detail.contextmenu.items[0].id,
"copy-image",
"IMG has a copy-image menu item"
);
is(
detail.contextmenu.customized,
false,
"Make sure we do not have customized items"
);
checkVideoContextMenu();
},
/* ignorePreventDefault */ true
);
}
function checkVideoContextMenu() {
sendContextMenuTo(
"#menu4-trigger",
function onContextMenu(detail) {
var target = detail.systemTargets[0];
is(target.nodeName, "VIDEO", "Reports correct nodeName");
is(target.data.uri, videoUrl, "Reports uri correctly in data");
is(target.data.hasVideo, true, 'Video data in video tag does "hasVideo"');
checkAudioContextMenu();
},
/* ignorePreventDefault */ true
);
}
function checkAudioContextMenu() {
sendContextMenuTo(
"#menu6-trigger",
function onContextMenu(detail) {
var target = detail.systemTargets[0];
is(target.nodeName, "AUDIO", "Reports correct nodeName");
is(target.data.uri, audioUrl, "Reports uri correctly in data");
checkAudioinVideoContextMenu();
},
/* ignorePreventDefault */ true
);
}
function checkAudioinVideoContextMenu() {
sendSrcTo("#menu5-trigger", audioUrl, function onSrcSet() {
sendContextMenuTo(
"#menu5-trigger",
function onContextMenu(detail) {
var target = detail.systemTargets[0];
is(target.nodeName, "VIDEO", "Reports correct nodeName");
is(target.data.uri, audioUrl, "Reports uri correctly in data");
is(
target.data.hasVideo,
false,
'Audio data in video tag reports no "hasVideo"'
);
checkFormNoMethod();
},
/* ignorePreventDefault */ true
);
});
}
function checkFormNoMethod() {
sendContextMenuTo(
"#menu7-trigger",
function onContextMenu(detail) {
var target = detail.systemTargets[0];
is(target.nodeName, "INPUT", "Reports correct nodeName");
is(target.data.method, "get", "Reports correct method");
is(target.data.action, "no_method", "Reports correct action url");
is(target.data.name, "input1", "Reports correct input name");
checkFormGetMethod();
},
/* ignorePreventDefault */ true
);
}
function checkFormGetMethod() {
sendContextMenuTo(
"#menu8-trigger",
function onContextMenu(detail) {
var target = detail.systemTargets[0];
is(target.nodeName, "INPUT", "Reports correct nodeName");
is(target.data.method, "get", "Reports correct method");
is(
target.data.action,
"http://example.com/get_method",
"Reports correct action url"
);
is(target.data.name, "input2", "Reports correct input name");
checkFormPostMethod();
},
/* ignorePreventDefault */ true
);
}
function checkFormPostMethod() {
sendContextMenuTo(
"#menu9-trigger",
function onContextMenu(detail) {
var target = detail.systemTargets[0];
is(target.nodeName, "INPUT", "Reports correct nodeName");
is(target.data.method, "post", "Reports correct method");
is(target.data.action, "post_method", "Reports correct action url");
is(target.data.name, "input3", "Reports correct input name");
SimpleTest.finish();
},
/* ignorePreventDefault */ true
);
}
/* Helpers */
var mm = null;
var previousContextMenuDetail = null;
var currentContextMenuDetail = null;
function sendSrcTo(selector, src, callback) {
mm.sendAsyncMessage("setsrc", { selector, src });
mm.addMessageListener("test:srcset", function onSrcSet(msg) {
mm.removeMessageListener("test:srcset", onSrcSet);
callback();
});
}
function sendContextMenuTo(selector, callback, ignorePreventDefault) {
iframe.addEventListener("mozbrowsercontextmenu", function oncontextmenu(e) {
iframe.removeEventListener(e.type, oncontextmenu);
// The embedder should call preventDefault() on the event if it will handle
// it. Not calling preventDefault() means it won't handle the event and
// should not be able to deal with context menu callbacks.
if (ignorePreventDefault !== true) {
e.preventDefault();
}
// Keep a reference to previous/current contextmenu event details.
previousContextMenuDetail = currentContextMenuDetail;
currentContextMenuDetail = e.detail;
setTimeout(function() {
callback(e.detail);
});
});
mm.sendAsyncMessage("contextmenu", { selector });
}
function checkContextMenuCallbackForId(detail, id, callback) {
mm.addMessageListener("test:callbackfired", function onCallbackFired(msg) {
mm.removeMessageListener("test:callbackfired", onCallbackFired);
msg = SpecialPowers.wrap(msg);
setTimeout(function() {
callback(msg.data.label);
});
});
detail.contextMenuItemSelected(id);
}
var iframe = null;
function createIframe(callback) {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.src =
"data:text/html,<html>" +
"<body>" +
'<menu type="context" id="menu1" label="firstmenu">' +
'<menuitem label="foo" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
'<menuitem label="bar" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
"</menu>" +
'<menu type="context" id="menu2" label="secondmenu">' +
'<menuitem label="outer" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
'<menu label="submenu">' +
'<menuitem label="inner 1"></menuitem>' +
'<menuitem label="inner 2" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
"</menu>" +
"</menu>" +
'<div id="menu1-trigger" contextmenu="menu1"><a id="inner-link" href="foo.html">Menu 1</a></div>' +
'<a href="bar.html" contextmenu="menu2"><img id="menu2-trigger" src="example.png" /></a>' +
'<img id="menu3-trigger" src="example.png" />' +
'<video id="menu4-trigger" src="' +
videoUrl +
'"></video>' +
'<video id="menu5-trigger" preload="metadata"></video>' +
'<audio id="menu6-trigger" src="' +
audioUrl +
'"></audio>' +
'<form action="no_method"><input id="menu7-trigger" name="input1"></input></form>' +
'<form action="http://example.com/get_method" method="get"><input id="menu8-trigger" name="input2"></input></form>' +
'<form action="post_method" method="post"><input id="menu9-trigger" name="input3"></input></form>' +
"</body></html>";
document.body.appendChild(iframe);
// The following code will be included in the child
// =========================================================================
function iframeScript() {
addMessageListener("contextmenu", function onContextMenu(msg) {
var document = content.document;
var evt = document.createEvent("HTMLEvents");
evt.initEvent("contextmenu", true, true);
document.querySelector(msg.data.selector).dispatchEvent(evt);
});
addMessageListener("setsrc", function onContextMenu(msg) {
var wrappedTarget = content.document.querySelector(msg.data.selector);
var target = XPCNativeWrapper.unwrap(wrappedTarget);
target.addEventListener("loadedmetadata", function() {
sendAsyncMessage("test:srcset");
});
target.src = msg.data.src;
});
addMessageListener("browser-element-api:call", function onCallback(msg) {
if (msg.data.msg_name != "fire-ctx-callback") {
return;
}
/* Use setTimeout in order to react *after* the platform */
content.setTimeout(function() {
sendAsyncMessage("test:callbackfired", { label });
label = null;
});
});
var label = null;
XPCNativeWrapper.unwrap(content).onContextMenuCallbackFired = function(e) {
label = e.target.getAttribute("label");
};
}
// =========================================================================
iframe.addEventListener("mozbrowserloadend", function onload(e) {
iframe.removeEventListener(e.type, onload);
mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.loadFrameScript("data:,(" + iframeScript.toString() + ")();", false);
// Now we're ready, let's start testing.
callback();
});
}
addEventListener("testready", runTests);

View File

@ -0,0 +1,57 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 806127 - Test that cookies set by <iframe mozbrowser> are not considered
// third-party.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
const innerPage =
"http://example.com/tests/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html";
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
if (e.detail.message == "next") {
iframe.src = innerPage + "?step=2";
return;
}
if (e.detail.message.startsWith("success:")) {
ok(true, e.detail.message);
return;
}
if (e.detail.message.startsWith("failure:")) {
ok(false, e.detail.message);
return;
}
if (e.detail.message == "finish") {
SimpleTest.finish();
}
});
// innerPage will set a cookie and then alert('next'). We'll load
// innerPage?step=2. That page will check that the cooke exists (despite the
// fact that we've disabled third-party cookies) and alert('success:') or
// alert('failure:'), as appropriate. Finally, the page will
// alert('finish');
iframe.src = innerPage;
document.body.appendChild(iframe);
}
// Disable third-party cookies for this test.
addEventListener("testready", function() {
SpecialPowers.pushPrefEnv(
{ set: [["network.cookie.cookieBehavior", 1]] },
runTest
);
});

View File

@ -0,0 +1,428 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that "cut, copy, paste, selectall" and caretstatechanged event works from inside an <iframe mozbrowser>.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.setupAccessibleCaretPref();
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
var gTextarea = null;
var mm;
var iframeOuter;
var iframeInner;
var state = 0;
var stateMeaning;
var defaultData;
var pasteData;
var focusScript;
var createEmbededFrame = false;
var testSelectionChange = false;
function copyToClipboard(str, callback) {
gTextarea.value = str;
SpecialPowers.wrap(gTextarea).editor.selectAll();
SimpleTest.waitForClipboard(
gTextarea.value,
() => {
SpecialPowers.wrap(gTextarea).editor.copy();
},
callback,
() => {
ok(false, "clipboard copy failed");
}
);
}
function getScriptForGetContent() {
var script =
'data:,\
var elt = content.document.getElementById("text"); \
var txt = ""; \
if (elt) { \
if (elt.tagName === "DIV" || elt.tagName === "BODY") { \
txt = elt.textContent; \
} else { \
txt = elt.value; \
} \
} \
sendAsyncMessage("content-text", txt);';
return script;
}
function getScriptForSetFocus() {
var script = "data:," + focusScript + 'sendAsyncMessage("content-focus")';
return script;
}
function runTest() {
iframeOuter = document.createElement("iframe");
iframeOuter.setAttribute("mozbrowser", "true");
if (createEmbededFrame) {
iframeOuter.src = "file_empty.html";
}
document.body.appendChild(iframeOuter);
gTextarea = document.createElement("textarea");
document.body.appendChild(gTextarea);
iframeOuter.addEventListener(
"mozbrowserloadend",
function(e) {
if (createEmbededFrame) {
var contentWin = SpecialPowers.wrap(iframeOuter).frameLoader.docShell
.contentViewer.DOMDocument.defaultView;
var contentDoc = contentWin.document;
iframeInner = contentDoc.createElement("iframe");
iframeInner.setAttribute("mozbrowser", true);
iframeInner.setAttribute("remote", "false");
contentDoc.body.appendChild(iframeInner);
iframeInner.addEventListener(
"mozbrowserloadend",
function(f) {
mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner);
dispatchTest(f);
},
{ once: true }
);
} else {
iframeInner = iframeOuter;
mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner);
dispatchTest(e);
}
},
{ once: true }
);
}
function doCommand(cmd) {
var COMMAND_MAP = {
cut: "cmd_cut",
copy: "cmd_copy",
paste: "cmd_paste",
selectall: "cmd_selectAll",
};
var script = 'data:,docShell.doCommand("' + COMMAND_MAP[cmd] + '");';
mm.loadFrameScript(script, false);
}
function dispatchTest(e) {
iframeInner.addEventListener(
"mozbrowserloadend",
function(f) {
iframeInner.focus();
SimpleTest.executeSoon(function() {
testSelectAll(f);
});
},
{ once: true }
);
switch (state) {
case 0: // test for textarea
defaultData = "Test for selection change event";
pasteData = "from parent ";
iframeInner.src =
"data:text/html,<html><body>" +
"<textarea id='text'>" +
defaultData +
"</textarea>" +
"</body>" +
"</html>";
stateMeaning = " (test: textarea)";
focusScript =
"var elt=content.document.getElementById('text');elt.focus();elt.select();";
break;
case 1: // test for input text
defaultData = "Test for selection change event";
pasteData = "from parent ";
iframeInner.src =
"data:text/html,<html><body>" +
"<input type='text' id='text' value='" +
defaultData +
"'>" +
"</body>" +
"</html>";
stateMeaning = " (test: <input type=text>)";
focusScript =
"var elt=content.document.getElementById('text');elt.focus();elt.select();";
break;
case 2: // test for input number
defaultData = "12345";
pasteData = "67890";
iframeInner.src =
"data:text/html,<html><body>" +
"<input type='number' id='text' value='" +
defaultData +
"'>" +
"</body>" +
"</html>";
stateMeaning = " (test: <input type=number>)";
focusScript =
"var elt=content.document.getElementById('text');elt.focus();elt.select();";
break;
case 3: // test for div contenteditable
defaultData = "Test for selection change event";
pasteData = "from parent ";
iframeInner.src =
"data:text/html,<html><body>" +
"<div contenteditable='true' id='text'>" +
defaultData +
"</div>" +
"</body>" +
"</html>";
stateMeaning = " (test: content editable div)";
focusScript =
"var elt=content.document.getElementById('text');elt.focus();";
break;
case 4: // test for normal div
defaultData = "Test for selection change event";
pasteData = "from parent ";
iframeInner.src =
"data:text/html,<html><body>" +
"<div id='text'>" +
defaultData +
"</div>" +
"</body>" +
"</html>";
stateMeaning = " (test: normal div)";
focusScript =
"var elt=content.document.getElementById('text');elt.focus();";
break;
case 5: // test for normal div with designMode:on
defaultData = "Test for selection change event";
pasteData = "from parent ";
iframeInner.src =
"data:text/html,<html><body id='text'>" +
defaultData +
"</body>" +
"<script>document.designMode='on';</script>" +
"</html>";
stateMeaning = " (test: normal div with designMode:on)";
focusScript =
"var elt=content.document.getElementById('text');elt.focus();";
break;
default:
if (
createEmbededFrame ||
browserElementTestHelpers.getOOPByDefaultPref()
) {
SimpleTest.finish();
} else {
createEmbededFrame = true;
// clean up and run test again.
document.body.removeChild(iframeOuter);
document.body.removeChild(gTextarea);
state = 0;
runTest();
}
break;
}
}
function isChildProcess() {
return (
SpecialPowers.Services.appinfo.processType !=
SpecialPowers.Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
);
}
function testSelectAll(e) {
// Skip mozbrowser test if we're at child process.
if (!isChildProcess()) {
let eventName = "mozbrowsercaretstatechanged";
iframeOuter.addEventListener(
eventName,
function(f) {
ok(true, "got mozbrowsercaretstatechanged event." + stateMeaning);
ok(f.detail, "event.detail is not null." + stateMeaning);
ok(
f.detail.width != 0,
"event.detail.width is not zero" + stateMeaning
);
ok(
f.detail.height != 0,
"event.detail.height is not zero" + stateMeaning
);
SimpleTest.executeSoon(function() {
testCopy1(f);
});
},
{ capture: true, once: true }
);
}
mm.addMessageListener("content-focus", function messageforfocus(msg) {
mm.removeMessageListener("content-focus", messageforfocus);
// test selectall command, after calling this the caretstatechanged event should be fired.
doCommand("selectall");
if (isChildProcess()) {
SimpleTest.executeSoon(function() {
testCopy1(e);
});
}
});
mm.loadFrameScript(getScriptForSetFocus(), false);
}
function testCopy1(e) {
// Right now we're at "selectall" state, so we can test copy commnad by
// calling doCommand
copyToClipboard("", () => {
let setup = function() {
doCommand("copy");
};
let nextTest = function(success) {
ok(success, "copy command works" + stateMeaning);
SimpleTest.executeSoon(function() {
testPaste1(e);
});
};
let success = function() {
nextTest(true);
};
let fail = function() {
nextTest(false);
};
let compareData = defaultData;
SimpleTest.waitForClipboard(compareData, setup, success, fail);
});
}
function testPaste1(e) {
// Next test paste command, first we copy to global clipboard in parent side.
// Then paste it to child side.
copyToClipboard(pasteData, () => {
doCommand("selectall");
doCommand("paste");
SimpleTest.executeSoon(function() {
testPaste2(e);
});
});
}
function testPaste2(e) {
mm.addMessageListener("content-text", function messageforpaste(msg) {
mm.removeMessageListener("content-text", messageforpaste);
if (state == 4) {
// normal div cannot paste, so the content remain unchange
ok(
SpecialPowers.wrap(msg).json === defaultData,
"paste command works" + stateMeaning
);
} else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
// Something weird when we doCommand with content editable element in OOP. Mark this case as todo
todo(false, "paste command works" + stateMeaning);
} else {
ok(
SpecialPowers.wrap(msg).json === pasteData,
"paste command works" + stateMeaning
);
}
SimpleTest.executeSoon(function() {
testCut1(e);
});
});
mm.loadFrameScript(getScriptForGetContent(), false);
}
function testCut1(e) {
// Clean clipboard first
copyToClipboard("", () => {
let setup = function() {
doCommand("selectall");
doCommand("cut");
};
let nextTest = function(success) {
if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
// Something weird when we doCommand with content editable element in OOP.
todo(false, "cut function works" + stateMeaning);
} else {
ok(success, "cut function works" + stateMeaning);
}
SimpleTest.executeSoon(function() {
testCut2(e);
});
};
let success = function() {
nextTest(true);
};
let fail = function() {
nextTest(false);
};
let compareData = pasteData;
// Something weird when we doCommand with content editable element in OOP.
// Always true in this case
// Normal div case cannot cut, always true as well.
if (
(state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) ||
state == 4
) {
compareData = function() {
return true;
};
}
SimpleTest.waitForClipboard(compareData, setup, success, fail);
});
}
function testCut2(e) {
mm.addMessageListener("content-text", function messageforcut(msg) {
mm.removeMessageListener("content-text", messageforcut);
// normal div cannot cut
if (state == 4) {
ok(
SpecialPowers.wrap(msg).json !== "",
"cut command works" + stateMeaning
);
} else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
// Something weird when we doCommand with content editable element in OOP. Mark this case as todo
todo(false, "cut command works" + stateMeaning);
} else {
ok(
SpecialPowers.wrap(msg).json === "",
"cut command works" + stateMeaning
);
}
state++;
dispatchTest(e);
});
mm.loadFrameScript(getScriptForGetContent(), false);
}
// Give our origin permission to open browsers, and remove it when the test is complete.
var principal = SpecialPowers.wrap(document).nodePrincipal;
var context = {
url: SpecialPowers.wrap(principal.URI).spec,
originAttributes: {
inIsolatedMozBrowser: true,
},
};
addEventListener("testready", function() {
SpecialPowers.pushPermissions(
[{ type: "browser", allow: 1, context }],
runTest
);
});

View File

@ -0,0 +1,74 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that data: URIs work with mozbrowserlocationchange events.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe1 = document.createElement("iframe");
iframe1.setAttribute("mozbrowser", "true");
iframe1.id = "iframe1";
iframe1.addEventListener(
"mozbrowserloadend",
function() {
ok(true, "Got first loadend event.");
SimpleTest.executeSoon(runTest2);
},
{ once: true }
);
iframe1.src = browserElementTestHelpers.emptyPage1;
document.body.appendChild(iframe1);
var iframe2 = document.createElement("iframe");
iframe2.id = "iframe2";
document.body.appendChild(iframe2);
}
function runTest2() {
var iframe1 = document.getElementById("iframe1");
var iframe2 = document.getElementById("iframe2");
var sawLoadEnd = false;
var sawLocationChange = false;
iframe1.addEventListener("mozbrowserlocationchange", function(e) {
ok(e.isTrusted, "Event should be trusted.");
ok(!sawLocationChange, "Just one locationchange event.");
ok(!sawLoadEnd, "locationchange before load.");
is(e.detail.url, "data:text/html,1", "event's reported location");
sawLocationChange = true;
});
iframe1.addEventListener("mozbrowserloadend", function() {
ok(sawLocationChange, "Loadend after locationchange.");
ok(!sawLoadEnd, "Just one loadend event.");
sawLoadEnd = true;
});
function iframe2Load() {
if (!sawLoadEnd || !sawLocationChange) {
// Spin if iframe1 hasn't loaded yet.
SimpleTest.executeSoon(iframe2Load);
return;
}
ok(true, "Got iframe2 load.");
SimpleTest.finish();
}
iframe2.addEventListener("load", iframe2Load);
iframe1.src = "data:text/html,1";
// Load something into iframe2 to check that it doesn't trigger a
// locationchange for our iframe1 listener.
iframe2.src = browserElementTestHelpers.emptyPage2;
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,5 @@
<html>
<body>
foo
</body>
</html>

View File

@ -0,0 +1,72 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout(
"testing mozbrowser data: navigation is blocked"
);
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
// make sure top level data: URI navigations are blocked.
const PREF = "security.data_uri.block_toplevel_data_uri_navigations";
browserElementTestHelpers._setPref(PREF, true);
const INNER = "foo";
const DATA_URI = "data:text/html,<html><body>" + INNER + "</body></html>";
const HTTP_URI = "browserElement_DataURILoad.html";
function runTest1() {
let frame = document.createElement("iframe");
frame.setAttribute("mozbrowser", "true");
frame.src = DATA_URI;
document.body.appendChild(frame);
let wrappedFrame = SpecialPowers.wrap(frame);
// wait for 1000ms and check that the data: URI did not load
setTimeout(function() {
isnot(
wrappedFrame.contentWindow.document.body.innerHTML,
INNER,
"data: URI navigation should be blocked"
);
runTest2();
}, 1000);
}
function runTest2() {
let frame = document.createElement("iframe");
frame.setAttribute("mozbrowser", "true");
frame.src = HTTP_URI;
document.body.appendChild(frame);
let wrappedFrame = SpecialPowers.wrap(frame);
wrappedFrame.addEventListener(
"mozbrowserloadend",
function onloadend(e) {
ok(
wrappedFrame.contentWindow.document.location.href.endsWith(HTTP_URI),
"http: URI navigation should be allowed"
);
frame.src = DATA_URI;
// wait for 1000ms and check that the data: URI did not load
setTimeout(function() {
isnot(
wrappedFrame.contentWindow.document.body.innerHTML,
INNER,
"data: URI navigation should be blocked"
);
SimpleTest.finish();
}, 1000);
},
{ once: true }
);
}
addEventListener("testready", runTest1);

View File

@ -0,0 +1,77 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 829486 - Add mozdocumentbrowserfirstpaint event.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
var iframe;
function runTestQueue(queue) {
if (queue.length == 0) {
SimpleTest.finish();
return;
}
var gotFirstPaint = false;
var gotFirstLocationChange = false;
var test = queue.shift();
function runNext() {
iframe.removeEventListener(
"mozbrowserdocumentfirstpaint",
documentfirstpainthandler
);
iframe.removeEventListener("mozbrowserloadend", loadendhandler);
runTestQueue(queue);
}
function documentfirstpainthandler(e) {
ok(!gotFirstPaint, "Got firstpaint only once");
gotFirstPaint = true;
if (gotFirstLocationChange) {
runNext();
}
}
function loadendhandler(e) {
gotFirstLocationChange = true;
if (gotFirstPaint) {
runNext();
}
}
iframe.addEventListener(
"mozbrowserdocumentfirstpaint",
documentfirstpainthandler
);
iframe.addEventListener("mozbrowserloadend", loadendhandler);
test();
}
function testChangeLocation() {
iframe.src = browserElementTestHelpers.emptyPage1 + "?2";
}
function testReload() {
iframe.reload();
}
function testFirstLoad() {
document.body.appendChild(iframe);
iframe.src = browserElementTestHelpers.emptyPage1;
}
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
runTestQueue([testFirstLoad, testReload, testChangeLocation]);
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,74 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 764718 - Test that mozbrowsererror works for a security error.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
var iframe = null;
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
checkForDnsError();
}
function checkForDnsError() {
iframe.addEventListener("mozbrowsererror", function onDnsError(e) {
iframe.removeEventListener(e.type, onDnsError);
ok(true, "Got mozbrowsererror event.");
ok(
e.detail.type == "dnsNotFound",
"Event's detail has a |type| param with the value '" +
e.detail.type +
"'."
);
checkForExpiredCertificateError();
});
iframe.src = "http://this_is_not_a_domain.example.com";
}
function checkForExpiredCertificateError() {
iframe.addEventListener("mozbrowsererror", function onCertError(e) {
iframe.removeEventListener(e.type, onCertError);
ok(true, "Got mozbrowsererror event.");
ok(
e.detail.type == "certerror",
"Event's detail has a |type| param with the value '" +
e.detail.type +
"'."
);
checkForNoCertificateError();
});
iframe.src = "https://expired.example.com";
}
function checkForNoCertificateError() {
iframe.addEventListener("mozbrowsererror", function onCertError(e) {
iframe.removeEventListener(e.type, onCertError);
ok(true, "Got mozbrowsererror event.");
ok(
e.detail.type == "certerror",
"Event's detail has a |type| param with the value '" +
e.detail.type +
"'."
);
SimpleTest.finish();
});
iframe.src = "https://nocert.example.com";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,45 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 795317: Test that the browser element sanitizes its URIs by removing the
// "unexposable" parts before sending them in the locationchange event.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
var iframe;
function testPassword() {
function locationchange(e) {
var uri = e.detail.url;
is(
uri,
"http://mochi.test:8888/tests/dom/browser-element/mochitest/file_empty.html",
"Username and password shouldn't be exposed in uri."
);
SimpleTest.finish();
}
iframe.addEventListener("mozbrowserlocationchange", locationchange);
iframe.src =
"http://iamuser:iampassword@mochi.test:8888/tests/dom/browser-element/mochitest/file_empty.html";
}
function runTest() {
SpecialPowers.pushPrefEnv(
{ set: [["network.http.rcwn.enabled", false]] },
_ => {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
testPassword();
}
);
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,44 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 787378 - Add mozbrowserfirstpaint event.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
var gotFirstPaint = false;
var gotFirstLocationChange = false;
iframe.addEventListener("mozbrowserfirstpaint", function(e) {
ok(!gotFirstPaint, "Got only one first paint.");
gotFirstPaint = true;
if (gotFirstLocationChange) {
iframe.src = browserElementTestHelpers.emptyPage1 + "?2";
}
});
iframe.addEventListener("mozbrowserlocationchange", function(e) {
if (e.detail.url == browserElementTestHelpers.emptyPage1) {
gotFirstLocationChange = true;
if (gotFirstPaint) {
iframe.src = browserElementTestHelpers.emptyPage1 + "?2";
}
} else if (e.detail.url.endsWith("?2")) {
SimpleTest.finish();
}
});
document.body.appendChild(iframe);
iframe.src = browserElementTestHelpers.emptyPage1;
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,41 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 781320 - Test that the name in <iframe mozbrowser name="foo"> is
// forwarded down to remote mozbrowsers.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.setAttribute("name", "foo");
iframe.addEventListener("mozbrowserlocationchange", function(e) {
ok(true, "Got locationchange to " + e.detail.url);
if (e.detail.url.endsWith("ForwardName.html#finish")) {
SimpleTest.finish();
}
});
// The file sends us messages via alert() that start with "success:" or
// "failure:".
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
ok(e.detail.message.startsWith("success:"), e.detail.message);
});
document.body.appendChild(iframe);
// This file does window.open('file_browserElement_ForwardName.html#finish',
// 'foo'); That should open in the curent window, because the window should
// be named foo.
iframe.src = "file_browserElement_ForwardName.html";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,139 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowsericonchange event works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function createHtml(link) {
return "data:text/html,<html><head>" + link + "<body></body></html>";
}
function createLink(name, sizes, rel) {
var s = sizes ? 'sizes="' + sizes + '"' : "";
if (!rel) {
rel = "icon";
}
return (
'<link rel="' +
rel +
'" type="image/png" ' +
s +
' href="http://example.com/' +
name +
'.png">'
);
}
function runTest() {
var iframe1 = document.createElement("iframe");
iframe1.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe1);
// iframe2 is a red herring; we modify its favicon but don't listen for
// iconchanges; we want to make sure that its iconchange events aren't
// picked up by the listener on iframe1.
var iframe2 = document.createElement("iframe");
iframe2.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe2);
// iframe3 is another red herring. It's not a mozbrowser, so we shouldn't
// get any iconchange events on it.
var iframe3 = document.createElement("iframe");
document.body.appendChild(iframe3);
var numIconChanges = 0;
iframe1.addEventListener("mozbrowsericonchange", function(e) {
numIconChanges++;
if (numIconChanges == 1) {
is(e.detail.href, "http://example.com/myicon.png");
// We should recieve iconchange events when the user creates new links
// to a favicon, but only when we listen for them
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.title='New title';",
/* allowDelayedLoad = */ false
);
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=ICON href=http://example.com/newicon.png>')",
/* allowDelayedLoad = */ false
);
SpecialPowers.getBrowserFrameMessageManager(iframe2).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=ICON href=http://example.com/newicon.png>')",
/* allowDelayedLoad = */ false
);
} else if (numIconChanges == 2) {
is(e.detail.href, "http://example.com/newicon.png");
// Full new pages should trigger iconchange events
iframe1.src = createHtml(createLink("3rdicon"));
} else if (numIconChanges == 3) {
is(e.detail.href, "http://example.com/3rdicon.png");
// the rel attribute can have various space seperated values, make
// sure we only pick up correct values for 'icon'
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=shortcuticon href=http://example.com/newicon.png>')",
/* allowDelayedLoad = */ false
);
// Test setting a page with multiple links elements
iframe1.src = createHtml(createLink("another") + createLink("icon"));
} else if (numIconChanges == 4) {
is(e.detail.href, "http://example.com/another.png");
// 2 events will be triggered by previous test, wait for next
} else if (numIconChanges == 5) {
is(e.detail.href, "http://example.com/icon.png");
// Make sure icon check is case insensitive
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=ICON href=http://example.com/ucaseicon.png>')",
/* allowDelayedLoad = */ false
);
} else if (numIconChanges == 6) {
is(e.detail.href, "http://example.com/ucaseicon.png");
iframe1.src = createHtml(createLink("testsize", "50x50", "icon"));
} else if (numIconChanges == 7) {
is(e.detail.href, "http://example.com/testsize.png");
is(e.detail.sizes, "50x50");
iframe1.src = createHtml(
createLink("testapple1", "100x100", "apple-touch-icon")
);
} else if (numIconChanges == 8) {
is(e.detail.href, "http://example.com/testapple1.png");
is(e.detail.rel, "apple-touch-icon");
is(e.detail.sizes, "100x100");
iframe1.src = createHtml(
createLink("testapple2", "100x100", "apple-touch-icon-precomposed")
);
} else if (numIconChanges == 9) {
is(e.detail.href, "http://example.com/testapple2.png");
is(e.detail.rel, "apple-touch-icon-precomposed");
is(e.detail.sizes, "100x100");
SimpleTest.finish();
} else {
ok(false, "Too many iconchange events.");
}
});
iframe3.addEventListener("mozbrowsericonchange", function(e) {
ok(false, "Should not get a iconchange event for iframe3.");
});
iframe1.src = createHtml(createLink("myicon"));
// We should not recieve icon change events for either of the below iframes
iframe2.src = createHtml(createLink("myicon"));
iframe3.src = createHtml(createLink("myicon"));
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,144 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that an iframe with the |mozbrowser| attribute emits mozbrowserloadX
// events when this page is in the whitelist.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
// Load emptypage1 into the iframe, wait for that to finish loading, then
// call runTest2.
//
// This should trigger loadstart, locationchange, and loadend events.
var seenLoadEnd = false;
var seenLoadStart = false;
var seenLocationChange = false;
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.id = "iframe";
iframe.src =
"http://example.com/tests/dom/browser-element/mochitest/file_browserElement_LoadEvents.html";
function loadstart(e) {
ok(e.isTrusted, "Event should be trusted.");
ok(!seenLoadEnd, "loadstart before loadend.");
ok(!seenLoadStart, "Just one loadstart event.");
ok(!seenLocationChange, "loadstart before locationchange.");
seenLoadStart = true;
}
function locationchange(e) {
ok(e.isTrusted, "Event should be trusted.");
ok(!seenLocationChange, "Just one locationchange event.");
seenLocationChange = true;
ok(seenLoadStart, "Location change after load start.");
ok(!seenLoadEnd, "Location change before load end.");
// XXX: Switched to from ok() to todo_is() in Bug 1467712. Follow up in 1503862
// Fails with: event's reported location -
// got "http://example.com/tests/dom/browser-element/mochitest/file_browserElement_LoadEvents.html",
// expected "http://example.com/tests/dom/browser-element/mochitest/file_empty.html"
todo_is(
e.detail.url,
browserElementTestHelpers.emptyPage1,
"event's reported location"
);
}
function loadend(e) {
ok(e.isTrusted, "Event should be trusted.");
ok(seenLoadStart, "loadend after loadstart.");
ok(!seenLoadEnd, "Just one loadend event.");
ok(seenLocationChange, "loadend after locationchange.");
is(
e.detail.backgroundColor,
"rgb(0, 128, 0)",
"Expected background color reported"
);
seenLoadEnd = true;
}
iframe.addEventListener("mozbrowserloadstart", loadstart);
iframe.addEventListener("mozbrowserlocationchange", locationchange);
iframe.addEventListener("mozbrowserloadend", loadend);
function waitForAllCallbacks() {
if (!seenLoadStart || !seenLoadEnd) {
SimpleTest.executeSoon(waitForAllCallbacks);
return;
}
iframe.removeEventListener("mozbrowserloadstart", loadstart);
iframe.removeEventListener("mozbrowserlocationchange", locationchange);
iframe.removeEventListener("mozbrowserloadend", loadend);
runTest2();
}
document.body.appendChild(iframe);
waitForAllCallbacks();
}
function runTest2() {
var seenLoadStart = false;
var seenLoadEnd = false;
var seenLocationChange = false;
// Add this event listener to the document; the events should bubble.
document.addEventListener("mozbrowserloadstart", function(e) {
ok(e.isTrusted, "Event should be trusted.");
ok(!seenLoadStart, "Just one loadstart event.");
seenLoadStart = true;
ok(!seenLoadEnd, "Got mozbrowserloadstart before loadend.");
ok(!seenLocationChange, "Got mozbrowserloadstart before locationchange.");
});
var iframe = document.getElementById("iframe");
iframe.addEventListener("mozbrowserlocationchange", function(e) {
ok(e.isTrusted, "Event should be trusted.");
ok(!seenLocationChange, "Just one locationchange event.");
seenLocationChange = true;
ok(seenLoadStart, "Location change after load start.");
ok(!seenLoadEnd, "Location change before load end.");
is(
e.detail.url,
browserElementTestHelpers.emptyPage2,
"event's reported location"
);
});
iframe.addEventListener("mozbrowserloadend", function(e) {
ok(e.isTrusted, "Event should be trusted.");
ok(!seenLoadEnd, "Just one load end event.");
seenLoadEnd = true;
ok(seenLoadStart, "Load end after load start.");
ok(seenLocationChange, "Load end after location change.");
is(
e.detail.backgroundColor,
"rgba(0, 0, 0, 0)",
"Expected background color reported"
);
});
iframe.src = browserElementTestHelpers.emptyPage2;
function waitForAllCallbacks() {
if (!seenLoadStart || !seenLoadEnd || !seenLocationChange) {
SimpleTest.executeSoon(waitForAllCallbacks);
return;
}
SimpleTest.finish();
}
waitForAllCallbacks();
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,198 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowsermetachange event works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function createHtml(meta) {
return (
'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' +
meta +
"<body></body></html>"
);
}
function createHtmlWithLang(meta, lang) {
return (
'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace" lang="' +
lang +
'"><head>' +
meta +
"<body></body></html>"
);
}
function createMeta(name, content) {
return '<meta name="' + name + '" content="' + content + '">';
}
function createMetaWithLang(name, content, lang) {
return (
'<meta name="' + name + '" content="' + content + '" lang="' + lang + '">'
);
}
function createMetaWithProperty(property, content) {
return '<meta property="' + property + '" content="' + content + '">';
}
function runTest() {
var iframe1 = document.createElement("iframe");
iframe1.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe1);
// iframe2 is a red herring; we modify its meta elements but don't listen for
// metachanges; we want to make sure that its metachange events aren't
// picked up by the listener on iframe1.
var iframe2 = document.createElement("iframe");
iframe2.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe2);
// iframe3 is another red herring. It's not a mozbrowser, so we shouldn't
// get any metachange events on it.
var iframe3 = document.createElement("iframe");
document.body.appendChild(iframe3);
var numMetaChanges = 0;
iframe1.addEventListener("mozbrowsermetachange", function(e) {
numMetaChanges++;
if (numMetaChanges == 1) {
is(e.detail.name, "application-name");
is(e.detail.content, "foobar");
// We should recieve metachange events when the user creates new metas
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.title='New title';",
/* allowDelayedLoad = */ false
);
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<meta name=application-name content=new_foobar>')",
/* allowDelayedLoad = */ false
);
SpecialPowers.getBrowserFrameMessageManager(iframe2).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<meta name=application-name content=new_foobar>')",
/* allowDelayedLoad = */ false
);
} else if (numMetaChanges == 2) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "new_foobar", "content matches");
ok(!("lang" in e.detail), "lang not present");
// Full new pages should trigger metachange events
iframe1.src = createHtml(createMeta("application-name", "3rd_foobar"));
} else if (numMetaChanges == 3) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "3rd_foobar", "content matches");
ok(!("lang" in e.detail), "lang not present");
// Test setting a page with multiple meta elements
iframe1.src = createHtml(
createMeta("application-name", "foobar_1") +
createMeta("application-name", "foobar_2")
);
} else if (numMetaChanges == 4) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "foobar_1", "content matches");
ok(!("lang" in e.detail), "lang not present");
// 2 events will be triggered by previous test, wait for next
} else if (numMetaChanges == 5) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "foobar_2", "content matches");
ok(!("lang" in e.detail), "lang not present");
// Test the language
iframe1.src = createHtml(
createMetaWithLang("application-name", "foobar_lang_1", "en")
);
} else if (numMetaChanges == 6) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "foobar_lang_1", "content matches");
is(e.detail.lang, "en", "language matches");
// Test the language in the ancestor element
iframe1.src = createHtmlWithLang(
createMeta("application-name", "foobar_lang_2"),
"es"
);
} else if (numMetaChanges == 7) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "foobar_lang_2", "content matches");
is(e.detail.lang, "es", "language matches");
// Test the language in the ancestor element
iframe1.src = createHtmlWithLang(
createMetaWithLang("application-name", "foobar_lang_3", "it"),
"fi"
);
} else if (numMetaChanges == 8) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "foobar_lang_3", "content matches");
is(e.detail.lang, "it", "language matches");
// Test the content-language
iframe1.src =
"http://test/tests/dom/browser-element/mochitest/file_browserElement_Metachange.sjs?ru";
} else if (numMetaChanges == 9) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "sjs", "content matches");
is(e.detail.lang, "ru", "language matches");
// Test the content-language
iframe1.src =
"http://test/tests/dom/browser-element/mochitest/file_browserElement_Metachange.sjs?ru|dk";
} else if (numMetaChanges == 10) {
is(e.detail.name, "application-name", "name matches");
is(e.detail.content, "sjs", "content matches");
is(e.detail.lang, "dk", "language matches");
// Test Open Graph property
iframe1.src = createHtml(
createMetaWithProperty("og:description", "Fascinating article")
);
// We should not get event if property doesn't start with 'og:'
iframe3.src = createHtml(
createMetaWithProperty("go:description", "Fascinating article")
);
} else if (numMetaChanges == 11) {
is(e.detail.name, "og:description", "property name matches");
is(e.detail.content, "Fascinating article", "content matches");
// Sometimes 'name' is used instead of 'property'. Verify that works.
iframe1.src = createHtml(createMeta("og:title", "One weird trick!"));
// We should not get event if property doesn't start with 'og:'
iframe3.src = createHtml(createMeta("go:title", "One weird trick!"));
} else if (numMetaChanges == 12) {
is(e.detail.name, "og:title", "property name matches");
is(e.detail.content, "One weird trick!", "content matches");
// Test the language
SimpleTest.finish();
} else {
ok(false, "Too many metachange events.");
}
});
iframe3.addEventListener("mozbrowsermetachange", function(e) {
ok(false, "Should not get a metachange event for iframe3.");
});
iframe1.src = createHtml(createMeta("application-name", "foobar"));
// We should not recieve meta change events for either of the below iframes
iframe2.src = createHtml(createMeta("application-name", "foobar"));
iframe3.src = createHtml(createMeta("application-name", "foobar"));
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,113 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowseropensearch event works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function createHtml(link) {
return "data:text/html,<html><head>" + link + "<body></body></html>";
}
function createLink(name) {
return (
'<link rel="search" title="Test OpenSearch" type="application/opensearchdescription+xml" href="http://example.com/' +
name +
'.xml">'
);
}
function runTest() {
var iframe1 = document.createElement("iframe");
iframe1.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe1);
// iframe2 is a red herring; we modify its link but don't listen for
// opensearch; we want to make sure that its opensearch events aren't
// picked up by the listener on iframe1.
var iframe2 = document.createElement("iframe");
iframe2.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe2);
// iframe3 is another red herring. It's not a mozbrowser, so we shouldn't
// get any opensearch events on it.
var iframe3 = document.createElement("iframe");
document.body.appendChild(iframe3);
var numLinkChanges = 0;
iframe1.addEventListener("mozbrowseropensearch", function(e) {
numLinkChanges++;
if (numLinkChanges == 1) {
is(e.detail.title, "Test OpenSearch");
is(e.detail.href, "http://example.com/mysearch.xml");
// We should recieve opensearch events when the user creates new links
// to a search engine, but only when we listen for them
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.title='New title';",
/* allowDelayedLoad = */ false
);
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=SEARCH type=application/opensearchdescription+xml href=http://example.com/newsearch.xml>')",
/* allowDelayedLoad = */ false
);
SpecialPowers.getBrowserFrameMessageManager(iframe2).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=SEARCH type=application/opensearchdescription+xml href=http://example.com/newsearch.xml>')",
/* allowDelayedLoad = */ false
);
} else if (numLinkChanges == 2) {
is(e.detail.href, "http://example.com/newsearch.xml");
// Full new pages should trigger opensearch events
iframe1.src = createHtml(createLink("3rdsearch"));
} else if (numLinkChanges == 3) {
is(e.detail.href, "http://example.com/3rdsearch.xml");
// the rel attribute can have various space seperated values, make
// sure we only pick up correct values for 'opensearch'
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=someopensearch type=application/opensearchdescription+xml href=http://example.com/newsearch.xml>')",
/* allowDelayedLoad = */ false
);
// Test setting a page with multiple links elements
iframe1.src = createHtml(createLink("another") + createLink("search"));
} else if (numLinkChanges == 4) {
is(e.detail.href, "http://example.com/another.xml");
// 2 events will be triggered by previous test, wait for next
} else if (numLinkChanges == 5) {
is(e.detail.href, "http://example.com/search.xml");
// Make sure opensearch check is case insensitive
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=SEARCH type=application/opensearchdescription+xml href=http://example.com/ucasesearch.xml>')",
/* allowDelayedLoad = */ false
);
} else if (numLinkChanges == 6) {
is(e.detail.href, "http://example.com/ucasesearch.xml");
SimpleTest.finish();
} else {
ok(false, "Too many opensearch events.");
}
});
iframe3.addEventListener("mozbrowseropensearch", function(e) {
ok(false, "Should not get a opensearch event for iframe3.");
});
iframe1.src = createHtml(createLink("mysearch"));
// We should not recieve opensearch change events for either of the below iframes
iframe2.src = createHtml(createLink("mysearch"));
iframe3.src = createHtml(createLink("mysearch"));
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,56 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the mozprivatebrowsing attribute works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function createFrame(aIsPrivate) {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
if (aIsPrivate) {
iframe.setAttribute("mozprivatebrowsing", "true");
}
return iframe;
}
function createTest(aIsPrivate, aExpected, aClearStorage) {
info("createTest " + aIsPrivate + " " + aExpected);
return new Promise(function(resolve, reject) {
var iframe = createFrame(aIsPrivate);
document.body.appendChild(iframe);
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
is(e.detail.message, aExpected, "Checking localstorage");
resolve();
});
var src = "file_browserElement_PrivateBrowsing.html";
iframe.src = aClearStorage ? src + "?clear=true" : src;
});
}
function runTest() {
// We first create a iframe in non private browsing mode, set up some
// localstorage, reopen it to check that we get the previously set value.
// Finally, open it in private browsing mode and check that localstorage
// is clear.
createTest(false, "CLEAR", true)
.then(() => {
return createTest(false, "EMPTY", false);
})
.then(() => {
return createTest(false, "bar", false);
})
.then(() => {
return createTest(true, "EMPTY", false);
})
.then(SimpleTest.finish);
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,65 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that alertCheck (i.e., alert with the opportunity to opt out of future
// alerts), promptCheck, and confirmCheck work. We do this by spamming
// alerts/prompts/confirms from inside an <iframe mozbrowser>.
//
// At the moment, we treat alertCheck/promptCheck/confirmCheck just like a
// normal alert. But it's different to nsIPrompt!
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
var numPrompts = 0;
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
is(e.detail.message, String(numPrompts), "prompt message");
if (numPrompts / 10 < 1) {
is(e.detail.promptType, "alert");
} else if (numPrompts / 10 < 2) {
is(e.detail.promptType, "confirm");
} else {
is(e.detail.promptType, "prompt");
}
numPrompts++;
if (numPrompts == 30) {
SimpleTest.finish();
}
});
/* eslint-disable no-useless-concat */
iframe.src =
'data:text/html,<html><body><script>\
addEventListener("load", function() { \
setTimeout(function() { \
var i = 0; \
for (; i < 10; i++) { alert(i); } \
for (; i < 20; i++) { confirm(i); } \
for (; i < 30; i++) { prompt(i); } \
}); \
}); \
</scr' +
"ipt></body></html>";
/* eslint-enable no-useless-concat */
}
// The test harness sets dom.successive_dialog_time_limit to 0 for some bizarre
// reason. That's not normal usage, and it keeps us from testing alertCheck!
addEventListener("testready", function() {
SpecialPowers.pushPrefEnv(
{ set: [["dom.successive_dialog_time_limit", 10]] },
runTest
);
});

View File

@ -0,0 +1,99 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that prompt and confirm work. In particular, we're concerned that we
// get correct return values out of them.
//
// We use alert() to communicate the return values of prompt/confirm back to
// ourselves.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
var prompts = [
{ msg: "1", type: "alert", rv: 42, expected: "undefined" },
{ msg: "2", type: "confirm", rv: true, expected: "true" },
{ msg: "3", type: "confirm", rv: false, expected: "false" },
// rv == 42 should be coerced to 'true' for confirm.
{ msg: "4", type: "confirm", rv: 42, expected: "true" },
{ msg: "5", type: "prompt", rv: "worked", expected: "worked" },
{ msg: "6", type: "prompt", rv: null, expected: "null" },
{ msg: "7", type: "prompt", rv: "", expected: "" },
];
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
var curPrompt = prompts[0];
if (!curPrompt.waitingForResponse) {
curPrompt.waitingForResponse = true;
is(e.detail.message, curPrompt.msg, "prompt message");
is(e.detail.promptType, curPrompt.type, "prompt type");
if (e.detail.promptType == "prompt") {
ok(
e.detail.returnValue === null,
"prompt's returnValue should be null"
);
is(e.detail.initialValue, "initial", "prompt's initial value.");
} else {
ok(
e.detail.returnValue === undefined,
"Other than for prompt, shouldn't have initial value."
);
}
// Block the child until we call e.detail.unblock().
e.preventDefault();
SimpleTest.executeSoon(function() {
e.detail.returnValue = curPrompt.rv;
e.detail.unblock();
});
} else {
prompts.shift();
// |e| now corresponds to an alert() containing the return value we just
// sent for this prompt.
is(
e.detail.message,
"RESULT:" + curPrompt.expected,
"expected rv for msg " + curPrompt.msg
);
if (prompts.length == 0) {
SimpleTest.finish();
}
}
});
/* eslint-disable no-useless-concat */
iframe.src =
'data:text/html,<html><body><script>\
function sendVal(val) { \
alert("RESULT:" + val); \
} \
sendVal(alert("1")); \
sendVal(confirm("2")); \
sendVal(confirm("3")); \
sendVal(confirm("4")); \
sendVal(prompt("5", "initial")); \
sendVal(prompt("6", "initial")); \
sendVal(prompt("7", "initial")); \
</scr' +
"ipt></body></html>";
/* eslint-enable no-useless-concat */
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,63 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 741717 - Test the reload ability of <iframe mozbrowser>.
"use strict";
/* global browserElementTestHelpers */
/* eslint-env mozilla/frame-script */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
var iframeScript = function() {
sendAsyncMessage("test:innerHTML", {
data: XPCNativeWrapper.unwrap(content).document.body.innerHTML,
});
};
var mm;
var iframe;
var loadedEvents = 0;
var countAcc;
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.addEventListener("mozbrowserloadend", mozbrowserLoaded);
iframe.src = "file_bug741717.sjs";
document.body.appendChild(iframe);
}
function iframeBodyRecv(data) {
data = SpecialPowers.wrap(data);
var previousCount = countAcc;
var currentCount = parseInt(data.json.data, 10);
countAcc = currentCount;
switch (loadedEvents) {
case 1:
iframe.reload();
break;
case 2:
ok(true, "reload was triggered");
ok(previousCount === currentCount, "reload was a soft reload");
iframe.reload(true);
break;
case 3:
ok(currentCount > previousCount, "reload was a hard reload");
SimpleTest.finish();
}
}
function mozbrowserLoaded() {
loadedEvents++;
mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.addMessageListener("test:innerHTML", iframeBodyRecv);
mm.loadFrameScript("data:,(" + iframeScript.toString() + ")();", false);
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,122 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 793644, fire an event when attempting to reloads browser element after
// POST respest.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
browserElementTestHelpers.setEnabledPref(true);
var iframe;
var gotConfirmRepost = false;
var doRepost = true;
var timer;
var isPostRequestSubmitted;
function getExpectedStrings() {
let result = {};
let appBundle = Services.strings.createBundle(
"chrome://global/locale/appstrings.properties"
);
let brandBundle = Services.strings.createBundle(
"chrome://branding/locale/brand.properties"
);
try {
let brandName = brandBundle.GetStringFromName("brandShortName");
result.message = appBundle.formatStringFromName("confirmRepostPrompt", [
brandName,
]);
} catch (e) {
// for the case that we don't have brandShortName
result.message = appBundle.GetStringFromName("confirmRepostPrompt");
}
result.resend = appBundle.GetStringFromName("resendButton.label");
return result;
}
function failBecauseReloaded() {
window.clearTimeout(timer);
timer = null;
iframe.removeEventListener("mozbrowserloadend", failBecauseReloaded);
ok(false, "We don't expect browser element to reload, but it did");
SimpleTest.finish();
}
function reloadDone() {
iframe.removeEventListener("mozbrowserloadend", reloadDone);
ok(gotConfirmRepost, "Didn't get confirmEx prompt before reload");
// Run again, with repost disallowed.
doRepost = false;
isPostRequestSubmitted = false;
iframe.src = "file_post_request.html";
iframe.addEventListener("mozbrowserloadend", pageLoadDone);
}
function pageLoadDone() {
if (!isPostRequestSubmitted) {
// This loadend is done by setting url in address bar, so we don't need to
// do anything. The test page will submit a POST request.
isPostRequestSubmitted = true;
return;
}
gotConfirmRepost = false;
iframe.removeEventListener("mozbrowserloadend", pageLoadDone);
if (doRepost) {
iframe.addEventListener("mozbrowserloadend", reloadDone);
} else {
// We don't expect browserelement to reload; use a timer to make sure
// it is not reloaded.
iframe.addEventListener("mozbrowserloadend", failBecauseReloaded);
}
iframe.reload();
}
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
isPostRequestSubmitted = false;
iframe.src = "file_post_request.html";
document.body.appendChild(iframe);
iframe.addEventListener("mozbrowserloadend", pageLoadDone);
let expectedMessage = getExpectedStrings();
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
if (e.detail.promptType == "custom-prompt") {
gotConfirmRepost = true;
e.preventDefault();
e.detail.returnValue = {
selectedButton: doRepost ? 0 : 1,
};
is(e.detail.returnValue.checked, undefined);
is(e.detail.buttons[0].messageType, "custom");
is(e.detail.buttons[0].message, expectedMessage.resend);
is(e.detail.buttons[1].messageType, "builtin");
is(e.detail.buttons[1].message, "cancel");
is(e.detail.message, expectedMessage.message);
is(e.detail.buttons.length, 2);
is(e.detail.showCheckbox, false);
is(e.detail.checkboxMessage, null);
e.detail.unblock();
if (!doRepost) {
// To make sure the page doesn't reload in 1 sec.
timer = window.setTimeout(function() {
iframe.removeEventListener("mozbrowserloadend", failBecauseReloaded);
SimpleTest.finish();
}, 1000);
}
}
});
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 787517: Remove iframe in the handler of showmodalprompt. This shouldn't
// cause an exception to be thrown.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
document.body.removeChild(iframe);
SimpleTest.executeSoon(function() {
ok(true);
SimpleTest.finish();
});
});
iframe.src =
'data:text/html,<html><body><script>alert("test")</script>' +
"</body></html>";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that scroll event bubbles up.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
iframe.addEventListener("mozbrowserscroll", function(e) {
ok(true, "got mozbrowserscroll event.");
ok(e.detail, "event.detail is not null.");
is(Math.round(e.detail.top), 4000, "top position is correct.");
is(Math.round(e.detail.left), 4000, "left position is correct.");
SimpleTest.finish();
});
// We need a viewport meta tag to allow us to scroll to (4000, 4000). Without
// the viewport meta tag, we shrink the (5000, 5000) content so that we can't
// have enough space to scroll to the point in the layout viewport.
iframe.src =
"data:text/html,<html><meta name='viewport' content='width=device-width,minimum-scale=1,initial-scale=1'><body style='min-height: 5000px; min-width: 5000px;'></body><script>window.scrollTo(4000, 4000);</script></html>";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,66 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 763694 - Test that <iframe mozbrowser> delivers proper
// mozbrowsersecuritychange events.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
var lastSecurityState;
iframe.addEventListener("mozbrowsersecuritychange", function(e) {
lastSecurityState = e.detail;
});
var filepath =
"tests/dom/browser-element/mochitest/file_browserElement_SecurityChange.html";
var count = 0;
iframe.addEventListener("mozbrowserloadend", function(e) {
count++;
switch (count) {
case 1:
is(lastSecurityState.state, "secure");
is(lastSecurityState.extendedValidation, false);
is(lastSecurityState.mixedContent, false);
iframe.src = "http://example.com/" + filepath;
break;
case 2:
is(lastSecurityState.state, "insecure");
is(lastSecurityState.extendedValidation, false);
is(lastSecurityState.mixedContent, false);
iframe.src = "https://example.com:443/" + filepath + "?broken";
break;
case 3:
is(lastSecurityState.state, "broken");
is(lastSecurityState.extendedValidation, false);
is(lastSecurityState.mixedContent, true);
SimpleTest.finish();
break;
}
});
iframe.src = "https://example.com/" + filepath;
document.body.appendChild(iframe);
}
addEventListener("testready", function() {
SpecialPowers.pushPrefEnv(
{
set: [
["browser.safebrowsing.phishing.enabled", false],
["browser.safebrowsing.malware.enabled", false],
],
},
runTest
);
});

View File

@ -0,0 +1,60 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that sendMouseEvent dispatch events.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
var x = 10;
var y = 10;
// This test used to try to transform the coordinates from child
// to parent coordinate space by first calling
// iframe.getBoundingClientRect();
// to refresh offsets and then calling
// var remoteTab = SpecialPowers.wrap(iframe)
// .frameLoader.remoteTab;
// and calling remoteTab.getChildProcessOffset(offsetX, offsetY) if
// remoteTab was not null, but remoteTab was always null.
iframe.addEventListener("mozbrowserloadend", function onloadend(e) {
// Ensure we lay out the iframe before sending mouse events.
iframe.getBoundingClientRect();
iframe.sendMouseEvent("mousedown", x, y, 0, 1, 0);
});
iframe.addEventListener("mozbrowserlocationchange", function onlocchange(e) {
var a = document.createElement("a");
a.href = e.detail.url;
switch (a.hash) {
case "#mousedown":
ok(true, "Receive a mousedown event.");
iframe.sendMouseEvent("mousemove", x, y, 0, 0, 0);
break;
case "#mousemove":
ok(true, "Receive a mousemove event.");
iframe.sendMouseEvent("mouseup", x, y, 0, 1, 0);
break;
case "#mouseup":
ok(true, "Receive a mouseup event.");
break;
case "#click":
ok(true, "Receive a click event.");
iframe.removeEventListener("mozbrowserlocationchange", onlocchange);
SimpleTest.finish();
break;
}
});
iframe.src = "file_browserElement_SendEvent.html";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,59 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 709759 - Test the stop ability of <iframe mozbrowser>.
// The img that is loaded will never be returned and will block
// the page from loading, the timeout ensures that the page is
// actually blocked from loading, once stop is called the
// image load will be cancaelled and mozbrowserloadend should be called.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
browserElementTestHelpers.setEnabledPref(true);
var iframe;
var stopped = false;
var imgSrc =
"http://test/tests/dom/browser-element/mochitest/file_bug709759.sjs";
function runTest() {
iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
// FIXME: Bug 1270790
iframe.setAttribute("remote", "true");
iframe.addEventListener("mozbrowserloadend", loadend);
iframe.src =
"data:text/html,<html>" +
'<body><img src="' +
imgSrc +
'" /></body></html>';
document.body.appendChild(iframe);
setTimeout(function() {
stopped = true;
iframe.stop();
}, 200);
}
function loadend() {
ok(stopped, "Iframes network connections were stopped");
// Wait 1 second and make sure there isn't a mozbrowsererror after stop();
iframe.addEventListener("mozbrowsererror", handleError);
window.setTimeout(function() {
iframe.removeEventListener("mozbrowsererror", handleError);
SimpleTest.finish();
}, 1000);
}
function handleError() {
ok(false, "mozbrowsererror should not be fired");
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,88 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowsermetachange event for theme-color works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
function loadFrameScript(script) {
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:," + script,
/* allowDelayedLoad = */ false
);
}
let iframe1 = document.createElement("iframe");
iframe1.setAttribute("mozbrowser", "true");
iframe1.src =
"http://test/tests/dom/browser-element/mochitest/file_browserElement_ThemeColor.html";
iframe1.addEventListener("mozbrowsermetachange", tests);
document.body.appendChild(iframe1);
let numMetaChanges = 0;
function tests(e) {
let detail = e.detail;
switch (numMetaChanges++) {
case 0: {
is(detail.name, "theme-color", "name matches");
is(detail.content, "pink", "content matches");
is(detail.type, "added", "type matches");
let script =
"var meta = content.document.head.querySelector('meta');" +
"meta.content = 'green';";
loadFrameScript(script);
break;
}
case 1: {
is(detail.name, "theme-color", "name matches");
is(detail.content, "green", "content matches");
is(detail.type, "changed", "type matches");
let script =
"var meta = content.document.createElement('meta');" +
"meta.name = 'theme-group';" +
"meta.content = 'theme-productivity';" +
"content.document.head.appendChild(meta)";
loadFrameScript(script);
break;
}
case 2: {
is(detail.name, "theme-group", "name matches");
is(detail.content, "theme-productivity", "content matches");
is(detail.type, "added", "type matches");
let script =
"var meta = content.document.head.querySelector('meta');" +
"meta.parentNode.removeChild(meta);";
loadFrameScript(script);
break;
}
case 3: {
is(detail.name, "theme-color", "name matches");
is(detail.content, "green", "content matches");
is(detail.type, "removed", "type matches");
SimpleTest.finish();
break;
}
default: {
ok(false, "Too many metachange events.");
break;
}
}
}
}
window.addEventListener("testready", runTest);

View File

@ -0,0 +1,75 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowsertitlechange event works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
function runTest() {
var iframe1 = document.createElement("iframe");
iframe1.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe1);
// iframe2 is a red herring; we modify its title but don't listen for
// titlechanges; we want to make sure that its titlechange events aren't
// picked up by the listener on iframe1.
var iframe2 = document.createElement("iframe");
iframe2.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe2);
// iframe3 is another red herring. It's not a mozbrowser, so we shouldn't
// get any titlechange events on it.
var iframe3 = document.createElement("iframe");
document.body.appendChild(iframe3);
var numTitleChanges = 0;
iframe1.addEventListener("mozbrowsertitlechange", function(e) {
// Ignore empty titles; these come from about:blank.
if (e.detail == "") {
return;
}
numTitleChanges++;
if (numTitleChanges == 1) {
is(e.detail, "Title");
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:,content.document.title='New title';",
/* allowDelayedLoad = */ false
);
SpecialPowers.getBrowserFrameMessageManager(iframe2).loadFrameScript(
"data:,content.document.title='BAD TITLE 2';",
/* allowDelayedLoad = */ false
);
} else if (numTitleChanges == 2) {
is(e.detail, "New title");
iframe1.src =
"data:text/html,<html><head><title>Title 3</title></head><body></body></html>";
} else if (numTitleChanges == 3) {
is(e.detail, "Title 3");
SimpleTest.finish();
} else {
ok(false, "Too many titlechange events.");
}
});
iframe3.addEventListener("mozbrowsertitlechange", function(e) {
ok(false, "Should not get a titlechange event for iframe3.");
});
iframe1.src =
"data:text/html,<html><head><title>Title</title></head><body></body></html>";
iframe2.src =
"data:text/html,<html><head><title>BAD TITLE</title></head><body></body></html>";
iframe3.src =
"data:text/html,<html><head><title>SHOULD NOT GET EVENT</title></head><body></body></html>";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,87 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that an <iframe mozbrowser> is a window.{top,parent,frameElement} barrier.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
browserElementTestHelpers.allowTopLevelDataURINavigation();
var iframe;
function runTest() {
iframe = document.createElement("iframe");
iframe.addEventListener("mozbrowserloadend", function() {
try {
outerIframeLoaded();
} catch (e) {
dump("Got error: " + e + "\n");
}
});
iframe.setAttribute("mozbrowser", "true");
iframe.src =
'data:text/html,Outer iframe <iframe id="inner-iframe"></iframe>';
// For kicks, this test uses a display:none iframe. This shouldn't make a
// difference in anything.
iframe.style.display = "none";
document.body.appendChild(iframe);
}
var numMsgReceived = 0;
function outerIframeLoaded() {
// If you're changing the amount of is() calls in injectedScript,
// also change the number in waitForMessages accordingly
var injectedScript =
"data:,function is(a, b, desc) { \
if (a == b) { \
sendAsyncMessage('test:test-pass', desc); \
} else { \
sendAsyncMessage('test:test-fail', desc + ' ' + a + ' != ' + b); \
} \
} \
is(content.window.top, content.window, 'top'); \
is(content.window.content, content.window, 'content'); \
is(content.window.parent, content.window, 'parent'); \
is(content.window.frameElement, null, 'frameElement'); \
var innerIframe = content.document.getElementById('inner-iframe'); \
var innerWindow = innerIframe.contentWindow; \
is(innerWindow.top, content.window, 'inner top'); \
is(innerWindow.content, content.window, 'inner content'); \
is(innerWindow.parent, content.window, 'inner parent'); \
is(innerWindow.frameElement, innerIframe, 'inner frameElement');";
var mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
function onRecvTestPass(msg) {
numMsgReceived++;
ok(true, msg.json);
}
mm.addMessageListener("test:test-pass", onRecvTestPass);
function onRecvTestFail(msg) {
numMsgReceived++;
ok(false, msg.json);
}
mm.addMessageListener("test:test-fail", onRecvTestFail);
mm.loadFrameScript(injectedScript, /* allowDelayedLoad = */ false);
// 8 is the number of is() calls in injectedScript
waitForMessages(8);
}
function waitForMessages(num) {
if (numMsgReceived < num) {
SimpleTest.executeSoon(function() {
waitForMessages(num);
});
return;
}
SimpleTest.finish();
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,74 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowsermetachange event for viewmode works.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
function loadFrameScript(script) {
SpecialPowers.getBrowserFrameMessageManager(iframe1).loadFrameScript(
"data:," + script,
/* allowDelayedLoad = */ false
);
}
let iframe1 = document.createElement("iframe");
iframe1.setAttribute("mozbrowser", "true");
iframe1.src =
"http://test/tests/dom/browser-element/mochitest/file_browserElement_Viewmode.html";
iframe1.addEventListener("mozbrowsermetachange", tests);
document.body.appendChild(iframe1);
let numMetaChanges = 0;
function tests(e) {
let detail = e.detail;
switch (numMetaChanges++) {
case 0: {
is(detail.name, "viewmode", "name matches");
is(detail.content, "projection=stereo", "content matches");
is(detail.type, "added", "type matches");
let script =
"var meta = content.document.head.querySelector('meta');" +
"meta.content = 'projection=mono';";
loadFrameScript(script);
break;
}
case 1: {
is(detail.name, "viewmode", "name matches");
is(detail.content, "projection=mono", "content matches");
is(detail.type, "changed", "type matches");
let script =
"var meta = content.document.head.querySelector('meta');" +
"meta.parentNode.removeChild(meta);";
loadFrameScript(script);
break;
}
case 2: {
is(detail.name, "viewmode", "name matches");
is(detail.content, "projection=mono", "content matches");
is(detail.type, "removed", "type matches");
SimpleTest.finish();
break;
}
default: {
ok(false, "Too many metachange events.");
break;
}
}
}
}
window.addEventListener("testready", runTest);

View File

@ -0,0 +1,28 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 770239 - Test that we can load pages with X-Frame-Options: Deny inside
// <iframe mozbrowser>.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
// The page we load will fire an alert when it successfully loads.
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
ok(true, "Got alert");
SimpleTest.finish();
});
document.body.appendChild(iframe);
iframe.src = "file_browserElement_XFrameOptions.sjs?DENY";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,69 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 770239 - Test that X-Frame-Options will correctly block a page inside a
// subframe of <iframe mozbrowser>.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
var initialScreenshotArrayBuffer;
function arrayBuffersEqual(a, b) {
var x = new Int8Array(a);
var y = new Int8Array(b);
if (x.length != y.length) {
return false;
}
for (var i = 0; i < x.length; i++) {
if (x[i] != y[i]) {
return false;
}
}
return true;
}
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
// Our child will create two iframes, so make sure this iframe is big enough
// to show both of them without scrolling, so taking a screenshot gets both
// frames.
iframe.height = "1000px";
var step1, stepfinish;
iframe.addEventListener("mozbrowsershowmodalprompt", async function(e) {
switch (e.detail.message) {
case "step 1":
step1 = await SpecialPowers.snapshotWindow(iframe.contentWindow);
break;
case "step 2":
// The page has now attempted to load the X-Frame-Options page; take
// another screenshot.
stepfinish = await SpecialPowers.snapshotWindow(iframe.contentWindow);
ok(
step1.toDataURL() == stepfinish.toDataURL(),
"Screenshots should be identical"
);
SimpleTest.finish();
break;
}
});
document.body.appendChild(iframe);
// Load this page from a different origin than ourselves. This page will, in
// turn, load a child from mochi.test:8888, our origin, with X-Frame-Options:
// SAMEORIGIN. That load should be denied.
iframe.src =
"http://example.com/tests/dom/browser-element/mochitest/file_browserElement_XFrameOptionsDeny.html";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,31 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 770239 - Load an X-Frame-Options: SAMEORIGIN page inside an <iframe>
// inside <iframe mozbrowser>. The two iframes will have the same origin, but
// this page will be of a different origin. The load should succeed.
"use strict";
/* global browserElementTestHelpers */
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
var iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
// The innermost page we load will fire an alert when it successfully loads.
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
ok(true, "Got alert");
SimpleTest.finish();
});
document.body.appendChild(iframe);
iframe.src =
"http://example.com/tests/dom/browser-element/mochitest/file_browserElement_XFrameOptionsSameOrigin.html";
}
addEventListener("testready", runTest);

View File

@ -0,0 +1,24 @@
[DEFAULT]
skip-if = e10s
support-files =
audio.ogg
async.js
browserElementTestHelpers.js
browserElement_BackForward.js
browserElement_DocumentFirstPaint.js
browserElement_ReloadPostRequest.js
browserElement_SendEvent.js
browserElement_Stop.js
file_browserElement_SendEvent.html
file_bug709759.sjs
file_empty.html
file_post_request.html
[test_browserElement_inproc_BackForward.html]
[test_browserElement_inproc_DocumentFirstPaint.html]
[test_browserElement_inproc_ReloadPostRequest.html]
disabled = no modal prompt on POST reload for chrome window
[test_browserElement_inproc_SendEvent.html]
[test_browserElement_inproc_Stop.html]
skip-if = (os == "win" && !debug) #Bug 1345410

View File

@ -0,0 +1,126 @@
"""A script to generate the browser-element test boilerplate.
This script requires Python 2.7."""
from __future__ import print_function
import sys
import os
import stat
import argparse
import textwrap
import subprocess
html_template = textwrap.dedent("""\
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug {bug}</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript" src="browserElement_{test}.js">
</script>
</body>
</html>""")
# Note: Curly braces are escaped as "{{".
js_template = textwrap.dedent("""\
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug {bug} - FILL IN TEST DESCRIPTION
"use strict";
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {{
var iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
// FILL IN TEST
document.body.appendChild(iframe);
}}
addEventListener('testready', runTest);
""")
def print_fill(s):
print(textwrap.fill(textwrap.dedent(s)))
def add_to_ini(filename, test, support_file=None):
"""Add test to mochitest config {filename}, then open
$EDITOR and let the user move the filenames to their appropriate
places in the file.
"""
lines_to_write = ['[{0}]'.format(test)]
if support_file:
lines_to_write += ['support-files = {0}'.format(support_file)]
lines_to_write += ['']
with open(filename, 'a') as f:
f.write('\n'.join(lines_to_write))
if 'EDITOR' not in os.environ or not os.environ['EDITOR']:
print_fill("""\
Now open {filename} and move the filenames to their correct places.")
(Define $EDITOR and I'll open your editor for you next time.)""".format(filename=filename))
return
# Count the number of lines in the file
with open(filename, 'r') as f:
num_lines = len(f.readlines())
try:
subprocess.call([os.environ['EDITOR'],
'+%d' % (num_lines - len(lines_to_write) + 2),
filename])
except Exception as e:
print_fill("Error opening $EDITOR: {0}.".format(e))
print()
print_fill("""\
Please open {filename} and move the filenames at the bottom of the
file to their correct places.""".format(filename=filename))
def main(test_name, bug_number):
global html_template, js_template
def format(str):
return str.format(bug=bug_number, test=test_name)
def create_file(filename, template):
path = os.path.join(os.path.dirname(sys.argv[0]), format(filename))
# Create a new file, bailing with an error if the file exists.
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
try:
# This file has 777 permission when created, for whatever reason. Make it rw-rw-r---.
os.fchmod(fd, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH)
except:
# fchmod doesn't work on Windows.
pass
with os.fdopen(fd, 'w') as file:
file.write(format(template))
create_file('browserElement_{test}.js', js_template)
create_file('test_browserElement_inproc_{test}.html', html_template)
create_file('test_browserElement_oop_{test}.html', html_template)
add_to_ini('mochitest.ini',
format('test_browserElement_inproc_{test}.html'),
format('browserElement_{test}.js'))
add_to_ini('mochitest-oop.ini',
format('test_browserElement_oop_{test}.html'))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Create a new browser-element testcase.")
parser.add_argument('test_name')
parser.add_argument('bug_number', type=int)
args = parser.parse_args()
main(args.test_name, args.bug_number)

View File

@ -0,0 +1,6 @@
<html>
<body>
I'm file_browserElement_AlertInFrame.html.
<iframe src='file_browserElement_AlertInFrame_Inner.html'></iframe>
<body>
</html>

View File

@ -0,0 +1,12 @@
<html>
<body>
I'm file_browserElement_AlertInFrame_Inner.html.
<script>
addEventListener("load", function() {
alert("Hello");
});
</script>
</body>
</html>

View File

@ -0,0 +1,23 @@
<html>
<body>
file_browserElement_CookiesNotThirdParty.html
<script type='text/javascript'>
if (location.search != "?step=2") {
// Step 1: Set a cookie.
document.cookie = "file_browserElement_CookiesNotThirdParty";
alert("next");
} else {
// Step 2: Read the cookie.
if (document.cookie == "file_browserElement_CookiesNotThirdParty") {
alert("success: got the correct cookie");
} else {
alert('failure: got unexpected cookie: "' + document.cookie + '"');
}
alert("finish");
}
</script>
</body>
</html>

View File

@ -0,0 +1,14 @@
<html>
<body>
<script>
if (window.name == "foo") {
alert("success:window.name == 'foo'");
} else {
alert("failure:window.name == '" + window.name + "', expected 'foo'");
}
window.open("file_browserElement_ForwardName.html#finish", "foo");
</script>
</body>
</html>

View File

@ -0,0 +1,15 @@
<html>
<body style="background-color:green;">
<!-- Tests rely on the fact that there's an element in here called 'url' and
that there's visible text on the page. -->
Aloha! My URL is <span id='url'></span>.
<script>
// eslint-disable-next-line no-unsanitized/property
document.getElementById("url").innerHTML = window.location;
</script>
</body>
</html>

View File

@ -0,0 +1,7 @@
function handleRequest(request, response)
{
var p = request.queryString.split('|');
response.setHeader('Content-Language', p[0], false);
response.write('<html><head><meta name="application-name" content="sjs"' +
(p.length > 1 ? (' lang="' + p[1] + '"') : '') + '></head><body></body></html>');
}

View File

@ -0,0 +1,15 @@
<html>
<body>
<script>
if (location.href.includes("clear=true")) {
localStorage.removeItem("foo");
alert("CLEAR");
} else {
var initialValue = localStorage.getItem("foo") || "EMPTY";
localStorage.setItem("foo", "bar");
alert(initialValue);
}
</script>
</body>
</html>

View File

@ -0,0 +1,17 @@
<html>
<head>
<script>
if (location.search === "?broken") {
// Load something non-https.
var s = document.createElement("script");
s.src = "http://example.com/dom/browser-element/mochitest/file_empty_script.js";
document.head.appendChild(s);
}
</script>
</head>
<body>
file_browserElement_SecurityChange.html.
</body>
</html>

View File

@ -0,0 +1,11 @@
<html><body>
<button>sendMouseEvent</button>
</body><script>
function changeHash(e) {
document.location.hash = e.type;
}
window.addEventListener("mousedown", changeHash);
window.addEventListener("mousemove", changeHash);
window.addEventListener("mouseup", changeHash);
window.addEventListener("click", changeHash, true);
</script></html>

View File

@ -0,0 +1,2 @@
<input autofocus value="hello" />
<p>This is targetted mozbrowser frame.</p>

View File

@ -0,0 +1,18 @@
<html>
<body>
<script>
var name = location.search.substring(1);
addEventListener("load", function() {
setTimeout(function() {
alert(name + ":ready");
}, 0);
});
addEventListener("visibilitychange", function() {
alert(name + ":" + (document.hidden ? "hidden" : "visible"));
});
</script>
</body>
</html>

View File

@ -0,0 +1,8 @@
<html>
<head>
<meta name="theme-color" content="pink">
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,8 @@
<html>
<head>
<meta name="viewmode" content="projection=stereo">
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,9 @@
function handleRequest(request, response)
{
response.setHeader("X-Frame-Options", request.queryString, false);
response.setHeader("Content-Type", "text/html", false);
// Tests rely on this page not being entirely blank, because they take
// screenshots to determine whether this page was loaded.
response.write("<html><body>XFrameOptions test<script>alert('finish')</script></body></html>");
}

View File

@ -0,0 +1,39 @@
<html>
<body>
<!-- Try to load in a frame a cross-origin page which sends:
"X-Frame-Options: Allow-From http://mochi.test:8888/",
and a cross-origin page which sends
"X-Frame-Options: Allow-From http://example.com/". -->
<script>
// Make sure these iframes aren't too tall; they both need to fit inside the
// iframe this page is contained in, without scrolling, in order for the test's
// screenshots to work properly.
var frame_src = "http://example.com/tests/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.sjs";
var iframe1 = document.createElement("iframe");
iframe1.height = "300px";
var iframe2 = document.createElement("iframe");
iframe2.height = "300px";
document.body.appendChild(iframe1);
iframe1.addEventListener("load", function() {
// This causes our embedder to take a screenshot (and blocks until the
// screenshot is completed).
iframe2.addEventListener("load", function() {
alert("finish");
}, {once: true});
document.body.appendChild(iframe2);
iframe2.src = frame_src;
}, {once: true});
iframe1.src = frame_src + "?iframe1";
</script>
</body>
</html>

View File

@ -0,0 +1,16 @@
function handleRequest(request, response)
{
var content = 'step 1';
if (request.queryString == "iframe1") {
response.setHeader("X-Frame-Options", "Allow-From http://mochi.test:8888/")
content = 'finish';
} else {
response.setHeader("X-Frame-Options", "Allow-From http://example.com")
}
response.setHeader("Content-Type", "text/html", false);
// Tests rely on this page not being entirely blank, because they take
// screenshots to determine whether this page was loaded.
response.write("<html><body>XFrameOptions test<script>alert('" + content + "')</script></body></html>");
}

View File

@ -0,0 +1,55 @@
<html>
<body>
<!-- Try to load in a frame a page which sends "X-Frame-Options: DENY", and a
cross-origin page which sends "X-Frame-Options: SAMEORIGIN". -->
<script>
// Make sure these iframes aren't too tall; they both need to fit inside the
// iframe this page is contained in, without scrolling, in order for the test's
// screenshots to work properly.
var iframe1 = document.createElement("iframe");
iframe1.height = "300px";
var iframe2 = document.createElement("iframe");
iframe2.height = "300px";
document.body.appendChild(iframe1);
document.body.appendChild(iframe2);
// This causes our embedder to take a screenshot (and blocks until the
// screenshot is completed).
alert("step 1");
// Wait for both iframes to load.
var iframe1Loaded = false;
iframe1.addEventListener("load", function() {
iframe1Loaded = true;
waitForBothLoads();
}, {once: true});
var iframe2Loaded = false;
iframe2.addEventListener("load", function() {
iframe2Loaded = true;
waitForBothLoads();
}, {once: true});
function waitForBothLoads() {
if (iframe1Loaded && iframe2Loaded) {
setTimeout(function() {
// This causes our embedder to take another screenshot.
alert("step 2");
}, 0);
}
}
iframe1.src = "file_browserElement_XFrameOptions.sjs?DENY";
// Load iframe2 with the origin of our parent. Since we have a different
// origin and are inside <iframe mozbrowser>, this should not load.
iframe2.src = "http://mochi.test:8888/tests/dom/browser-element/mochitest/file_browserElement_XFrameOptions.sjs?SAMEORIGIN";
</script>
</body>
</html>

View File

@ -0,0 +1,5 @@
<html>
<body>
<iframe src='file_browserElement_XFrameOptions.sjs?SAMEORIGIN'></iframe>
</body>
</html>

View File

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.processAsync();
response.setHeader("Content-Type", "image/jpeg", false);
}

View File

@ -0,0 +1,27 @@
function handleRequest(request, response)
{
function etag(count) {
return '"anetag' + count + '"';
}
var count = parseInt(getState('count'));
if (!count)
count = 0;
// reload(false) will make a request with If-None-Match headers
var ifNoneMatch = request.hasHeader("If-None-Match") ?
request.getHeader("If-None-Match") : "";
if (ifNoneMatch === etag(count)) {
response.setStatusLine(request.httpVersion, "304", "Not Modified");
return;
}
count++;
setState('count', count + '');
response.setHeader('Content-Type', 'text/html', false);
response.setHeader('Cache-Control', 'public, max-age=3600', false);
response.setHeader("ETag", etag(count), false);
response.write('<html><body>' + count + '</body></html>');
}

View File

@ -0,0 +1,15 @@
<html>
<body>
<!-- Tests rely on the fact that there's an element in here called 'url' and
that there's visible text on the page. -->
Aloha! My URL is <span id='url'></span>.
<script>
// eslint-disable-next-line no-unsanitized/property
document.getElementById("url").innerHTML = window.location;
</script>
</body>
</html>

View File

@ -0,0 +1,24 @@
<html>
<body>
Aloha! My URL is <span id='url'></span>.
<script>
// eslint-disable-next-line no-unsanitized/property
document.getElementById("url").innerHTML = window.location;
</script>
<script>
// The input element is getting synthesized key events and will prevent
// default on the first ESC keydown event.
var alreadyBlocked = false;
addEventListener("keydown", function(e) {
if (e.keyCode == KeyboardEvent.DOM_VK_ESCAPE && !alreadyBlocked) {
alreadyBlocked = true;
e.preventDefault();
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,16 @@
function handleRequest(request, response)
{
var auth = "";
try {
auth = request.getHeader("Authorization");
} catch(e) {}
if (auth == "Basic aHR0cHVzZXI6aHR0cHBhc3M=") {
response.setStatusLine("1.1", 200, "OK");
response.write("<html><head><title>http auth success</title></head><html>");
} else {
response.setStatusLine("1.1", 401, "Http authentication required");
response.setHeader("WWW-Authenticate", "Basic realm=\"http_realm\"");
response.write("<html><head><title>http auth failed</title></head><html>");
}
}

View File

@ -0,0 +1,16 @@
function handleRequest(request, response)
{
var auth = "";
try {
auth = request.getHeader("Proxy-Authorization");
} catch(e) {}
if (auth == "Basic cHJveHl1c2VyOnByb3h5cGFzcw==") {
response.setStatusLine("1.1", 200, "OK");
response.write("<html><head><title>http auth success</title></head><html>");
} else {
response.setStatusLine("1.1", 407, "Proxy Authentication Required");
response.setHeader("Proxy-Authenticate", "Basic realm=\"http_realm\"");
response.write("<html><head><title>http auth failed</title></head><html>");
}
}

View File

@ -0,0 +1,15 @@
<html>
<head>
<script>
addEventListener("load", function() {
document.getElementsByTagName("form")[0].submit();
});
</script>
</head>
<body>
<form action="file_empty.html" method="POST">
<input type="text" name="postvalue" value="I am a test string!!" />
<input type="submit" />
</form>
</body>
</html>

View File

@ -0,0 +1,55 @@
[DEFAULT]
# FIXME(bz, bug 1504026): now that we're not testing OpenMixedProcess,
# can we reenable these tests on Android and e10s?
skip-if = os == "android" || e10s
[test_browserElement_oop_Viewmode.html]
[test_browserElement_oop_ThemeColor.html]
[test_browserElement_inproc_ErrorSecurity.html]
[test_browserElement_oop_Alert.html]
[test_browserElement_oop_AlertInFrame.html]
[test_browserElement_oop_Auth.html]
[test_browserElement_oop_BackForward.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_BrowserWindowResize.html]
[test_browserElement_oop_Close.html]
[test_browserElement_oop_CookiesNotThirdParty.html]
[test_browserElement_oop_CopyPaste.html]
[test_browserElement_oop_DataURI.html]
[test_browserElement_oop_DocumentFirstPaint.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_ErrorSecurity.html]
[test_browserElement_oop_FirstPaint.html]
[test_browserElement_oop_ForwardName.html]
[test_browserElement_oop_Iconchange.html]
[test_browserElement_oop_LoadEvents.html]
[test_browserElement_oop_Metachange.html]
[test_browserElement_oop_NoAudioTrack.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_Opensearch.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_PrivateBrowsing.html]
skip-if = true # Bug 1315042
[test_browserElement_oop_PromptCheck.html]
[test_browserElement_oop_PromptConfirm.html]
[test_browserElement_oop_Reload.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_ReloadPostRequest.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_RemoveBrowserElement.html]
[test_browserElement_oop_ScrollEvent.html]
[test_browserElement_oop_SecurityChange.html]
skip-if = toolkit == 'android' #TIMED_OUT, bug 766586
[test_browserElement_oop_SendEvent.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_Stop.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_Titlechange.html]
[test_browserElement_oop_TopBarrier.html]
[test_browserElement_oop_XFrameOptions.html]
[test_browserElement_oop_XFrameOptionsDeny.html]
disabled = Disabling some OOP tests for WebIDL scope changes (bug 1310706 for re-enabling)
[test_browserElement_oop_XFrameOptionsSameOrigin.html]
[test_browserElement_oop_ContextmenuEvents.html]
[test_browserElement_oop_ExposableURI.html]
skip-if = !e10s # Bug 1391349

View File

@ -0,0 +1,100 @@
[DEFAULT]
skip-if = e10s
support-files =
audio.ogg
../../../dom/media/test/short-video.ogv
async.js
browserElementTestHelpers.js
browserElement_Alert.js
browserElement_AlertInFrame.js
browserElement_Auth.js
browserElement_Viewmode.js
browserElement_ThemeColor.js
browserElement_BrowserWindowResize.js
browserElement_Close.js
browserElement_ContextmenuEvents.js
browserElement_CookiesNotThirdParty.js
browserElement_CopyPaste.js
browserElement_DataURI.js
browserElement_DataURILoad.html
browserElement_DataURILoad.js
browserElement_ErrorSecurity.js
browserElement_ExposableURI.js
browserElement_FirstPaint.js
browserElement_ForwardName.js
browserElement_Iconchange.js
browserElement_LoadEvents.js
browserElement_Metachange.js
browserElement_Opensearch.js
browserElement_PrivateBrowsing.js
browserElement_PromptCheck.js
browserElement_PromptConfirm.js
browserElement_Reload.js
browserElement_RemoveBrowserElement.js
browserElement_ScrollEvent.js
browserElement_SecurityChange.js
browserElement_Titlechange.js
browserElement_TopBarrier.js
browserElement_XFrameOptions.js
browserElement_XFrameOptionsDeny.js
browserElement_XFrameOptionsSameOrigin.js
file_browserElement_AlertInFrame.html
file_browserElement_AlertInFrame_Inner.html
file_browserElement_Viewmode.html
file_browserElement_ThemeColor.html
file_browserElement_CookiesNotThirdParty.html
file_browserElement_ForwardName.html
file_browserElement_LoadEvents.html
file_browserElement_Metachange.sjs
file_browserElement_PrivateBrowsing.html
file_browserElement_SecurityChange.html
file_browserElement_XFrameOptions.sjs
file_browserElement_XFrameOptionsDeny.html
file_browserElement_XFrameOptionsSameOrigin.html
file_bug741717.sjs
file_empty.html
file_empty_script.js
file_focus.html
file_http_401_response.sjs
file_http_407_response.sjs
noaudio.webm
# Note: browserElementTestHelpers.js looks at the test's filename to determine
# whether the test should be OOP. "_oop_" signals OOP, "_inproc_" signals in
# process. Default is OOP.
[test_browserElement_NoAttr.html]
[test_browserElement_NoPref.html]
[test_browserElement_NoPermission.html]
[test_browserElement_inproc_Alert.html]
[test_browserElement_inproc_Viewmode.html]
[test_browserElement_inproc_ThemeColor.html]
[test_browserElement_inproc_AlertInFrame.html]
[test_browserElement_inproc_Auth.html]
disabled = No longer supported
[test_browserElement_inproc_BrowserWindowResize.html]
[test_browserElement_inproc_Close.html]
[test_browserElement_inproc_ContextmenuEvents.html]
[test_browserElement_inproc_CookiesNotThirdParty.html]
[test_browserElement_inproc_CopyPaste.html]
[test_browserElement_inproc_DataURI.html]
[test_browserElement_inproc_ExposableURI.html]
[test_browserElement_inproc_FirstPaint.html]
[test_browserElement_inproc_ForwardName.html]
[test_browserElement_inproc_Iconchange.html]
[test_browserElement_inproc_LoadEvents.html]
[test_browserElement_inproc_Metachange.html]
[test_browserElement_inproc_Opensearch.html]
[test_browserElement_inproc_PrivateBrowsing.html]
[test_browserElement_inproc_PromptCheck.html]
[test_browserElement_inproc_PromptConfirm.html]
[test_browserElement_inproc_RemoveBrowserElement.html]
[test_browserElement_inproc_ScrollEvent.html]
[test_browserElement_inproc_SecurityChange.html]
[test_browserElement_inproc_Titlechange.html]
[test_browserElement_inproc_TopBarrier.html]
[test_browserElement_inproc_XFrameOptions.html]
[test_browserElement_inproc_XFrameOptionsDeny.html]
[test_browserElement_inproc_XFrameOptionsSameOrigin.html]
[test_browserElement_inproc_Reload.html]
disabled = bug 774100
[test_browserElement_inproc_dataBlock.html]

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More