diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /dom/browser-element | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/browser-element')
327 files changed, 17433 insertions, 0 deletions
diff --git a/dom/browser-element/BrowserElementAudioChannel.cpp b/dom/browser-element/BrowserElementAudioChannel.cpp new file mode 100644 index 000000000..c9c29e2ea --- /dev/null +++ b/dom/browser-element/BrowserElementAudioChannel.cpp @@ -0,0 +1,591 @@ +/* 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/. */ + +#include "BrowserElementAudioChannel.h" + +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/dom/BrowserElementAudioChannelBinding.h" +#include "mozilla/dom/DOMRequest.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/TabParent.h" +#include "mozilla/dom/ToJSValue.h" +#include "AudioChannelService.h" +#include "nsContentUtils.h" +#include "nsIBrowserElementAPI.h" +#include "nsIDocShell.h" +#include "nsIDOMDOMRequest.h" +#include "nsIObserverService.h" +#include "nsISupportsPrimitives.h" +#include "nsITabParent.h" +#include "nsPIDOMWindow.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_ADDREF_INHERITED(BrowserElementAudioChannel, DOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(BrowserElementAudioChannel, DOMEventTargetHelper) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BrowserElementAudioChannel) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsIObserver) +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(BrowserElementAudioChannel, + DOMEventTargetHelper, + mFrameLoader, + mFrameWindow, + mTabParent, + mBrowserElementAPI) + +/* static */ already_AddRefed<BrowserElementAudioChannel> +BrowserElementAudioChannel::Create(nsPIDOMWindowInner* aWindow, + nsIFrameLoader* aFrameLoader, + nsIBrowserElementAPI* aAPI, + AudioChannel aAudioChannel, + ErrorResult& aRv) +{ + RefPtr<BrowserElementAudioChannel> ac = + new BrowserElementAudioChannel(aWindow, aFrameLoader, aAPI, aAudioChannel); + + aRv = ac->Initialize(); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug, + ("BrowserElementAudioChannel, Create, channel = %p, type = %d\n", + ac.get(), aAudioChannel)); + + return ac.forget(); +} + +BrowserElementAudioChannel::BrowserElementAudioChannel( + nsPIDOMWindowInner* aWindow, + nsIFrameLoader* aFrameLoader, + nsIBrowserElementAPI* aAPI, + AudioChannel aAudioChannel) + : DOMEventTargetHelper(aWindow) + , mFrameLoader(aFrameLoader) + , mBrowserElementAPI(aAPI) + , mAudioChannel(aAudioChannel) + , mState(eStateUnknown) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + nsAutoString name; + AudioChannelService::GetAudioChannelString(aAudioChannel, name); + + nsAutoCString topic; + topic.Assign("audiochannel-activity-"); + topic.Append(NS_ConvertUTF16toUTF8(name)); + + obs->AddObserver(this, topic.get(), true); + } +} + +BrowserElementAudioChannel::~BrowserElementAudioChannel() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + nsAutoString name; + AudioChannelService::GetAudioChannelString(mAudioChannel, name); + + nsAutoCString topic; + topic.Assign("audiochannel-activity-"); + topic.Append(NS_ConvertUTF16toUTF8(name)); + + obs->RemoveObserver(this, topic.get()); + } +} + +nsresult +BrowserElementAudioChannel::Initialize() +{ + if (!mFrameLoader) { + nsCOMPtr<nsPIDOMWindowInner> window = GetOwner(); + if (!window) { + return NS_ERROR_FAILURE; + } + + mFrameWindow = window->GetScriptableTop(); + mFrameWindow = mFrameWindow->GetOuterWindow(); + return NS_OK; + } + + nsCOMPtr<nsIDocShell> docShell; + nsresult rv = mFrameLoader->GetDocShell(getter_AddRefs(docShell)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (docShell) { + nsCOMPtr<nsPIDOMWindowOuter> window = docShell->GetWindow(); + if (!window) { + return NS_ERROR_FAILURE; + } + + mFrameWindow = window->GetScriptableTop(); + mFrameWindow = mFrameWindow->GetOuterWindow(); + return NS_OK; + } + + rv = mFrameLoader->GetTabParent(getter_AddRefs(mTabParent)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + MOZ_ASSERT(mTabParent); + return NS_OK; +} + +JSObject* +BrowserElementAudioChannel::WrapObject(JSContext *aCx, + JS::Handle<JSObject*> aGivenProto) +{ + return BrowserElementAudioChannelBinding::Wrap(aCx, this, aGivenProto); +} + +AudioChannel +BrowserElementAudioChannel::Name() const +{ + MOZ_ASSERT(NS_IsMainThread()); + return mAudioChannel; +} + +namespace { + +class BaseRunnable : public Runnable +{ +protected: + nsCOMPtr<nsPIDOMWindowInner> mParentWindow; + nsCOMPtr<nsPIDOMWindowOuter> mFrameWindow; + RefPtr<DOMRequest> mRequest; + AudioChannel mAudioChannel; + + virtual void DoWork(AudioChannelService* aService, + JSContext* aCx) = 0; + +public: + BaseRunnable(nsPIDOMWindowInner* aParentWindow, + nsPIDOMWindowOuter* aFrameWindow, + DOMRequest* aRequest, AudioChannel aAudioChannel) + : mParentWindow(aParentWindow) + , mFrameWindow(aFrameWindow) + , mRequest(aRequest) + , mAudioChannel(aAudioChannel) + {} + + NS_IMETHOD Run() override + { + RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate(); + if (!service) { + return NS_OK; + } + + AutoJSAPI jsapi; + if (!jsapi.Init(mParentWindow)) { + mRequest->FireError(NS_ERROR_FAILURE); + return NS_OK; + } + + DoWork(service, jsapi.cx()); + return NS_OK; + } +}; + +class GetVolumeRunnable final : public BaseRunnable +{ +public: + GetVolumeRunnable(nsPIDOMWindowInner* aParentWindow, + nsPIDOMWindowOuter* aFrameWindow, + DOMRequest* aRequest, AudioChannel aAudioChannel) + : BaseRunnable(aParentWindow, aFrameWindow, aRequest, aAudioChannel) + {} + +protected: + virtual void DoWork(AudioChannelService* aService, JSContext* aCx) override + { + float volume = aService->GetAudioChannelVolume(mFrameWindow, mAudioChannel); + + JS::Rooted<JS::Value> value(aCx); + if (!ToJSValue(aCx, volume, &value)) { + mRequest->FireError(NS_ERROR_FAILURE); + return; + } + + mRequest->FireSuccess(value); + } +}; + +class GetMutedRunnable final : public BaseRunnable +{ +public: + GetMutedRunnable(nsPIDOMWindowInner* aParentWindow, + nsPIDOMWindowOuter* aFrameWindow, + DOMRequest* aRequest, AudioChannel aAudioChannel) + : BaseRunnable(aParentWindow, aFrameWindow, aRequest, aAudioChannel) + {} + +protected: + virtual void DoWork(AudioChannelService* aService, JSContext* aCx) override + { + bool muted = aService->GetAudioChannelMuted(mFrameWindow, mAudioChannel); + + JS::Rooted<JS::Value> value(aCx); + if (!ToJSValue(aCx, muted, &value)) { + mRequest->FireError(NS_ERROR_FAILURE); + return; + } + + mRequest->FireSuccess(value); + } +}; + +class IsActiveRunnable final : public BaseRunnable +{ + bool mActive; + bool mValueKnown; + +public: + IsActiveRunnable(nsPIDOMWindowInner* aParentWindow, + nsPIDOMWindowOuter* aFrameWindow, + DOMRequest* aRequest, AudioChannel aAudioChannel, + bool aActive) + : BaseRunnable(aParentWindow, aFrameWindow, aRequest, aAudioChannel) + , mActive(aActive) + , mValueKnown(true) + {} + + IsActiveRunnable(nsPIDOMWindowInner* aParentWindow, + nsPIDOMWindowOuter* aFrameWindow, + DOMRequest* aRequest, AudioChannel aAudioChannel) + : BaseRunnable(aParentWindow, aFrameWindow, aRequest, aAudioChannel) + , mActive(true) + , mValueKnown(false) + {} + +protected: + virtual void DoWork(AudioChannelService* aService, JSContext* aCx) override + { + if (!mValueKnown) { + mActive = aService->IsAudioChannelActive(mFrameWindow, mAudioChannel); + } + + JS::Rooted<JS::Value> value(aCx); + if (!ToJSValue(aCx, mActive, &value)) { + mRequest->FireError(NS_ERROR_FAILURE); + return; + } + + mRequest->FireSuccess(value); + } +}; + +class FireSuccessRunnable final : public BaseRunnable +{ +public: + FireSuccessRunnable(nsPIDOMWindowInner* aParentWindow, + nsPIDOMWindowOuter* aFrameWindow, + DOMRequest* aRequest, AudioChannel aAudioChannel) + : BaseRunnable(aParentWindow, aFrameWindow, aRequest, aAudioChannel) + {} + +protected: + virtual void DoWork(AudioChannelService* aService, JSContext* aCx) override + { + JS::Rooted<JS::Value> value(aCx); + mRequest->FireSuccess(value); + } +}; + +} // anonymous namespace + +already_AddRefed<dom::DOMRequest> +BrowserElementAudioChannel::GetVolume(ErrorResult& aRv) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!mFrameWindow) { + nsCOMPtr<nsIDOMDOMRequest> request; + aRv = mBrowserElementAPI->GetAudioChannelVolume((uint32_t)mAudioChannel, + getter_AddRefs(request)); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return request.forget().downcast<DOMRequest>(); + } + + RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner()); + + nsCOMPtr<nsIRunnable> runnable = + new GetVolumeRunnable(GetOwner(), mFrameWindow, domRequest, mAudioChannel); + NS_DispatchToMainThread(runnable); + + return domRequest.forget(); +} + +already_AddRefed<dom::DOMRequest> +BrowserElementAudioChannel::SetVolume(float aVolume, ErrorResult& aRv) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!mFrameWindow) { + nsCOMPtr<nsIDOMDOMRequest> request; + aRv = mBrowserElementAPI->SetAudioChannelVolume((uint32_t)mAudioChannel, + aVolume, + getter_AddRefs(request)); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return request.forget().downcast<DOMRequest>(); + } + + RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate(); + if (service) { + service->SetAudioChannelVolume(mFrameWindow, mAudioChannel, aVolume); + } + + RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner()); + nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(), + mFrameWindow, + domRequest, + mAudioChannel); + NS_DispatchToMainThread(runnable); + + return domRequest.forget(); +} + +already_AddRefed<dom::DOMRequest> +BrowserElementAudioChannel::GetMuted(ErrorResult& aRv) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!mFrameWindow) { + nsCOMPtr<nsIDOMDOMRequest> request; + aRv = mBrowserElementAPI->GetAudioChannelMuted((uint32_t)mAudioChannel, + getter_AddRefs(request)); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return request.forget().downcast<DOMRequest>(); + } + + RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner()); + + nsCOMPtr<nsIRunnable> runnable = + new GetMutedRunnable(GetOwner(), mFrameWindow, domRequest, mAudioChannel); + NS_DispatchToMainThread(runnable); + + return domRequest.forget(); +} + +already_AddRefed<dom::DOMRequest> +BrowserElementAudioChannel::SetMuted(bool aMuted, ErrorResult& aRv) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!mFrameWindow) { + nsCOMPtr<nsIDOMDOMRequest> request; + aRv = mBrowserElementAPI->SetAudioChannelMuted((uint32_t)mAudioChannel, + aMuted, + getter_AddRefs(request)); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return request.forget().downcast<DOMRequest>(); + } + + RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate(); + if (service) { + service->SetAudioChannelMuted(mFrameWindow, mAudioChannel, aMuted); + } + + RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner()); + nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(), + mFrameWindow, + domRequest, + mAudioChannel); + NS_DispatchToMainThread(runnable); + + return domRequest.forget(); +} + +already_AddRefed<dom::DOMRequest> +BrowserElementAudioChannel::IsActive(ErrorResult& aRv) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (mState != eStateUnknown) { + RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner()); + + nsCOMPtr<nsIRunnable> runnable = + new IsActiveRunnable(GetOwner(), mFrameWindow, domRequest, mAudioChannel, + mState == eStateActive); + NS_DispatchToMainThread(runnable); + + return domRequest.forget(); + } + + if (!mFrameWindow) { + nsCOMPtr<nsIDOMDOMRequest> request; + aRv = mBrowserElementAPI->IsAudioChannelActive((uint32_t)mAudioChannel, + getter_AddRefs(request)); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return request.forget().downcast<DOMRequest>(); + } + + RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner()); + + nsCOMPtr<nsIRunnable> runnable = + new IsActiveRunnable(GetOwner(), mFrameWindow, domRequest, mAudioChannel); + NS_DispatchToMainThread(runnable); + + return domRequest.forget(); +} + +NS_IMETHODIMP +BrowserElementAudioChannel::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) +{ + nsAutoString name; + AudioChannelService::GetAudioChannelString(mAudioChannel, name); + + nsAutoCString topic; + topic.Assign("audiochannel-activity-"); + topic.Append(NS_ConvertUTF16toUTF8(name)); + + if (strcmp(topic.get(), aTopic)) { + return NS_OK; + } + + // Message received from the child. + if (!mFrameWindow) { + if (mTabParent == aSubject) { + ProcessStateChanged(aData); + } + + return NS_OK; + } + + nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject); + if (!wrapper) { + bool isNested = false; + nsresult rv = IsFromNestedFrame(aSubject, isNested); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (isNested) { + ProcessStateChanged(aData); + } + + return NS_OK; + } + + uint64_t windowID; + nsresult rv = wrapper->GetData(&windowID); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (windowID != mFrameWindow->WindowID()) { + return NS_OK; + } + + ProcessStateChanged(aData); + return NS_OK; +} + +void +BrowserElementAudioChannel::ProcessStateChanged(const char16_t* aData) +{ + MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug, + ("BrowserElementAudioChannel, ProcessStateChanged, this = %p, " + "type = %d\n", this, mAudioChannel)); + + nsAutoString value(aData); + mState = value.EqualsASCII("active") ? eStateActive : eStateInactive; + DispatchTrustedEvent(NS_LITERAL_STRING("activestatechanged")); +} + +bool +BrowserElementAudioChannel::IsSystemAppWindow(nsPIDOMWindowOuter* aWindow) const +{ + nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc(); + if (!doc) { + return false; + } + + if (nsContentUtils::IsChromeDoc(doc)) { + return true; + } + + nsAdoptingCString systemAppUrl = + mozilla::Preferences::GetCString("b2g.system_startup_url"); + if (!systemAppUrl) { + return false; + } + + nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal(); + nsCOMPtr<nsIURI> uri; + principal->GetURI(getter_AddRefs(uri)); + + if (uri) { + nsAutoCString spec; + uri->GetSpec(spec); + + if (spec.Equals(systemAppUrl)) { + return true; + } + } + + return false; +} + +nsresult +BrowserElementAudioChannel::IsFromNestedFrame(nsISupports* aSubject, + bool& aIsNested) const +{ + aIsNested = false; + nsCOMPtr<nsITabParent> iTabParent = do_QueryInterface(aSubject); + if (!iTabParent) { + return NS_ERROR_FAILURE; + } + + RefPtr<TabParent> tabParent = TabParent::GetFrom(iTabParent); + if (!tabParent) { + return NS_ERROR_FAILURE; + } + + Element* element = tabParent->GetOwnerElement(); + if (!element) { + return NS_ERROR_FAILURE; + } + + // Since the normal OOP processes are opened out from b2g process, the owner + // of their tabParent are the same - system app window. Therefore, in order + // to find the case of nested MozFrame, we need to exclude this situation. + nsCOMPtr<nsPIDOMWindowOuter> window = element->OwnerDoc()->GetWindow(); + if (window == mFrameWindow && !IsSystemAppWindow(window)) { + aIsNested = true; + return NS_OK; + } + + return NS_OK; +} + +} // dom namespace +} // mozilla namespace diff --git a/dom/browser-element/BrowserElementAudioChannel.h b/dom/browser-element/BrowserElementAudioChannel.h new file mode 100644 index 000000000..237e5edc8 --- /dev/null +++ b/dom/browser-element/BrowserElementAudioChannel.h @@ -0,0 +1,97 @@ +/* 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/. */ + +#ifndef mozilla_dom_BrowserElementAudioChannels_h +#define mozilla_dom_BrowserElementAudioChannels_h + +#include "mozilla/dom/AudioChannelBinding.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/DOMEventTargetHelper.h" +#include "mozilla/ErrorResult.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIObserver.h" +#include "nsIFrameLoader.h" +#include "nsWeakReference.h" +#include "nsWrapperCache.h" + +class nsIBrowserElementAPI; +class nsITabParent; +class nsPIDOMWindowOuter; + +namespace mozilla { +namespace dom { + +class DOMRequest; + +class BrowserElementAudioChannel final : public DOMEventTargetHelper + , public nsSupportsWeakReference + , public nsIObserver +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIOBSERVER + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BrowserElementAudioChannel, + DOMEventTargetHelper) + + static already_AddRefed<BrowserElementAudioChannel> + Create(nsPIDOMWindowInner* aWindow, + nsIFrameLoader* aFrameLoader, + nsIBrowserElementAPI* aAPI, + AudioChannel aAudioChannel, + ErrorResult& aRv); + + // WebIDL methods + + virtual JSObject* WrapObject(JSContext *aCx, + JS::Handle<JSObject*> aGivenProto) override; + + AudioChannel Name() const; + + already_AddRefed<dom::DOMRequest> GetVolume(ErrorResult& aRv); + already_AddRefed<dom::DOMRequest> SetVolume(float aVolume, ErrorResult& aRv); + + already_AddRefed<dom::DOMRequest> GetMuted(ErrorResult& aRv); + already_AddRefed<dom::DOMRequest> SetMuted(bool aMuted, ErrorResult& aRv); + + already_AddRefed<dom::DOMRequest> IsActive(ErrorResult& aRv); + + IMPL_EVENT_HANDLER(activestatechanged); + +private: + BrowserElementAudioChannel(nsPIDOMWindowInner* aWindow, + nsIFrameLoader* aFrameLoader, + nsIBrowserElementAPI* aAPI, + AudioChannel aAudioChannel); + + bool IsSystemAppWindow(nsPIDOMWindowOuter* aWindow) const; + + // This method is used to check whether we're in the nested-mozbrower-frame + // situation, see bug1214148. + nsresult IsFromNestedFrame(nsISupports* aSubject, + bool& aIsNested) const; + + ~BrowserElementAudioChannel(); + + nsresult Initialize(); + + void ProcessStateChanged(const char16_t* aData); + + nsCOMPtr<nsIFrameLoader> mFrameLoader; + nsCOMPtr<nsIBrowserElementAPI> mBrowserElementAPI; + nsCOMPtr<nsITabParent> mTabParent; + nsCOMPtr<nsPIDOMWindowOuter> mFrameWindow; + AudioChannel mAudioChannel; + + enum { + eStateActive, + eStateInactive, + eStateUnknown + } mState; +}; + +} // dom namespace +} // mozilla namespace + +#endif // mozilla_dom_BrowserElementAudioChannels_h diff --git a/dom/browser-element/BrowserElementChild.js b/dom/browser-element/BrowserElementChild.js new file mode 100644 index 000000000..066be66d2 --- /dev/null +++ b/dom/browser-element/BrowserElementChild.js @@ -0,0 +1,83 @@ +/* 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/. */ + +"use strict"; + +var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; +Cu.import("resource://gre/modules/Services.jsm"); + +function debug(msg) { + //dump("BrowserElementChild - " + msg + "\n"); +} + +// NB: this must happen before we process any messages from +// mozbrowser API clients. +docShell.isActive = true; + +function parentDocShell(docshell) { + if (!docshell) { + return null; + } + let treeitem = docshell.QueryInterface(Ci.nsIDocShellTreeItem); + return treeitem.parent ? treeitem.parent.QueryInterface(Ci.nsIDocShell) : null; +} + +function isTopBrowserElement(docShell) { + while (docShell) { + docShell = parentDocShell(docShell); + if (docShell && docShell.isMozBrowserOrApp) { + return false; + } + } + return true; +} + +var BrowserElementIsReady; + +debug(`Might load BE scripts: BEIR: ${BrowserElementIsReady}`); +if (!BrowserElementIsReady) { + debug("Loading BE scripts") + if (!("BrowserElementIsPreloaded" in this)) { + if (isTopBrowserElement(docShell)) { + if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) { + try { + Services.scriptloader.loadSubScript("chrome://global/content/forms.js"); + } catch (e) { + } + } + } + + if(Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) { + // general content apps + if (isTopBrowserElement(docShell)) { + Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js"); + } + } else { + // rocketbar in system app and other in-process case (ex. B2G desktop client) + Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js"); + } + + Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js"); + } + + function onDestroy() { + removeMessageListener("browser-element-api:destroy", onDestroy); + + if (api) { + api.destroy(); + } + if ("CopyPasteAssistent" in this) { + CopyPasteAssistent.destroy(); + } + + BrowserElementIsReady = false; + } + addMessageListener("browser-element-api:destroy", onDestroy); + + BrowserElementIsReady = true; +} else { + debug("BE already loaded, abort"); +} + +sendAsyncMessage('browser-element-api:call', { 'msg_name': 'hello' }); diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js new file mode 100644 index 000000000..780dfa80e --- /dev/null +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -0,0 +1,1823 @@ +/* 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/. */ + +"use strict"; + +function debug(msg) { + // dump("BrowserElementChildPreload - " + msg + "\n"); +} + +debug("loaded"); + +var BrowserElementIsReady; + +var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/BrowserElementPromptService.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); +Cu.import("resource://gre/modules/ExtensionContent.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "acs", + "@mozilla.org/audiochannel/service;1", + "nsIAudioChannelService"); +XPCOMUtils.defineLazyModuleGetter(this, "ManifestFinder", + "resource://gre/modules/ManifestFinder.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ManifestObtainer", + "resource://gre/modules/ManifestObtainer.jsm"); + + +var kLongestReturnedString = 128; + +var Timer = Components.Constructor("@mozilla.org/timer;1", + "nsITimer", + "initWithCallback"); + +function sendAsyncMsg(msg, data) { + // Ensure that we don't send any messages before BrowserElementChild.js + // finishes loading. + if (!BrowserElementIsReady) { + return; + } + + if (!data) { + data = { }; + } + + data.msg_name = msg; + sendAsyncMessage('browser-element-api:call', data); +} + +function sendSyncMsg(msg, data) { + // Ensure that we don't send any messages before BrowserElementChild.js + // finishes loading. + if (!BrowserElementIsReady) { + return; + } + + if (!data) { + data = { }; + } + + data.msg_name = msg; + return sendSyncMessage('browser-element-api:call', data); +} + +var CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page'; + +var OBSERVED_EVENTS = [ + 'xpcom-shutdown', + 'audio-playback', + 'activity-done', + 'will-launch-app' +]; + +var LISTENED_EVENTS = [ + { type: "DOMTitleChanged", useCapture: true, wantsUntrusted: false }, + { type: "DOMLinkAdded", useCapture: true, wantsUntrusted: false }, + { type: "MozScrolledAreaChanged", useCapture: true, wantsUntrusted: false }, + { type: "MozDOMFullscreen:Request", useCapture: true, wantsUntrusted: false }, + { type: "MozDOMFullscreen:NewOrigin", useCapture: true, wantsUntrusted: false }, + { type: "MozDOMFullscreen:Exit", useCapture: true, wantsUntrusted: false }, + { type: "DOMMetaAdded", useCapture: true, wantsUntrusted: false }, + { type: "DOMMetaChanged", useCapture: true, wantsUntrusted: false }, + { type: "DOMMetaRemoved", useCapture: true, wantsUntrusted: false }, + { type: "scrollviewchange", useCapture: true, wantsUntrusted: false }, + { type: "click", useCapture: false, wantsUntrusted: false }, + // This listens to unload events from our message manager, but /not/ from + // the |content| window. That's because the window's unload event doesn't + // bubble, and we're not using a capturing listener. If we'd used + // useCapture == true, we /would/ hear unload events from the window, which + // is not what we want! + { type: "unload", useCapture: false, wantsUntrusted: false }, +]; + +// We are using the system group for those events so if something in the +// content called .stopPropagation() this will still be called. +var LISTENED_SYSTEM_EVENTS = [ + { type: "DOMWindowClose", useCapture: false }, + { type: "DOMWindowCreated", useCapture: false }, + { type: "DOMWindowResize", useCapture: false }, + { type: "contextmenu", useCapture: false }, + { type: "scroll", useCapture: false }, +]; + +/** + * The BrowserElementChild implements one half of <iframe mozbrowser>. + * (The other half is, unsurprisingly, BrowserElementParent.) + * + * This script is injected into an <iframe mozbrowser> via + * nsIMessageManager::LoadFrameScript(). + * + * Our job here is to listen for events within this frame and bubble them up to + * the parent process. + */ + +var global = this; + +function BrowserElementProxyForwarder() { +} + +BrowserElementProxyForwarder.prototype = { + init: function() { + Services.obs.addObserver(this, "browser-element-api:proxy-call", false); + addMessageListener("browser-element-api:proxy", this); + }, + + uninit: function() { + Services.obs.removeObserver(this, "browser-element-api:proxy-call", false); + removeMessageListener("browser-element-api:proxy", this); + }, + + // Observer callback receives messages from BrowserElementProxy.js + observe: function(subject, topic, stringifedData) { + if (subject !== content) { + return; + } + + // Forward it to BrowserElementParent.js + sendAsyncMessage(topic, JSON.parse(stringifedData)); + }, + + // Message manager callback receives messages from BrowserElementParent.js + receiveMessage: function(mmMsg) { + // Forward it to BrowserElementProxy.js + Services.obs.notifyObservers( + content, mmMsg.name, JSON.stringify(mmMsg.json)); + } +}; + +function BrowserElementChild() { + // Maps outer window id --> weak ref to window. Used by modal dialog code. + this._windowIDDict = {}; + + // _forcedVisible corresponds to the visibility state our owner has set on us + // (via iframe.setVisible). ownerVisible corresponds to whether the docShell + // whose window owns this element is visible. + // + // Our docShell is visible iff _forcedVisible and _ownerVisible are both + // true. + this._forcedVisible = true; + this._ownerVisible = true; + + this._nextPaintHandler = null; + + this._isContentWindowCreated = false; + this._pendingSetInputMethodActive = []; + + this.forwarder = new BrowserElementProxyForwarder(); + + this._init(); +}; + +BrowserElementChild.prototype = { + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsISupportsWeakReference]), + + _init: function() { + debug("Starting up."); + + BrowserElementPromptService.mapWindowToBrowserElementChild(content, this); + + docShell.QueryInterface(Ci.nsIWebProgress) + .addProgressListener(this._progressListener, + Ci.nsIWebProgress.NOTIFY_LOCATION | + Ci.nsIWebProgress.NOTIFY_SECURITY | + Ci.nsIWebProgress.NOTIFY_STATE_WINDOW); + + let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation); + if (!webNavigation.sessionHistory) { + webNavigation.sessionHistory = Cc["@mozilla.org/browser/shistory;1"] + .createInstance(Ci.nsISHistory); + } + + // This is necessary to get security web progress notifications. + var securityUI = Cc['@mozilla.org/secure_browser_ui;1'] + .createInstance(Ci.nsISecureBrowserUI); + securityUI.init(content); + + // A cache of the menuitem dom objects keyed by the id we generate + // and pass to the embedder + this._ctxHandlers = {}; + // Counter of contextmenu events fired + this._ctxCounter = 0; + + this._shuttingDown = false; + + LISTENED_EVENTS.forEach(event => { + addEventListener(event.type, this, event.useCapture, event.wantsUntrusted); + }); + + // Registers a MozAfterPaint handler for the very first paint. + this._addMozAfterPaintHandler(function () { + sendAsyncMsg('firstpaint'); + }); + + addMessageListener("browser-element-api:call", this); + + let els = Cc["@mozilla.org/eventlistenerservice;1"] + .getService(Ci.nsIEventListenerService); + LISTENED_SYSTEM_EVENTS.forEach(event => { + els.addSystemEventListener(global, event.type, this, event.useCapture); + }); + + OBSERVED_EVENTS.forEach((aTopic) => { + Services.obs.addObserver(this, aTopic, false); + }); + + this.forwarder.init(); + }, + + /** + * Shut down the frame's side of the browser API. This is called when: + * - our TabChildGlobal starts to die + * - the content is moved to frame without the browser API + * This is not called when the page inside |content| unloads. + */ + destroy: function() { + debug("Destroying"); + this._shuttingDown = true; + + BrowserElementPromptService.unmapWindowToBrowserElementChild(content); + + docShell.QueryInterface(Ci.nsIWebProgress) + .removeProgressListener(this._progressListener); + + LISTENED_EVENTS.forEach(event => { + removeEventListener(event.type, this, event.useCapture, event.wantsUntrusted); + }); + + this._deactivateNextPaintListener(); + + removeMessageListener("browser-element-api:call", this); + + let els = Cc["@mozilla.org/eventlistenerservice;1"] + .getService(Ci.nsIEventListenerService); + LISTENED_SYSTEM_EVENTS.forEach(event => { + els.removeSystemEventListener(global, event.type, this, event.useCapture); + }); + + OBSERVED_EVENTS.forEach((aTopic) => { + Services.obs.removeObserver(this, aTopic); + }); + + this.forwarder.uninit(); + this.forwarder = null; + }, + + handleEvent: function(event) { + switch (event.type) { + case "DOMTitleChanged": + this._titleChangedHandler(event); + break; + case "DOMLinkAdded": + this._linkAddedHandler(event); + break; + case "MozScrolledAreaChanged": + this._mozScrollAreaChanged(event); + break; + case "MozDOMFullscreen:Request": + this._mozRequestedDOMFullscreen(event); + break; + case "MozDOMFullscreen:NewOrigin": + this._mozFullscreenOriginChange(event); + break; + case "MozDOMFullscreen:Exit": + this._mozExitDomFullscreen(event); + break; + case "DOMMetaAdded": + this._metaChangedHandler(event); + break; + case "DOMMetaChanged": + this._metaChangedHandler(event); + break; + case "DOMMetaRemoved": + this._metaChangedHandler(event); + break; + case "scrollviewchange": + this._ScrollViewChangeHandler(event); + break; + case "click": + this._ClickHandler(event); + break; + case "unload": + this.destroy(event); + break; + case "DOMWindowClose": + this._windowCloseHandler(event); + break; + case "DOMWindowCreated": + this._windowCreatedHandler(event); + break; + case "DOMWindowResize": + this._windowResizeHandler(event); + break; + case "contextmenu": + this._contextmenuHandler(event); + break; + case "scroll": + this._scrollEventHandler(event); + break; + } + }, + + receiveMessage: function(message) { + let self = this; + + let mmCalls = { + "purge-history": this._recvPurgeHistory, + "get-screenshot": this._recvGetScreenshot, + "get-contentdimensions": this._recvGetContentDimensions, + "set-visible": this._recvSetVisible, + "get-visible": this._recvVisible, + "send-mouse-event": this._recvSendMouseEvent, + "send-touch-event": this._recvSendTouchEvent, + "get-can-go-back": this._recvCanGoBack, + "get-can-go-forward": this._recvCanGoForward, + "mute": this._recvMute, + "unmute": this._recvUnmute, + "get-muted": this._recvGetMuted, + "set-volume": this._recvSetVolume, + "get-volume": this._recvGetVolume, + "go-back": this._recvGoBack, + "go-forward": this._recvGoForward, + "reload": this._recvReload, + "stop": this._recvStop, + "zoom": this._recvZoom, + "unblock-modal-prompt": this._recvStopWaiting, + "fire-ctx-callback": this._recvFireCtxCallback, + "owner-visibility-change": this._recvOwnerVisibilityChange, + "entered-fullscreen": this._recvEnteredFullscreen, + "exit-fullscreen": this._recvExitFullscreen, + "activate-next-paint-listener": this._activateNextPaintListener, + "set-input-method-active": this._recvSetInputMethodActive, + "deactivate-next-paint-listener": this._deactivateNextPaintListener, + "find-all": this._recvFindAll, + "find-next": this._recvFindNext, + "clear-match": this._recvClearMatch, + "execute-script": this._recvExecuteScript, + "get-audio-channel-volume": this._recvGetAudioChannelVolume, + "set-audio-channel-volume": this._recvSetAudioChannelVolume, + "get-audio-channel-muted": this._recvGetAudioChannelMuted, + "set-audio-channel-muted": this._recvSetAudioChannelMuted, + "get-is-audio-channel-active": this._recvIsAudioChannelActive, + "get-web-manifest": this._recvGetWebManifest, + } + + if (message.data.msg_name in mmCalls) { + return mmCalls[message.data.msg_name].apply(self, arguments); + } + }, + + _paintFrozenTimer: null, + observe: function(subject, topic, data) { + // Ignore notifications not about our document. (Note that |content| /can/ + // be null; see bug 874900.) + + if (topic !== 'activity-done' && + topic !== 'audio-playback' && + topic !== 'will-launch-app' && + (!content || subject !== content.document)) { + return; + } + if (topic == 'activity-done' && docShell !== subject) + return; + switch (topic) { + case 'activity-done': + sendAsyncMsg('activitydone', { success: (data == 'activity-success') }); + break; + case 'audio-playback': + if (subject === content) { + sendAsyncMsg('audioplaybackchange', { _payload_: data }); + } + break; + case 'xpcom-shutdown': + this._shuttingDown = true; + break; + case 'will-launch-app': + // If the launcher is not visible, let's ignore the message. + if (!docShell.isActive) { + return; + } + + // If this is not a content process, let's not freeze painting. + if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_CONTENT) { + return; + } + + docShell.contentViewer.pausePainting(); + + this._paintFrozenTimer && this._paintFrozenTimer.cancel(); + this._paintFrozenTimer = new Timer(this, 3000, Ci.nsITimer.TYPE_ONE_SHOT); + break; + } + }, + + notify: function(timer) { + docShell.contentViewer.resumePainting(); + this._paintFrozenTimer.cancel(); + this._paintFrozenTimer = null; + }, + + get _windowUtils() { + return content.document.defaultView + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + }, + + _tryGetInnerWindowID: function(win) { + let utils = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + try { + return utils.currentInnerWindowID; + } + catch(e) { + return null; + } + }, + + /** + * Show a modal prompt. Called by BrowserElementPromptService. + */ + showModalPrompt: function(win, args) { + let utils = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + + args.windowID = { outer: utils.outerWindowID, + inner: this._tryGetInnerWindowID(win) }; + sendAsyncMsg('showmodalprompt', args); + + let returnValue = this._waitForResult(win); + + if (args.promptType == 'prompt' || + args.promptType == 'confirm' || + args.promptType == 'custom-prompt') { + return returnValue; + } + }, + + /** + * Spin in a nested event loop until we receive a unblock-modal-prompt message for + * this window. + */ + _waitForResult: function(win) { + debug("_waitForResult(" + win + ")"); + let utils = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + + let outerWindowID = utils.outerWindowID; + let innerWindowID = this._tryGetInnerWindowID(win); + if (innerWindowID === null) { + // I have no idea what waiting for a result means when there's no inner + // window, so let's just bail. + debug("_waitForResult: No inner window. Bailing."); + return; + } + + this._windowIDDict[outerWindowID] = Cu.getWeakReference(win); + + debug("Entering modal state (outerWindowID=" + outerWindowID + ", " + + "innerWindowID=" + innerWindowID + ")"); + + utils.enterModalState(); + + // We'll decrement win.modalDepth when we receive a unblock-modal-prompt message + // for the window. + if (!win.modalDepth) { + win.modalDepth = 0; + } + win.modalDepth++; + let origModalDepth = win.modalDepth; + + let thread = Services.tm.currentThread; + debug("Nested event loop - begin"); + while (win.modalDepth == origModalDepth && !this._shuttingDown) { + // Bail out of the loop if the inner window changed; that means the + // window navigated. Bail out when we're shutting down because otherwise + // we'll leak our window. + if (this._tryGetInnerWindowID(win) !== innerWindowID) { + debug("_waitForResult: Inner window ID changed " + + "while in nested event loop."); + break; + } + + thread.processNextEvent(/* mayWait = */ true); + } + debug("Nested event loop - finish"); + + if (win.modalDepth == 0) { + delete this._windowIDDict[outerWindowID]; + } + + // If we exited the loop because the inner window changed, then bail on the + // modal prompt. + if (innerWindowID !== this._tryGetInnerWindowID(win)) { + throw Components.Exception("Modal state aborted by navigation", + Cr.NS_ERROR_NOT_AVAILABLE); + } + + let returnValue = win.modalReturnValue; + delete win.modalReturnValue; + + if (!this._shuttingDown) { + utils.leaveModalState(); + } + + debug("Leaving modal state (outerID=" + outerWindowID + ", " + + "innerID=" + innerWindowID + ")"); + return returnValue; + }, + + _recvStopWaiting: function(msg) { + let outerID = msg.json.windowID.outer; + let innerID = msg.json.windowID.inner; + let returnValue = msg.json.returnValue; + debug("recvStopWaiting(outer=" + outerID + ", inner=" + innerID + + ", returnValue=" + returnValue + ")"); + + if (!this._windowIDDict[outerID]) { + debug("recvStopWaiting: No record of outer window ID " + outerID); + return; + } + + let win = this._windowIDDict[outerID].get(); + + if (!win) { + debug("recvStopWaiting, but window is gone\n"); + return; + } + + if (innerID !== this._tryGetInnerWindowID(win)) { + debug("recvStopWaiting, but inner ID has changed\n"); + return; + } + + debug("recvStopWaiting " + win); + win.modalReturnValue = returnValue; + win.modalDepth--; + }, + + _recvEnteredFullscreen: function() { + if (!this._windowUtils.handleFullscreenRequests() && + !content.document.fullscreenElement) { + // If we don't actually have any pending fullscreen request + // to handle, neither we have been in fullscreen, tell the + // parent to just exit. + sendAsyncMsg("exit-dom-fullscreen"); + } + }, + + _recvExitFullscreen: function() { + this._windowUtils.exitFullscreen(); + }, + + _titleChangedHandler: function(e) { + debug("Got titlechanged: (" + e.target.title + ")"); + var win = e.target.defaultView; + + // Ignore titlechanges which don't come from the top-level + // <iframe mozbrowser> window. + if (win == content) { + sendAsyncMsg('titlechange', { _payload_: e.target.title }); + } + else { + debug("Not top level!"); + } + }, + + _maybeCopyAttribute: function(src, target, attribute) { + if (src.getAttribute(attribute)) { + target[attribute] = src.getAttribute(attribute); + } + }, + + _iconChangedHandler: function(e) { + debug('Got iconchanged: (' + e.target.href + ')'); + let icon = { href: e.target.href }; + this._maybeCopyAttribute(e.target, icon, 'sizes'); + this._maybeCopyAttribute(e.target, icon, 'rel'); + sendAsyncMsg('iconchange', icon); + }, + + _openSearchHandler: function(e) { + debug('Got opensearch: (' + e.target.href + ')'); + + if (e.target.type !== "application/opensearchdescription+xml") { + return; + } + + sendAsyncMsg('opensearch', { title: e.target.title, + href: e.target.href }); + + }, + + _manifestChangedHandler: function(e) { + debug('Got manifestchanged: (' + e.target.href + ')'); + let manifest = { href: e.target.href }; + sendAsyncMsg('manifestchange', manifest); + + }, + + // Processes the "rel" field in <link> tags and forward to specific handlers. + _linkAddedHandler: function(e) { + let win = e.target.ownerDocument.defaultView; + // Ignore links which don't come from the top-level + // <iframe mozbrowser> window. + if (win != content) { + debug('Not top level!'); + return; + } + + let handlers = { + 'icon': this._iconChangedHandler.bind(this), + 'apple-touch-icon': this._iconChangedHandler.bind(this), + 'apple-touch-icon-precomposed': this._iconChangedHandler.bind(this), + 'search': this._openSearchHandler, + 'manifest': this._manifestChangedHandler + }; + + debug('Got linkAdded: (' + e.target.href + ') ' + e.target.rel); + e.target.rel.split(' ').forEach(function(x) { + let token = x.toLowerCase(); + if (handlers[token]) { + handlers[token](e); + } + }, this); + }, + + _metaChangedHandler: function(e) { + let win = e.target.ownerDocument.defaultView; + // Ignore metas which don't come from the top-level + // <iframe mozbrowser> window. + if (win != content) { + debug('Not top level!'); + return; + } + + var name = e.target.name; + var property = e.target.getAttributeNS(null, "property"); + + if (!name && !property) { + return; + } + + debug('Got metaChanged: (' + (name || property) + ') ' + + e.target.content); + + let handlers = { + 'viewmode': this._genericMetaHandler, + 'theme-color': this._genericMetaHandler, + 'theme-group': this._genericMetaHandler, + 'application-name': this._applicationNameChangedHandler + }; + let handler = handlers[name]; + + if ((property || name).match(/^og:/)) { + name = property || name; + handler = this._genericMetaHandler; + } + + if (handler) { + handler(name, e.type, e.target); + } + }, + + _applicationNameChangedHandler: function(name, eventType, target) { + if (eventType !== 'DOMMetaAdded') { + // Bug 1037448 - Decide what to do when <meta name="application-name"> + // changes + return; + } + + let meta = { name: name, + content: target.content }; + + let lang; + let elm; + + for (elm = target; + !lang && elm && elm.nodeType == target.ELEMENT_NODE; + elm = elm.parentNode) { + if (elm.hasAttribute('lang')) { + lang = elm.getAttribute('lang'); + continue; + } + + if (elm.hasAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang')) { + lang = elm.getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang'); + continue; + } + } + + // No lang has been detected. + if (!lang && elm.nodeType == target.DOCUMENT_NODE) { + lang = elm.contentLanguage; + } + + if (lang) { + meta.lang = lang; + } + + sendAsyncMsg('metachange', meta); + }, + + _ScrollViewChangeHandler: function(e) { + e.stopPropagation(); + let detail = { + state: e.state, + }; + sendAsyncMsg('scrollviewchange', detail); + }, + + _ClickHandler: function(e) { + + let isHTMLLink = node => + ((node instanceof Ci.nsIDOMHTMLAnchorElement && node.href) || + (node instanceof Ci.nsIDOMHTMLAreaElement && node.href) || + node instanceof Ci.nsIDOMHTMLLinkElement); + + // Open in a new tab if middle click or ctrl/cmd-click, + // and e.target is a link or inside a link. + if ((Services.appinfo.OS == 'Darwin' && e.metaKey) || + (Services.appinfo.OS != 'Darwin' && e.ctrlKey) || + e.button == 1) { + + let node = e.target; + while (node && !isHTMLLink(node)) { + node = node.parentNode; + } + + if (node) { + sendAsyncMsg('opentab', {url: node.href}); + } + } + }, + + _genericMetaHandler: function(name, eventType, target) { + let meta = { + name: name, + content: target.content, + type: eventType.replace('DOMMeta', '').toLowerCase() + }; + sendAsyncMsg('metachange', meta); + }, + + _addMozAfterPaintHandler: function(callback) { + function onMozAfterPaint() { + let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI; + if (uri.spec != "about:blank") { + debug("Got afterpaint event: " + uri.spec); + removeEventListener('MozAfterPaint', onMozAfterPaint, + /* useCapture = */ true); + callback(); + } + } + + addEventListener('MozAfterPaint', onMozAfterPaint, /* useCapture = */ true); + return onMozAfterPaint; + }, + + _removeMozAfterPaintHandler: function(listener) { + removeEventListener('MozAfterPaint', listener, + /* useCapture = */ true); + }, + + _activateNextPaintListener: function(e) { + if (!this._nextPaintHandler) { + this._nextPaintHandler = this._addMozAfterPaintHandler(function () { + this._nextPaintHandler = null; + sendAsyncMsg('nextpaint'); + }.bind(this)); + } + }, + + _deactivateNextPaintListener: function(e) { + if (this._nextPaintHandler) { + this._removeMozAfterPaintHandler(this._nextPaintHandler); + this._nextPaintHandler = null; + } + }, + + _windowCloseHandler: function(e) { + let win = e.target; + if (win != content || e.defaultPrevented) { + return; + } + + debug("Closing window " + win); + sendAsyncMsg('close'); + + // Inform the window implementation that we handled this close ourselves. + e.preventDefault(); + }, + + _windowCreatedHandler: function(e) { + let targetDocShell = e.target.defaultView + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation); + if (targetDocShell != docShell) { + return; + } + + let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI; + debug("Window created: " + uri.spec); + if (uri.spec != "about:blank") { + this._addMozAfterPaintHandler(function () { + sendAsyncMsg('documentfirstpaint'); + }); + this._isContentWindowCreated = true; + // Handle pending SetInputMethodActive request. + while (this._pendingSetInputMethodActive.length > 0) { + this._recvSetInputMethodActive(this._pendingSetInputMethodActive.shift()); + } + } + }, + + _windowResizeHandler: function(e) { + let win = e.target; + if (win != content || e.defaultPrevented) { + return; + } + + debug("resizing window " + win); + sendAsyncMsg('resize', { width: e.detail.width, height: e.detail.height }); + + // Inform the window implementation that we handled this resize ourselves. + e.preventDefault(); + }, + + _contextmenuHandler: function(e) { + debug("Got contextmenu"); + + if (e.defaultPrevented) { + return; + } + + this._ctxCounter++; + this._ctxHandlers = {}; + + var elem = e.target; + var menuData = {systemTargets: [], contextmenu: null}; + var ctxMenuId = null; + var clipboardPlainTextOnly = Services.prefs.getBoolPref('clipboard.plainTextOnly'); + var copyableElements = { + image: false, + link: false, + hasElements: function() { + return this.image || this.link; + } + }; + + // Set the event target as the copy image command needs it to + // determine what was context-clicked on. + docShell.contentViewer.QueryInterface(Ci.nsIContentViewerEdit).setCommandNode(elem); + + while (elem && elem.parentNode) { + var ctxData = this._getSystemCtxMenuData(elem); + if (ctxData) { + menuData.systemTargets.push({ + nodeName: elem.nodeName, + data: ctxData + }); + } + + if (!ctxMenuId && 'hasAttribute' in elem && elem.hasAttribute('contextmenu')) { + ctxMenuId = elem.getAttribute('contextmenu'); + } + + // Enable copy image/link option + if (elem.nodeName == 'IMG') { + copyableElements.image = !clipboardPlainTextOnly; + } else if (elem.nodeName == 'A') { + copyableElements.link = true; + } + + elem = elem.parentNode; + } + + if (ctxMenuId || copyableElements.hasElements()) { + var menu = null; + if (ctxMenuId) { + menu = e.target.ownerDocument.getElementById(ctxMenuId); + } + menuData.contextmenu = this._buildMenuObj(menu, '', copyableElements); + } + + // Pass along the position where the context menu should be located + menuData.clientX = e.clientX; + menuData.clientY = e.clientY; + menuData.screenX = e.screenX; + menuData.screenY = e.screenY; + + // The value returned by the contextmenu sync call is true if the embedder + // called preventDefault() on its contextmenu event. + // + // We call preventDefault() on our contextmenu event if the embedder called + // preventDefault() on /its/ contextmenu event. This way, if the embedder + // ignored the contextmenu event, TabChild will fire a click. + if (sendSyncMsg('contextmenu', menuData)[0]) { + e.preventDefault(); + } else { + this._ctxHandlers = {}; + } + }, + + _getSystemCtxMenuData: function(elem) { + let documentURI = + docShell.QueryInterface(Ci.nsIWebNavigation).currentURI.spec; + if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) || + (elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) { + return {uri: elem.href, + documentURI: documentURI, + text: elem.textContent.substring(0, kLongestReturnedString)}; + } + if (elem instanceof Ci.nsIImageLoadingContent && elem.currentURI) { + return {uri: elem.currentURI.spec, documentURI: documentURI}; + } + if (elem instanceof Ci.nsIDOMHTMLImageElement) { + return {uri: elem.src, documentURI: documentURI}; + } + if (elem instanceof Ci.nsIDOMHTMLMediaElement) { + let hasVideo = !(elem.readyState >= elem.HAVE_METADATA && + (elem.videoWidth == 0 || elem.videoHeight == 0)); + return {uri: elem.currentSrc || elem.src, + hasVideo: hasVideo, + documentURI: documentURI}; + } + if (elem instanceof Ci.nsIDOMHTMLInputElement && + elem.hasAttribute("name")) { + // For input elements, we look for a parent <form> and if there is + // one we return the form's method and action uri. + let parent = elem.parentNode; + while (parent) { + if (parent instanceof Ci.nsIDOMHTMLFormElement && + parent.hasAttribute("action")) { + let actionHref = docShell.QueryInterface(Ci.nsIWebNavigation) + .currentURI + .resolve(parent.getAttribute("action")); + let method = parent.hasAttribute("method") + ? parent.getAttribute("method").toLowerCase() + : "get"; + return { + documentURI: documentURI, + action: actionHref, + method: method, + name: elem.getAttribute("name"), + } + } + parent = parent.parentNode; + } + } + return false; + }, + + _scrollEventHandler: function(e) { + let win = e.target.defaultView; + if (win != content) { + return; + } + + debug("scroll event " + win); + sendAsyncMsg("scroll", { top: win.scrollY, left: win.scrollX }); + }, + + _recvPurgeHistory: function(data) { + debug("Received purgeHistory message: (" + data.json.id + ")"); + + let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory; + + try { + if (history && history.count) { + history.PurgeHistory(history.count); + } + } catch(e) {} + + sendAsyncMsg('got-purge-history', { id: data.json.id, successRv: true }); + }, + + _recvGetScreenshot: function(data) { + debug("Received getScreenshot message: (" + data.json.id + ")"); + + let self = this; + let maxWidth = data.json.args.width; + let maxHeight = data.json.args.height; + let mimeType = data.json.args.mimeType; + let domRequestID = data.json.id; + + let takeScreenshotClosure = function() { + self._takeScreenshot(maxWidth, maxHeight, mimeType, domRequestID); + }; + + let maxDelayMS = 2000; + try { + maxDelayMS = Services.prefs.getIntPref('dom.browserElement.maxScreenshotDelayMS'); + } + catch(e) {} + + // Try to wait for the event loop to go idle before we take the screenshot, + // but once we've waited maxDelayMS milliseconds, go ahead and take it + // anyway. + Cc['@mozilla.org/message-loop;1'].getService(Ci.nsIMessageLoop).postIdleTask( + takeScreenshotClosure, maxDelayMS); + }, + + _recvExecuteScript: function(data) { + debug("Received executeScript message: (" + data.json.id + ")"); + + let domRequestID = data.json.id; + + let sendError = errorMsg => sendAsyncMsg("execute-script-done", { + errorMsg, + id: domRequestID + }); + + let sendSuccess = successRv => sendAsyncMsg("execute-script-done", { + successRv, + id: domRequestID + }); + + let isJSON = obj => { + try { + JSON.stringify(obj); + } catch(e) { + return false; + } + return true; + } + + let expectedOrigin = data.json.args.options.origin; + let expectedUrl = data.json.args.options.url; + + if (expectedOrigin) { + if (expectedOrigin != content.location.origin) { + sendError("Origin mismatches"); + return; + } + } + + if (expectedUrl) { + let expectedURI + try { + expectedURI = Services.io.newURI(expectedUrl, null, null); + } catch(e) { + sendError("Malformed URL"); + return; + } + let currentURI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI; + if (!currentURI.equalsExceptRef(expectedURI)) { + sendError("URL mismatches"); + return; + } + } + + let sandbox = new Cu.Sandbox([content], { + sandboxPrototype: content, + sandboxName: "browser-api-execute-script", + allowWaivers: false, + sameZoneAs: content + }); + + try { + let sandboxRv = Cu.evalInSandbox(data.json.args.script, sandbox, "1.8"); + if (sandboxRv instanceof sandbox.Promise) { + sandboxRv.then(rv => { + if (isJSON(rv)) { + sendSuccess(rv); + } else { + sendError("Value returned (resolve) by promise is not a valid JSON object"); + } + }, error => { + if (isJSON(error)) { + sendError(error); + } else { + sendError("Value returned (reject) by promise is not a valid JSON object"); + } + }); + } else { + if (isJSON(sandboxRv)) { + sendSuccess(sandboxRv); + } else { + sendError("Script last expression must be a promise or a JSON object"); + } + } + } catch(e) { + sendError(e.toString()); + } + }, + + _recvGetContentDimensions: function(data) { + debug("Received getContentDimensions message: (" + data.json.id + ")"); + sendAsyncMsg('got-contentdimensions', { + id: data.json.id, + successRv: this._getContentDimensions() + }); + }, + + _mozScrollAreaChanged: function(e) { + sendAsyncMsg('scrollareachanged', { + width: e.width, + height: e.height + }); + }, + + _mozRequestedDOMFullscreen: function(e) { + sendAsyncMsg("requested-dom-fullscreen"); + }, + + _mozFullscreenOriginChange: function(e) { + sendAsyncMsg("fullscreen-origin-change", { + originNoSuffix: e.target.nodePrincipal.originNoSuffix + }); + }, + + _mozExitDomFullscreen: function(e) { + sendAsyncMsg("exit-dom-fullscreen"); + }, + + _getContentDimensions: function() { + return { + width: content.document.body.scrollWidth, + height: content.document.body.scrollHeight + } + }, + + /** + * Actually take a screenshot and foward the result up to our parent, given + * the desired maxWidth and maxHeight (in CSS pixels), and given the + * DOMRequest ID associated with the request from the parent. + */ + _takeScreenshot: function(maxWidth, maxHeight, mimeType, domRequestID) { + // You can think of the screenshotting algorithm as carrying out the + // following steps: + // + // - Calculate maxWidth, maxHeight, and viewport's width and height in the + // dimension of device pixels by multiply the numbers with + // window.devicePixelRatio. + // + // - Let scaleWidth be the factor by which we'd need to downscale the + // viewport pixel width so it would fit within maxPixelWidth. + // (If the viewport's pixel width is less than maxPixelWidth, let + // scaleWidth be 1.) Compute scaleHeight the same way. + // + // - Scale the viewport by max(scaleWidth, scaleHeight). Now either the + // viewport's width is no larger than maxWidth, the viewport's height is + // no larger than maxHeight, or both. + // + // - Crop the viewport so its width is no larger than maxWidth and its + // height is no larger than maxHeight. + // + // - Set mozOpaque to true and background color to solid white + // if we are taking a JPEG screenshot, keep transparent if otherwise. + // + // - Return a screenshot of the page's viewport scaled and cropped per + // above. + debug("Taking a screenshot: maxWidth=" + maxWidth + + ", maxHeight=" + maxHeight + + ", mimeType=" + mimeType + + ", domRequestID=" + domRequestID + "."); + + if (!content) { + // If content is not loaded yet, bail out since even sendAsyncMessage + // fails... + debug("No content yet!"); + return; + } + + let devicePixelRatio = content.devicePixelRatio; + + let maxPixelWidth = Math.round(maxWidth * devicePixelRatio); + let maxPixelHeight = Math.round(maxHeight * devicePixelRatio); + + let contentPixelWidth = content.innerWidth * devicePixelRatio; + let contentPixelHeight = content.innerHeight * devicePixelRatio; + + let scaleWidth = Math.min(1, maxPixelWidth / contentPixelWidth); + let scaleHeight = Math.min(1, maxPixelHeight / contentPixelHeight); + + let scale = Math.max(scaleWidth, scaleHeight); + + let canvasWidth = + Math.min(maxPixelWidth, Math.round(contentPixelWidth * scale)); + let canvasHeight = + Math.min(maxPixelHeight, Math.round(contentPixelHeight * scale)); + + let transparent = (mimeType !== 'image/jpeg'); + + var canvas = content.document + .createElementNS("http://www.w3.org/1999/xhtml", "canvas"); + if (!transparent) + canvas.mozOpaque = true; + canvas.width = canvasWidth; + canvas.height = canvasHeight; + + let ctx = canvas.getContext("2d", { willReadFrequently: true }); + ctx.scale(scale * devicePixelRatio, scale * devicePixelRatio); + + let flags = ctx.DRAWWINDOW_DRAW_VIEW | + ctx.DRAWWINDOW_USE_WIDGET_LAYERS | + ctx.DRAWWINDOW_DO_NOT_FLUSH | + ctx.DRAWWINDOW_ASYNC_DECODE_IMAGES; + ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight, + transparent ? "rgba(255,255,255,0)" : "rgb(255,255,255)", + flags); + + // Take a JPEG screenshot by default instead of PNG with alpha channel. + // This requires us to unpremultiply the alpha channel, which + // is expensive on ARM processors because they lack a hardware integer + // division instruction. + canvas.toBlob(function(blob) { + sendAsyncMsg('got-screenshot', { + id: domRequestID, + successRv: blob + }); + }, mimeType); + }, + + _recvFireCtxCallback: function(data) { + debug("Received fireCtxCallback message: (" + data.json.menuitem + ")"); + + let doCommandIfEnabled = (command) => { + if (docShell.isCommandEnabled(command)) { + docShell.doCommand(command); + } + }; + + if (data.json.menuitem == 'copy-image') { + doCommandIfEnabled('cmd_copyImage'); + } else if (data.json.menuitem == 'copy-link') { + doCommandIfEnabled('cmd_copyLink'); + } else if (data.json.menuitem in this._ctxHandlers) { + this._ctxHandlers[data.json.menuitem].click(); + this._ctxHandlers = {}; + } else { + // We silently ignore if the embedder uses an incorrect id in the callback + debug("Ignored invalid contextmenu invocation"); + } + }, + + _buildMenuObj: function(menu, idPrefix, copyableElements) { + var menuObj = {type: 'menu', customized: false, items: []}; + // Customized context menu + if (menu) { + this._maybeCopyAttribute(menu, menuObj, 'label'); + + for (var i = 0, child; child = menu.children[i++];) { + if (child.nodeName === 'MENU') { + menuObj.items.push(this._buildMenuObj(child, idPrefix + i + '_', false)); + } else if (child.nodeName === 'MENUITEM') { + var id = this._ctxCounter + '_' + idPrefix + i; + var menuitem = {id: id, type: 'menuitem'}; + this._maybeCopyAttribute(child, menuitem, 'label'); + this._maybeCopyAttribute(child, menuitem, 'icon'); + this._ctxHandlers[id] = child; + menuObj.items.push(menuitem); + } + } + + if (menuObj.items.length > 0) { + menuObj.customized = true; + } + } + // Note: Display "Copy Link" first in order to make sure "Copy Image" is + // put together with other image options if elem is an image link. + // "Copy Link" menu item + if (copyableElements.link) { + menuObj.items.push({id: 'copy-link'}); + } + // "Copy Image" menu item + if (copyableElements.image) { + menuObj.items.push({id: 'copy-image'}); + } + + return menuObj; + }, + + _recvSetVisible: function(data) { + debug("Received setVisible message: (" + data.json.visible + ")"); + if (this._forcedVisible == data.json.visible) { + return; + } + + this._forcedVisible = data.json.visible; + this._updateVisibility(); + }, + + _recvVisible: function(data) { + sendAsyncMsg('got-visible', { + id: data.json.id, + successRv: docShell.isActive + }); + }, + + /** + * Called when the window which contains this iframe becomes hidden or + * visible. + */ + _recvOwnerVisibilityChange: function(data) { + debug("Received ownerVisibilityChange: (" + data.json.visible + ")"); + this._ownerVisible = data.json.visible; + this._updateVisibility(); + }, + + _updateVisibility: function() { + var visible = this._forcedVisible && this._ownerVisible; + if (docShell && docShell.isActive !== visible) { + docShell.isActive = visible; + sendAsyncMsg('visibilitychange', {visible: visible}); + + // Ensure painting is not frozen if the app goes visible. + if (visible && this._paintFrozenTimer) { + this.notify(); + } + } + }, + + _recvSendMouseEvent: function(data) { + let json = data.json; + let utils = content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + utils.sendMouseEventToWindow(json.type, json.x, json.y, json.button, + json.clickCount, json.modifiers); + }, + + _recvSendTouchEvent: function(data) { + let json = data.json; + let utils = content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + utils.sendTouchEventToWindow(json.type, json.identifiers, json.touchesX, + json.touchesY, json.radiisX, json.radiisY, + json.rotationAngles, json.forces, json.count, + json.modifiers); + }, + + _recvCanGoBack: function(data) { + var webNav = docShell.QueryInterface(Ci.nsIWebNavigation); + sendAsyncMsg('got-can-go-back', { + id: data.json.id, + successRv: webNav.canGoBack + }); + }, + + _recvCanGoForward: function(data) { + var webNav = docShell.QueryInterface(Ci.nsIWebNavigation); + sendAsyncMsg('got-can-go-forward', { + id: data.json.id, + successRv: webNav.canGoForward + }); + }, + + _recvMute: function(data) { + this._windowUtils.audioMuted = true; + }, + + _recvUnmute: function(data) { + this._windowUtils.audioMuted = false; + }, + + _recvGetMuted: function(data) { + sendAsyncMsg('got-muted', { + id: data.json.id, + successRv: this._windowUtils.audioMuted + }); + }, + + _recvSetVolume: function(data) { + this._windowUtils.audioVolume = data.json.volume; + }, + + _recvGetVolume: function(data) { + sendAsyncMsg('got-volume', { + id: data.json.id, + successRv: this._windowUtils.audioVolume + }); + }, + + _recvGoBack: function(data) { + try { + docShell.QueryInterface(Ci.nsIWebNavigation).goBack(); + } catch(e) { + // Silently swallow errors; these happen when we can't go back. + } + }, + + _recvGoForward: function(data) { + try { + docShell.QueryInterface(Ci.nsIWebNavigation).goForward(); + } catch(e) { + // Silently swallow errors; these happen when we can't go forward. + } + }, + + _recvReload: function(data) { + let webNav = docShell.QueryInterface(Ci.nsIWebNavigation); + let reloadFlags = data.json.hardReload ? + webNav.LOAD_FLAGS_BYPASS_PROXY | webNav.LOAD_FLAGS_BYPASS_CACHE : + webNav.LOAD_FLAGS_NONE; + try { + webNav.reload(reloadFlags); + } catch(e) { + // Silently swallow errors; these can happen if a used cancels reload + } + }, + + _recvStop: function(data) { + let webNav = docShell.QueryInterface(Ci.nsIWebNavigation); + webNav.stop(webNav.STOP_NETWORK); + }, + + _recvZoom: function(data) { + docShell.contentViewer.fullZoom = data.json.zoom; + }, + + _recvGetAudioChannelVolume: function(data) { + debug("Received getAudioChannelVolume message: (" + data.json.id + ")"); + + let volume = acs.getAudioChannelVolume(content, + data.json.args.audioChannel); + sendAsyncMsg('got-audio-channel-volume', { + id: data.json.id, successRv: volume + }); + }, + + _recvSetAudioChannelVolume: function(data) { + debug("Received setAudioChannelVolume message: (" + data.json.id + ")"); + + acs.setAudioChannelVolume(content, + data.json.args.audioChannel, + data.json.args.volume); + sendAsyncMsg('got-set-audio-channel-volume', { + id: data.json.id, successRv: true + }); + }, + + _recvGetAudioChannelMuted: function(data) { + debug("Received getAudioChannelMuted message: (" + data.json.id + ")"); + + let muted = acs.getAudioChannelMuted(content, data.json.args.audioChannel); + sendAsyncMsg('got-audio-channel-muted', { + id: data.json.id, successRv: muted + }); + }, + + _recvSetAudioChannelMuted: function(data) { + debug("Received setAudioChannelMuted message: (" + data.json.id + ")"); + + acs.setAudioChannelMuted(content, data.json.args.audioChannel, + data.json.args.muted); + sendAsyncMsg('got-set-audio-channel-muted', { + id: data.json.id, successRv: true + }); + }, + + _recvIsAudioChannelActive: function(data) { + debug("Received isAudioChannelActive message: (" + data.json.id + ")"); + + let active = acs.isAudioChannelActive(content, data.json.args.audioChannel); + sendAsyncMsg('got-is-audio-channel-active', { + id: data.json.id, successRv: active + }); + }, + _recvGetWebManifest: Task.async(function* (data) { + debug(`Received GetWebManifest message: (${data.json.id})`); + let manifest = null; + let hasManifest = ManifestFinder.contentHasManifestLink(content); + if (hasManifest) { + try { + manifest = yield ManifestObtainer.contentObtainManifest(content); + } catch (e) { + sendAsyncMsg('got-web-manifest', { + id: data.json.id, + errorMsg: `Error fetching web manifest: ${e}.`, + }); + return; + } + } + sendAsyncMsg('got-web-manifest', { + id: data.json.id, + successRv: manifest + }); + }), + + _initFinder: function() { + if (!this._finder) { + let {Finder} = Components.utils.import("resource://gre/modules/Finder.jsm", {}); + this._finder = new Finder(docShell); + } + let listener = { + onMatchesCountResult: (data) => { + sendAsyncMsg("findchange", { + active: true, + searchString: this._finder.searchString, + searchLimit: this._finder.matchesCountLimit, + activeMatchOrdinal: data.current, + numberOfMatches: data.total + }); + this._finder.removeResultListener(listener); + } + }; + this._finder.addResultListener(listener); + }, + + _recvFindAll: function(data) { + this._initFinder(); + let searchString = data.json.searchString; + this._finder.caseSensitive = data.json.caseSensitive; + this._finder.fastFind(searchString, false, false); + this._finder.requestMatchesCount(searchString, this._finder.matchesCountLimit, false); + }, + + _recvFindNext: function(data) { + if (!this._finder) { + debug("findNext() called before findAll()"); + return; + } + this._initFinder(); + this._finder.findAgain(data.json.backward, false, false); + this._finder.requestMatchesCount(this._finder.searchString, this._finder.matchesCountLimit, false); + }, + + _recvClearMatch: function(data) { + if (!this._finder) { + debug("clearMach() called before findAll()"); + return; + } + this._finder.removeSelection(); + sendAsyncMsg("findchange", {active: false}); + }, + + _recvSetInputMethodActive: function(data) { + let msgData = { id: data.json.id }; + if (!this._isContentWindowCreated) { + if (data.json.args.isActive) { + // To activate the input method, we should wait before the content + // window is ready. + this._pendingSetInputMethodActive.push(data); + return; + } + msgData.successRv = null; + sendAsyncMsg('got-set-input-method-active', msgData); + return; + } + // Unwrap to access webpage content. + let nav = XPCNativeWrapper.unwrap(content.document.defaultView.navigator); + if (nav.mozInputMethod) { + // Wrap to access the chrome-only attribute setActive. + new XPCNativeWrapper(nav.mozInputMethod).setActive(data.json.args.isActive); + msgData.successRv = null; + } else { + msgData.errorMsg = 'Cannot access mozInputMethod.'; + } + sendAsyncMsg('got-set-input-method-active', msgData); + }, + + // The docShell keeps a weak reference to the progress listener, so we need + // to keep a strong ref to it ourselves. + _progressListener: { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, + Ci.nsISupportsWeakReference]), + _seenLoadStart: false, + + onLocationChange: function(webProgress, request, location, flags) { + // We get progress events from subshells here, which is kind of weird. + if (webProgress != docShell) { + return; + } + + // Ignore locationchange events which occur before the first loadstart. + // These are usually about:blank loads we don't care about. + if (!this._seenLoadStart) { + return; + } + + // Remove password and wyciwyg from uri. + location = Cc["@mozilla.org/docshell/urifixup;1"] + .getService(Ci.nsIURIFixup).createExposableURI(location); + + var webNav = docShell.QueryInterface(Ci.nsIWebNavigation); + + sendAsyncMsg('locationchange', { url: location.spec, + canGoBack: webNav.canGoBack, + canGoForward: webNav.canGoForward }); + }, + + onStateChange: function(webProgress, request, stateFlags, status) { + if (webProgress != docShell) { + return; + } + + if (stateFlags & Ci.nsIWebProgressListener.STATE_START) { + this._seenLoadStart = true; + sendAsyncMsg('loadstart'); + } + + if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) { + let bgColor = 'transparent'; + try { + bgColor = content.getComputedStyle(content.document.body) + .getPropertyValue('background-color'); + } catch (e) {} + sendAsyncMsg('loadend', {backgroundColor: bgColor}); + + switch (status) { + case Cr.NS_OK : + case Cr.NS_BINDING_ABORTED : + // Ignoring NS_BINDING_ABORTED, which is set when loading page is + // stopped. + case Cr.NS_ERROR_PARSED_DATA_CACHED: + return; + + // TODO See nsDocShell::DisplayLoadError to see what extra + // information we should be annotating this first block of errors + // with. Bug 1107091. + case Cr.NS_ERROR_UNKNOWN_PROTOCOL : + sendAsyncMsg('error', { type: 'unknownProtocolFound' }); + return; + case Cr.NS_ERROR_FILE_NOT_FOUND : + sendAsyncMsg('error', { type: 'fileNotFound' }); + return; + case Cr.NS_ERROR_UNKNOWN_HOST : + sendAsyncMsg('error', { type: 'dnsNotFound' }); + return; + case Cr.NS_ERROR_CONNECTION_REFUSED : + sendAsyncMsg('error', { type: 'connectionFailure' }); + return; + case Cr.NS_ERROR_NET_INTERRUPT : + sendAsyncMsg('error', { type: 'netInterrupt' }); + return; + case Cr.NS_ERROR_NET_TIMEOUT : + sendAsyncMsg('error', { type: 'netTimeout' }); + return; + case Cr.NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION : + sendAsyncMsg('error', { type: 'cspBlocked' }); + return; + case Cr.NS_ERROR_PHISHING_URI : + sendAsyncMsg('error', { type: 'deceptiveBlocked' }); + return; + case Cr.NS_ERROR_MALWARE_URI : + sendAsyncMsg('error', { type: 'malwareBlocked' }); + return; + case Cr.NS_ERROR_UNWANTED_URI : + sendAsyncMsg('error', { type: 'unwantedBlocked' }); + return; + case Cr.NS_ERROR_FORBIDDEN_URI : + sendAsyncMsg('error', { type: 'forbiddenBlocked' }); + return; + + case Cr.NS_ERROR_OFFLINE : + sendAsyncMsg('error', { type: 'offline' }); + return; + case Cr.NS_ERROR_MALFORMED_URI : + sendAsyncMsg('error', { type: 'malformedURI' }); + return; + case Cr.NS_ERROR_REDIRECT_LOOP : + sendAsyncMsg('error', { type: 'redirectLoop' }); + return; + case Cr.NS_ERROR_UNKNOWN_SOCKET_TYPE : + sendAsyncMsg('error', { type: 'unknownSocketType' }); + return; + case Cr.NS_ERROR_NET_RESET : + sendAsyncMsg('error', { type: 'netReset' }); + return; + case Cr.NS_ERROR_DOCUMENT_NOT_CACHED : + sendAsyncMsg('error', { type: 'notCached' }); + return; + case Cr.NS_ERROR_DOCUMENT_IS_PRINTMODE : + sendAsyncMsg('error', { type: 'isprinting' }); + return; + case Cr.NS_ERROR_PORT_ACCESS_NOT_ALLOWED : + sendAsyncMsg('error', { type: 'deniedPortAccess' }); + return; + case Cr.NS_ERROR_UNKNOWN_PROXY_HOST : + sendAsyncMsg('error', { type: 'proxyResolveFailure' }); + return; + case Cr.NS_ERROR_PROXY_CONNECTION_REFUSED : + sendAsyncMsg('error', { type: 'proxyConnectFailure' }); + return; + case Cr.NS_ERROR_INVALID_CONTENT_ENCODING : + sendAsyncMsg('error', { type: 'contentEncodingFailure' }); + return; + case Cr.NS_ERROR_REMOTE_XUL : + sendAsyncMsg('error', { type: 'remoteXUL' }); + return; + case Cr.NS_ERROR_UNSAFE_CONTENT_TYPE : + sendAsyncMsg('error', { type: 'unsafeContentType' }); + return; + case Cr.NS_ERROR_CORRUPTED_CONTENT : + sendAsyncMsg('error', { type: 'corruptedContentErrorv2' }); + return; + + default: + // getErrorClass() will throw if the error code passed in is not a NSS + // error code. + try { + let nssErrorsService = Cc['@mozilla.org/nss_errors_service;1'] + .getService(Ci.nsINSSErrorsService); + if (nssErrorsService.getErrorClass(status) + == Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT) { + // XXX Is there a point firing the event if the error page is not + // certerror? If yes, maybe we should add a property to the + // event to to indicate whether there is a custom page. That would + // let the embedder have more control over the desired behavior. + let errorPage = null; + try { + errorPage = Services.prefs.getCharPref(CERTIFICATE_ERROR_PAGE_PREF); + } catch (e) {} + + if (errorPage == 'certerror') { + sendAsyncMsg('error', { type: 'certerror' }); + return; + } + } + } catch (e) {} + + sendAsyncMsg('error', { type: 'other' }); + return; + } + } + }, + + onSecurityChange: function(webProgress, request, state) { + if (webProgress != docShell) { + return; + } + + var securityStateDesc; + if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) { + securityStateDesc = 'secure'; + } + else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) { + securityStateDesc = 'broken'; + } + else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) { + securityStateDesc = 'insecure'; + } + else { + debug("Unexpected securitychange state!"); + securityStateDesc = '???'; + } + + var trackingStateDesc; + if (state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT) { + trackingStateDesc = 'loaded_tracking_content'; + } + else if (state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) { + trackingStateDesc = 'blocked_tracking_content'; + } + + var mixedStateDesc; + if (state & Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT) { + mixedStateDesc = 'blocked_mixed_active_content'; + } + else if (state & Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) { + // Note that STATE_LOADED_MIXED_ACTIVE_CONTENT implies STATE_IS_BROKEN + mixedStateDesc = 'loaded_mixed_active_content'; + } + + var isEV = !!(state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL); + var isTrackingContent = !!(state & + (Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT | + Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)); + var isMixedContent = !!(state & + (Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT | + Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT)); + + sendAsyncMsg('securitychange', { + state: securityStateDesc, + trackingState: trackingStateDesc, + mixedState: mixedStateDesc, + extendedValidation: isEV, + trackingContent: isTrackingContent, + mixedContent: isMixedContent, + }); + }, + + onStatusChange: function(webProgress, request, status, message) {}, + onProgressChange: function(webProgress, request, curSelfProgress, + maxSelfProgress, curTotalProgress, maxTotalProgress) {}, + }, + + // Expose the message manager for WebApps and others. + _messageManagerPublic: { + sendAsyncMessage: global.sendAsyncMessage.bind(global), + sendSyncMessage: global.sendSyncMessage.bind(global), + addMessageListener: global.addMessageListener.bind(global), + removeMessageListener: global.removeMessageListener.bind(global) + }, + + get messageManager() { + return this._messageManagerPublic; + } +}; + +var api = null; +if ('DoPreloadPostfork' in this && typeof this.DoPreloadPostfork === 'function') { + // If we are preloaded, instantiate BrowserElementChild after a content + // process is forked. + this.DoPreloadPostfork(function() { + api = new BrowserElementChild(); + }); +} else { + api = new BrowserElementChild(); +} diff --git a/dom/browser-element/BrowserElementCopyPaste.js b/dom/browser-element/BrowserElementCopyPaste.js new file mode 100644 index 000000000..7aa7c5148 --- /dev/null +++ b/dom/browser-element/BrowserElementCopyPaste.js @@ -0,0 +1,125 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- / +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* 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/. */ + +"use strict"; + +function debug(msg) { + // dump("BrowserElementCopyPaste - " + msg + "\n"); +} + +debug("loaded"); + +var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; + +var CopyPasteAssistent = { + COMMAND_MAP: { + 'cut': 'cmd_cut', + 'copy': 'cmd_copyAndCollapseToEnd', + 'paste': 'cmd_paste', + 'selectall': 'cmd_selectAll' + }, + + init: function() { + addEventListener("mozcaretstatechanged", this, + /* useCapture = */ true, /* wantsUntrusted = */ false); + addMessageListener("browser-element-api:call", this); + }, + + destroy: function() { + removeEventListener("mozcaretstatechanged", this, + /* useCapture = */ true, /* wantsUntrusted = */ false); + removeMessageListener("browser-element-api:call", this); + }, + + handleEvent: function(event) { + switch (event.type) { + case "mozcaretstatechanged": + this._caretStateChangedHandler(event); + break; + } + }, + + receiveMessage: function(message) { + switch (message.name) { + case "browser-element-api:call": + this._browserAPIHandler(message); + break; + } + }, + + _browserAPIHandler: function(e) { + switch (e.data.msg_name) { + case 'copypaste-do-command': + if (this._isCommandEnabled(e.data.command)) { + docShell.doCommand(this.COMMAND_MAP[e.data.command]); + } + break; + } + }, + + _isCommandEnabled: function(cmd) { + let command = this.COMMAND_MAP[cmd]; + if (!command) { + return false; + } + + return docShell.isCommandEnabled(command); + }, + + _caretStateChangedHandler: function(e) { + e.stopPropagation(); + + let boundingClientRect = e.boundingClientRect; + let canPaste = this._isCommandEnabled("paste"); + let zoomFactor = content.innerWidth == 0 ? 1 : content.screen.width / content.innerWidth; + + let detail = { + rect: { + width: boundingClientRect ? boundingClientRect.width : 0, + height: boundingClientRect ? boundingClientRect.height : 0, + top: boundingClientRect ? boundingClientRect.top : 0, + bottom: boundingClientRect ? boundingClientRect.bottom : 0, + left: boundingClientRect ? boundingClientRect.left : 0, + right: boundingClientRect ? boundingClientRect.right : 0, + }, + commands: { + canSelectAll: this._isCommandEnabled("selectall"), + canCut: this._isCommandEnabled("cut"), + canCopy: this._isCommandEnabled("copy"), + canPaste: this._isCommandEnabled("paste"), + }, + zoomFactor: zoomFactor, + reason: e.reason, + collapsed: e.collapsed, + caretVisible: e.caretVisible, + selectionVisible: e.selectionVisible, + selectionEditable: e.selectionEditable, + selectedTextContent: e.selectedTextContent + }; + + // Get correct geometry information if we have nested iframe. + let currentWindow = e.target.defaultView; + while (currentWindow.realFrameElement) { + let currentRect = currentWindow.realFrameElement.getBoundingClientRect(); + detail.rect.top += currentRect.top; + detail.rect.bottom += currentRect.top; + detail.rect.left += currentRect.left; + detail.rect.right += currentRect.left; + currentWindow = currentWindow.realFrameElement.ownerDocument.defaultView; + + let targetDocShell = currentWindow + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation); + if(targetDocShell.isMozBrowserOrApp) { + break; + } + } + + sendAsyncMsg('caretstatechanged', detail); + }, +}; + +CopyPasteAssistent.init(); diff --git a/dom/browser-element/BrowserElementParent.cpp b/dom/browser-element/BrowserElementParent.cpp new file mode 100644 index 000000000..fda9348fd --- /dev/null +++ b/dom/browser-element/BrowserElementParent.cpp @@ -0,0 +1,317 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "TabParent.h" + +// TabParent.h transitively includes <windows.h>, which does +// #define CreateEvent CreateEventW +// That messes up our call to EventDispatcher::CreateEvent below. + +#ifdef CreateEvent +#undef CreateEvent +#endif + +#include "BrowserElementParent.h" +#include "BrowserElementAudioChannel.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/dom/HTMLIFrameElement.h" +#include "mozilla/dom/ToJSValue.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsVariant.h" +#include "mozilla/dom/BrowserElementDictionariesBinding.h" +#include "mozilla/dom/CustomEvent.h" +#include "mozilla/layout/RenderFrameParent.h" + +using namespace mozilla; +using namespace mozilla::dom; +using namespace mozilla::layers; +using namespace mozilla::layout; + +namespace { + +using mozilla::BrowserElementParent; +/** + * Create an <iframe mozbrowser> owned by the same document as + * aOpenerFrameElement. + */ +already_AddRefed<HTMLIFrameElement> +CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote) +{ + nsNodeInfoManager *nodeInfoManager = + aOpenerFrameElement->OwnerDoc()->NodeInfoManager(); + + RefPtr<NodeInfo> nodeInfo = + nodeInfoManager->GetNodeInfo(nsGkAtoms::iframe, + /* aPrefix = */ nullptr, + kNameSpaceID_XHTML, + nsIDOMNode::ELEMENT_NODE); + + RefPtr<HTMLIFrameElement> popupFrameElement = + static_cast<HTMLIFrameElement*>( + NS_NewHTMLIFrameElement(nodeInfo.forget(), mozilla::dom::NOT_FROM_PARSER)); + + popupFrameElement->SetMozbrowser(true); + + // Copy the opener frame's mozapp attribute to the popup frame. + if (aOpenerFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozapp)) { + nsAutoString mozapp; + aOpenerFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, mozapp); + popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, + mozapp, /* aNotify = */ false); + } + + // Copy the opener frame's parentApp attribute to the popup frame. + if (aOpenerFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::parentapp)) { + nsAutoString parentApp; + aOpenerFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::parentapp, + parentApp); + popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::parentapp, + parentApp, /* aNotify = */ false); + } + + // Copy the window name onto the iframe. + popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::name, + aName, /* aNotify = */ false); + + // Indicate whether the iframe is should be remote. + popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::Remote, + aRemote ? NS_LITERAL_STRING("true") : + NS_LITERAL_STRING("false"), + /* aNotify = */ false); + + // Copy the opener frame's mozprivatebrowsing attribute to the popup frame. + nsAutoString mozprivatebrowsing; + if (aOpenerFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing, + mozprivatebrowsing)) { + popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing, + mozprivatebrowsing, /* aNotify = */ false); + } + + return popupFrameElement.forget(); +} + +bool +DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName, + JSContext* cx, JS::Handle<JS::Value> aDetailValue, + nsEventStatus *aStatus) +{ + NS_ENSURE_TRUE(aFrameElement, false); + nsIPresShell *shell = aFrameElement->OwnerDoc()->GetShell(); + RefPtr<nsPresContext> presContext; + if (shell) { + presContext = shell->GetPresContext(); + } + + RefPtr<CustomEvent> event = + NS_NewDOMCustomEvent(aFrameElement, presContext, nullptr); + + ErrorResult res; + event->InitCustomEvent(cx, + aEventName, + /* aCanBubble = */ true, + /* aCancelable = */ true, + aDetailValue, + res); + if (res.Failed()) { + return false; + } + event->SetTrusted(true); + // Dispatch the event. + // We don't initialize aStatus here, as our callers have already done so. + nsresult rv = + EventDispatcher::DispatchDOMEvent(aFrameElement, nullptr, event, + presContext, aStatus); + return NS_SUCCEEDED(rv); +} + +} // namespace + +namespace mozilla { + +/** + * Dispatch a mozbrowseropenwindow event to the given opener frame element. + * The "popup iframe" (event.detail.frameElement) will be |aPopupFrameElement|. + * + * Returns true iff there were no unexpected failures and the window.open call + * was accepted by the embedder. + */ +/*static*/ +BrowserElementParent::OpenWindowResult +BrowserElementParent::DispatchOpenWindowEvent(Element* aOpenerFrameElement, + Element* aPopupFrameElement, + const nsAString& aURL, + const nsAString& aName, + const nsAString& aFeatures) +{ + // Dispatch a CustomEvent at aOpenerFrameElement with a detail object + // (OpenWindowEventDetail) containing aPopupFrameElement, aURL, aName, and + // aFeatures. + + // Create the event's detail object. + OpenWindowEventDetail detail; + if (aURL.IsEmpty()) { + // URL should never be empty. Assign about:blank as default. + detail.mUrl = NS_LITERAL_STRING("about:blank"); + } else { + detail.mUrl = aURL; + } + detail.mName = aName; + detail.mFeatures = aFeatures; + detail.mFrameElement = aPopupFrameElement; + + AutoJSContext cx; + JS::Rooted<JS::Value> val(cx); + + nsIGlobalObject* sgo = aPopupFrameElement->OwnerDoc()->GetScopeObject(); + if (!sgo) { + return BrowserElementParent::OPEN_WINDOW_IGNORED; + } + + JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject()); + JSAutoCompartment ac(cx, global); + if (!ToJSValue(cx, detail, &val)) { + MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM."); + return BrowserElementParent::OPEN_WINDOW_IGNORED; + } + + nsEventStatus status = nsEventStatus_eIgnore; + bool dispatchSucceeded = + DispatchCustomDOMEvent(aOpenerFrameElement, + NS_LITERAL_STRING("mozbrowseropenwindow"), + cx, + val, &status); + + if (dispatchSucceeded) { + if (aPopupFrameElement->IsInUncomposedDoc()) { + return BrowserElementParent::OPEN_WINDOW_ADDED; + } else if (status == nsEventStatus_eConsumeNoDefault) { + // If the frame was not added to a document, report to callers whether + // preventDefault was called on or not + return BrowserElementParent::OPEN_WINDOW_CANCELLED; + } + } + + return BrowserElementParent::OPEN_WINDOW_IGNORED; +} + +/*static*/ +BrowserElementParent::OpenWindowResult +BrowserElementParent::OpenWindowOOP(TabParent* aOpenerTabParent, + TabParent* aPopupTabParent, + PRenderFrameParent* aRenderFrame, + const nsAString& aURL, + const nsAString& aName, + const nsAString& aFeatures, + TextureFactoryIdentifier* aTextureFactoryIdentifier, + uint64_t* aLayersId) +{ + // Create an iframe owned by the same document which owns openerFrameElement. + nsCOMPtr<Element> openerFrameElement = aOpenerTabParent->GetOwnerElement(); + NS_ENSURE_TRUE(openerFrameElement, + BrowserElementParent::OPEN_WINDOW_IGNORED); + RefPtr<HTMLIFrameElement> popupFrameElement = + CreateIframe(openerFrameElement, aName, /* aRemote = */ true); + + // Normally an <iframe> element will try to create a frameLoader when the + // page touches iframe.contentWindow or sets iframe.src. + // + // But in our case, we want to delay the creation of the frameLoader until + // we've verified that the popup has gone through successfully. If the popup + // is "blocked" by the embedder, we don't want to load the popup's url. + // + // Therefore we call DisallowCreateFrameLoader() on the element and call + // AllowCreateFrameLoader() only after we've verified that the popup was + // allowed. + popupFrameElement->DisallowCreateFrameLoader(); + + OpenWindowResult opened = + DispatchOpenWindowEvent(openerFrameElement, popupFrameElement, + aURL, aName, aFeatures); + + if (opened != BrowserElementParent::OPEN_WINDOW_ADDED) { + return opened; + } + + // The popup was not blocked, so hook up the frame element and the popup tab + // parent, and return success. + aPopupTabParent->SetOwnerElement(popupFrameElement); + popupFrameElement->AllowCreateFrameLoader(); + popupFrameElement->CreateRemoteFrameLoader(aPopupTabParent); + + RenderFrameParent* rfp = static_cast<RenderFrameParent*>(aRenderFrame); + if (!aPopupTabParent->SetRenderFrame(rfp) || + !aPopupTabParent->GetRenderFrameInfo(aTextureFactoryIdentifier, aLayersId)) { + return BrowserElementParent::OPEN_WINDOW_IGNORED; + } + + return opened; +} + +/* static */ +BrowserElementParent::OpenWindowResult +BrowserElementParent::OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow, + nsIURI* aURI, + const nsAString& aName, + const nsACString& aFeatures, + bool aForceNoOpener, + mozIDOMWindowProxy** aReturnWindow) +{ + *aReturnWindow = nullptr; + + // If we call window.open from an <iframe> inside an <iframe mozbrowser>, + // it's as though the top-level document inside the <iframe mozbrowser> + // called window.open. (Indeed, in the OOP case, the inner <iframe> lives + // out-of-process, so we couldn't touch it if we tried.) + // + // GetScriptableTop gets us the <iframe mozbrowser>'s window; we'll use its + // frame element, rather than aOpenerWindow's frame element, as our "opener + // frame element" below. + nsCOMPtr<nsPIDOMWindowOuter> win = aOpenerWindow->GetScriptableTop(); + + nsCOMPtr<Element> openerFrameElement = win->GetFrameElementInternal(); + NS_ENSURE_TRUE(openerFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED); + + + RefPtr<HTMLIFrameElement> popupFrameElement = + CreateIframe(openerFrameElement, aName, /* aRemote = */ false); + NS_ENSURE_TRUE(popupFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED); + + nsAutoCString spec; + if (aURI) { + aURI->GetSpec(spec); + } + + if (!aForceNoOpener) { + ErrorResult res; + popupFrameElement->PresetOpenerWindow(aOpenerWindow, res); + MOZ_ASSERT(!res.Failed()); + } + + OpenWindowResult opened = + DispatchOpenWindowEvent(openerFrameElement, popupFrameElement, + NS_ConvertUTF8toUTF16(spec), + aName, + NS_ConvertUTF8toUTF16(aFeatures)); + + if (opened != BrowserElementParent::OPEN_WINDOW_ADDED) { + return opened; + } + + // Return popupFrameElement's window. + RefPtr<nsFrameLoader> frameLoader = popupFrameElement->GetFrameLoader(); + NS_ENSURE_TRUE(frameLoader, BrowserElementParent::OPEN_WINDOW_IGNORED); + + nsCOMPtr<nsIDocShell> docshell; + frameLoader->GetDocShell(getter_AddRefs(docshell)); + NS_ENSURE_TRUE(docshell, BrowserElementParent::OPEN_WINDOW_IGNORED); + + nsCOMPtr<nsPIDOMWindowOuter> window = docshell->GetWindow(); + window.forget(aReturnWindow); + + return !!*aReturnWindow ? opened : BrowserElementParent::OPEN_WINDOW_CANCELLED; +} + +} // namespace mozilla diff --git a/dom/browser-element/BrowserElementParent.h b/dom/browser-element/BrowserElementParent.h new file mode 100644 index 000000000..428884f97 --- /dev/null +++ b/dom/browser-element/BrowserElementParent.h @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_BrowserElementHelpers_h +#define mozilla_BrowserElementHelpers_h + +#include "nsAString.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/gfx/Rect.h" +#include "Units.h" +#include "mozilla/dom/Element.h" + +class nsIDOMWindow; +class nsIURI; + +namespace mozilla { + +namespace dom { +class TabParent; +} // namespace dom + +namespace layers { +struct TextureFactoryIdentifier; +} // namespace layers + +namespace layout { +class PRenderFrameParent; +} // namespace layout + +/** + * BrowserElementParent implements a portion of the parent-process side of + * <iframe mozbrowser>. + * + * Most of the parent-process side of <iframe mozbrowser> is implemented in + * BrowserElementParent.js. This file implements the few parts of this + * functionality which must be written in C++. + * + * We don't communicate with the JS code that lives in BrowserElementParent.js; + * the JS and C++ parts are completely separate. + */ +class BrowserElementParent +{ +public: + + /** + * Possible results from a window.open call. + * ADDED - The frame was added to a document (i.e. handled by the embedder). + * IGNORED - The frame was not added to a document and the embedder didn't + * call preventDefault() to prevent the platform from handling the call. + * CANCELLED - The frame was not added to a document, but the embedder still + * called preventDefault() to prevent the platform from handling the call. + */ + + enum OpenWindowResult { + OPEN_WINDOW_ADDED, + OPEN_WINDOW_IGNORED, + OPEN_WINDOW_CANCELLED + }; + + /** + * Handle a window.open call from an out-of-process <iframe mozbrowser>. + * + * window.open inside <iframe mozbrowser> doesn't actually open a new + * top-level window. Instead, the "embedder" (the document which contains + * the <iframe mozbrowser> whose content called window.open) gets the + * opportunity to place a new <iframe mozbrowser> in the DOM somewhere. This + * new "popup" iframe acts as the opened window. + * + * This method proceeds in three steps. + * + * 1) We fire a mozbrowseropenwindow CustomEvent on the opener + * iframe element. This event's detail is an instance of + * OpenWindowEventDetail. + * + * 2) The embedder (the document which contains the opener iframe) can accept + * the window.open request by inserting event.detail.frameElement (an iframe + * element) into the DOM somewhere. + * + * 3) If the embedder accepted the window.open request, we return true and + * set aPopupTabParent's frame element to event.detail.frameElement. + * Otherwise, we return false. + * + * @param aURL the URL the new window should load. The empty string is + * allowed. + * @param aOpenerTabParent the TabParent whose TabChild called window.open. + * @param aPopupTabParent the TabParent inside which the opened window will + * live. + * @return an OpenWindowresult that describes whether the embedder added the + * frame to a document and whether it called preventDefault to prevent + * the platform from handling the open request. + */ + static OpenWindowResult + OpenWindowOOP(dom::TabParent* aOpenerTabParent, + dom::TabParent* aPopupTabParent, + layout::PRenderFrameParent* aRenderFrame, + const nsAString& aURL, + const nsAString& aName, + const nsAString& aFeatures, + layers::TextureFactoryIdentifier* aTextureFactoryIdentifier, + uint64_t* aLayersId); + + /** + * Handle a window.open call from an in-process <iframe mozbrowser>. + * + * (These parameter types are silly, but they match what our caller has in + * hand. Feel free to add an override, if they are inconvenient to you.) + * + * @param aURI the URI the new window should load. May be null. + * @return an OpenWindowResult that describes whether the browser added the + * frame to a document or whether they called preventDefault to prevent + * the platform from handling the open request + */ + static OpenWindowResult + OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow, + nsIURI* aURI, + const nsAString& aName, + const nsACString& aFeatures, + bool aForceNoOpener, + mozIDOMWindowProxy** aReturnWindow); + +private: + static OpenWindowResult + DispatchOpenWindowEvent(dom::Element* aOpenerFrameElement, + dom::Element* aPopupFrameElement, + const nsAString& aURL, + const nsAString& aName, + const nsAString& aFeatures); +}; + +} // namespace mozilla + +#endif diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js new file mode 100644 index 000000000..67d05f0ab --- /dev/null +++ b/dom/browser-element/BrowserElementParent.js @@ -0,0 +1,1202 @@ +/* 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/. */ + +"use strict"; + +var Cu = Components.utils; +var Ci = Components.interfaces; +var Cc = Components.classes; +var Cr = Components.results; + +/* BrowserElementParent injects script to listen for certain events in the + * child. We then listen to messages from the child script and take + * appropriate action here in the parent. + */ + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/BrowserElementPromptService.jsm"); + +function debug(msg) { + //dump("BrowserElementParent - " + msg + "\n"); +} + +function getIntPref(prefName, def) { + try { + return Services.prefs.getIntPref(prefName); + } + catch(err) { + return def; + } +} + +function handleWindowEvent(e) { + if (this._browserElementParents) { + let beps = ThreadSafeChromeUtils.nondeterministicGetWeakMapKeys(this._browserElementParents); + beps.forEach(bep => bep._handleOwnerEvent(e)); + } +} + +function defineNoReturnMethod(fn) { + return function method() { + if (!this._domRequestReady) { + // Remote browser haven't been created, we just queue the API call. + let args = Array.slice(arguments); + args.unshift(this); + this._pendingAPICalls.push(method.bind.apply(fn, args)); + return; + } + if (this._isAlive()) { + fn.apply(this, arguments); + } + }; +} + +function defineDOMRequestMethod(msgName) { + return function() { + return this._sendDOMRequest(msgName); + }; +} + +function BrowserElementParentProxyCallHandler() { +} + +BrowserElementParentProxyCallHandler.prototype = { + _frameElement: null, + _mm: null, + + MOZBROWSER_EVENT_NAMES: Object.freeze([ + "loadstart", "loadend", "close", "error", "firstpaint", + "documentfirstpaint", "audioplaybackchange", + "contextmenu", "securitychange", "locationchange", + "iconchange", "scrollareachanged", "titlechange", + "opensearch", "manifestchange", "metachange", + "resize", "scrollviewchange", + "caretstatechanged", "activitydone", "scroll", "opentab"]), + + init: function(frameElement, mm) { + this._frameElement = frameElement; + this._mm = mm; + this.innerWindowIDSet = new Set(); + + mm.addMessageListener("browser-element-api:proxy-call", this); + }, + + // Message manager callback receives messages from BrowserElementProxy.js + receiveMessage: function(mmMsg) { + let data = mmMsg.json; + + let mm; + try { + mm = mmMsg.target.QueryInterface(Ci.nsIFrameLoaderOwner) + .frameLoader.messageManager; + } catch(e) { + mm = mmMsg.target; + } + if (!mm.assertPermission("browser:embedded-system-app")) { + dump("BrowserElementParent.js: Method call " + data.methodName + + " from a content process with no 'browser:embedded-system-app'" + + " privileges.\n"); + return; + } + + switch (data.methodName) { + case '_proxyInstanceInit': + if (!this.innerWindowIDSet.size) { + this._attachEventListeners(); + } + this.innerWindowIDSet.add(data.innerWindowID); + + break; + + case '_proxyInstanceUninit': + this.innerWindowIDSet.delete(data.innerWindowID); + if (!this.innerWindowIDSet.size) { + this._detachEventListeners(); + } + + break; + + // void methods + case 'setVisible': + case 'setActive': + case 'sendMouseEvent': + case 'sendTouchEvent': + case 'goBack': + case 'goForward': + case 'reload': + case 'stop': + case 'zoom': + case 'findAll': + case 'findNext': + case 'clearMatch': + case 'mute': + case 'unmute': + case 'setVolume': + this._frameElement[data.methodName] + .apply(this._frameElement, data.args); + + break; + + // DOMRequest methods + case 'getVisible': + case 'download': + case 'purgeHistory': + case 'getCanGoBack': + case 'getCanGoForward': + case 'getContentDimensions': + case 'setInputMethodActive': + case 'executeScript': + case 'getMuted': + case 'getVolume': + let req = this._frameElement[data.methodName] + .apply(this._frameElement, data.args); + req.onsuccess = () => { + this._sendToProxy({ + domRequestId: data.domRequestId, + innerWindowID: data.innerWindowID, + result: req.result + }); + }; + req.onerror = () => { + this._sendToProxy({ + domRequestId: data.domRequestId, + innerWindowID: data.innerWindowID, + err: req.error + }); + }; + + break; + + // Not implemented + case 'getActive': // Sync ??? + case 'addNextPaintListener': // Takes a callback + case 'removeNextPaintListener': // Takes a callback + case 'getScreenshot': // Need to pass a blob back + dump("BrowserElementParentProxyCallHandler Error:" + + "Attempt to call unimplemented method " + data.methodName + ".\n"); + break; + + default: + dump("BrowserElementParentProxyCallHandler Error:" + + "Attempt to call non-exist method " + data.methodName + ".\n"); + break; + } + }, + + // Receving events from the frame element and forward it. + handleEvent: function(evt) { + // Ignore the events from nested mozbrowser iframes + if (evt.target !== this._frameElement) { + return; + } + + let detailString; + try { + detailString = JSON.stringify(evt.detail); + } catch (e) { + dump("BrowserElementParentProxyCallHandler Error:" + + "Event detail of " + evt.type + " can't be stingified.\n"); + return; + } + + this.innerWindowIDSet.forEach((innerWindowID) => { + this._sendToProxy({ + eventName: evt.type, + innerWindowID: innerWindowID, + eventDetailString: detailString + }); + }); + }, + + _sendToProxy: function(data) { + this._mm.sendAsyncMessage("browser-element-api:proxy", data); + }, + + _attachEventListeners: function() { + this.MOZBROWSER_EVENT_NAMES.forEach(function(eventName) { + this._frameElement.addEventListener( + "mozbrowser" + eventName, this, true); + }, this); + }, + + _detachEventListeners: function() { + this.MOZBROWSER_EVENT_NAMES.forEach(function(eventName) { + this._frameElement.removeEventListener( + "mozbrowser" + eventName, this, true); + }, this); + } +}; + +function BrowserElementParent() { + debug("Creating new BrowserElementParent object"); + this._domRequestCounter = 0; + this._domRequestReady = false; + this._pendingAPICalls = []; + this._pendingDOMRequests = {}; + this._pendingSetInputMethodActive = []; + this._nextPaintListeners = []; + this._pendingDOMFullscreen = false; + + Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true); + Services.obs.addObserver(this, 'ask-children-to-execute-copypaste-command', /* ownsWeak = */ true); + Services.obs.addObserver(this, 'back-docommand', /* ownsWeak = */ true); + + this.proxyCallHandler = new BrowserElementParentProxyCallHandler(); +} + +BrowserElementParent.prototype = { + + classDescription: "BrowserElementAPI implementation", + classID: Components.ID("{9f171ac4-0939-4ef8-b360-3408aedc3060}"), + contractID: "@mozilla.org/dom/browser-element-api;1", + QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserElementAPI, + Ci.nsIObserver, + Ci.nsISupportsWeakReference]), + + setFrameLoader: function(frameLoader) { + debug("Setting frameLoader"); + this._frameLoader = frameLoader; + this._frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement; + if (!this._frameElement) { + debug("No frame element?"); + return; + } + // Listen to visibilitychange on the iframe's owner window, and forward + // changes down to the child. We want to do this while registering as few + // visibilitychange listeners on _window as possible, because such a listener + // may live longer than this BrowserElementParent object. + // + // To accomplish this, we register just one listener on the window, and have + // it reference a WeakMap whose keys are all the BrowserElementParent objects + // on the window. Then when the listener fires, we iterate over the + // WeakMap's keys (which we can do, because we're chrome) to notify the + // BrowserElementParents. + if (!this._window._browserElementParents) { + this._window._browserElementParents = new WeakMap(); + let handler = handleWindowEvent.bind(this._window); + let windowEvents = ['visibilitychange', 'fullscreenchange']; + let els = Cc["@mozilla.org/eventlistenerservice;1"] + .getService(Ci.nsIEventListenerService); + for (let event of windowEvents) { + els.addSystemEventListener(this._window, event, handler, + /* useCapture = */ true); + } + } + + this._window._browserElementParents.set(this, null); + + // Insert ourself into the prompt service. + BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this); + this._setupMessageListener(); + + this.proxyCallHandler.init( + this._frameElement, this._frameLoader.messageManager); + }, + + destroyFrameScripts() { + debug("Destroying frame scripts"); + this._mm.sendAsyncMessage("browser-element-api:destroy"); + }, + + _runPendingAPICall: function() { + if (!this._pendingAPICalls) { + return; + } + for (let i = 0; i < this._pendingAPICalls.length; i++) { + try { + this._pendingAPICalls[i](); + } catch (e) { + // throw the expections from pending functions. + debug('Exception when running pending API call: ' + e); + } + } + delete this._pendingAPICalls; + }, + + _setupMessageListener: function() { + this._mm = this._frameLoader.messageManager; + this._mm.addMessageListener('browser-element-api:call', this); + this._mm.loadFrameScript("chrome://global/content/extensions.js", true); + }, + + receiveMessage: function(aMsg) { + if (!this._isAlive()) { + return; + } + + // Messages we receive are handed to functions which take a (data) argument, + // where |data| is the message manager's data object. + // We use a single message and dispatch to various function based + // on data.msg_name + let mmCalls = { + "hello": this._recvHello, + "loadstart": this._fireProfiledEventFromMsg, + "loadend": this._fireProfiledEventFromMsg, + "close": this._fireEventFromMsg, + "error": this._fireEventFromMsg, + "firstpaint": this._fireProfiledEventFromMsg, + "documentfirstpaint": this._fireProfiledEventFromMsg, + "nextpaint": this._recvNextPaint, + "got-purge-history": this._gotDOMRequestResult, + "got-screenshot": this._gotDOMRequestResult, + "got-contentdimensions": this._gotDOMRequestResult, + "got-can-go-back": this._gotDOMRequestResult, + "got-can-go-forward": this._gotDOMRequestResult, + "got-muted": this._gotDOMRequestResult, + "got-volume": this._gotDOMRequestResult, + "requested-dom-fullscreen": this._requestedDOMFullscreen, + "fullscreen-origin-change": this._fullscreenOriginChange, + "exit-dom-fullscreen": this._exitDomFullscreen, + "got-visible": this._gotDOMRequestResult, + "visibilitychange": this._childVisibilityChange, + "got-set-input-method-active": this._gotDOMRequestResult, + "scrollviewchange": this._handleScrollViewChange, + "caretstatechanged": this._handleCaretStateChanged, + "findchange": this._handleFindChange, + "execute-script-done": this._gotDOMRequestResult, + "got-audio-channel-volume": this._gotDOMRequestResult, + "got-set-audio-channel-volume": this._gotDOMRequestResult, + "got-audio-channel-muted": this._gotDOMRequestResult, + "got-set-audio-channel-muted": this._gotDOMRequestResult, + "got-is-audio-channel-active": this._gotDOMRequestResult, + "got-web-manifest": this._gotDOMRequestResult, + }; + + let mmSecuritySensitiveCalls = { + "audioplaybackchange": this._fireEventFromMsg, + "showmodalprompt": this._handleShowModalPrompt, + "contextmenu": this._fireCtxMenuEvent, + "securitychange": this._fireEventFromMsg, + "locationchange": this._fireEventFromMsg, + "iconchange": this._fireEventFromMsg, + "scrollareachanged": this._fireEventFromMsg, + "titlechange": this._fireProfiledEventFromMsg, + "opensearch": this._fireEventFromMsg, + "manifestchange": this._fireEventFromMsg, + "metachange": this._fireEventFromMsg, + "resize": this._fireEventFromMsg, + "activitydone": this._fireEventFromMsg, + "scroll": this._fireEventFromMsg, + "opentab": this._fireEventFromMsg + }; + + if (aMsg.data.msg_name in mmCalls) { + return mmCalls[aMsg.data.msg_name].apply(this, arguments); + } else if (aMsg.data.msg_name in mmSecuritySensitiveCalls) { + return mmSecuritySensitiveCalls[aMsg.data.msg_name].apply(this, arguments); + } + }, + + _removeMessageListener: function() { + this._mm.removeMessageListener('browser-element-api:call', this); + }, + + /** + * You shouldn't touch this._frameElement or this._window if _isAlive is + * false. (You'll likely get an exception if you do.) + */ + _isAlive: function() { + return !Cu.isDeadWrapper(this._frameElement) && + !Cu.isDeadWrapper(this._frameElement.ownerDocument) && + !Cu.isDeadWrapper(this._frameElement.ownerDocument.defaultView); + }, + + get _window() { + return this._frameElement.ownerDocument.defaultView; + }, + + get _windowUtils() { + return this._window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + }, + + promptAuth: function(authDetail, callback) { + let evt; + let self = this; + let callbackCalled = false; + let cancelCallback = function() { + if (!callbackCalled) { + callbackCalled = true; + callback(false, null, null); + } + }; + + // We don't handle password-only prompts. + if (authDetail.isOnlyPassword) { + cancelCallback(); + return; + } + + /* username and password */ + let detail = { + host: authDetail.host, + path: authDetail.path, + realm: authDetail.realm, + isProxy: authDetail.isProxy + }; + + evt = this._createEvent('usernameandpasswordrequired', detail, + /* cancelable */ true); + Cu.exportFunction(function(username, password) { + if (callbackCalled) + return; + callbackCalled = true; + callback(true, username, password); + }, evt.detail, { defineAs: 'authenticate' }); + + Cu.exportFunction(cancelCallback, evt.detail, { defineAs: 'cancel' }); + + this._frameElement.dispatchEvent(evt); + + if (!evt.defaultPrevented) { + cancelCallback(); + } + }, + + _sendAsyncMsg: function(msg, data) { + try { + if (!data) { + data = { }; + } + + data.msg_name = msg; + this._mm.sendAsyncMessage('browser-element-api:call', data); + } catch (e) { + return false; + } + return true; + }, + + _recvHello: function() { + debug("recvHello"); + + // Inform our child if our owner element's document is invisible. Note + // that we must do so here, rather than in the BrowserElementParent + // constructor, because the BrowserElementChild may not be initialized when + // we run our constructor. + if (this._window.document.hidden) { + this._ownerVisibilityChange(); + } + + if (!this._domRequestReady) { + // At least, one message listener such as for hello is registered. + // So we can use sendAsyncMessage now. + this._domRequestReady = true; + this._runPendingAPICall(); + } + }, + + _fireCtxMenuEvent: function(data) { + let detail = data.json; + let evtName = detail.msg_name; + + debug('fireCtxMenuEventFromMsg: ' + evtName + ' ' + detail); + let evt = this._createEvent(evtName, detail, /* cancellable */ true); + + if (detail.contextmenu) { + var self = this; + Cu.exportFunction(function(id) { + self._sendAsyncMsg('fire-ctx-callback', {menuitem: id}); + }, evt.detail, { defineAs: 'contextMenuItemSelected' }); + } + + // The embedder may have default actions on context menu events, so + // we fire a context menu event even if the child didn't define a + // custom context menu + return !this._frameElement.dispatchEvent(evt); + }, + + /** + * add profiler marker for each event fired. + */ + _fireProfiledEventFromMsg: function(data) { + if (Services.profiler !== undefined) { + Services.profiler.AddMarker(data.json.msg_name); + } + this._fireEventFromMsg(data); + }, + + /** + * Fire either a vanilla or a custom event, depending on the contents of + * |data|. + */ + _fireEventFromMsg: function(data) { + let detail = data.json; + let name = detail.msg_name; + + // For events that send a "_payload_" property, we just want to transmit + // this in the event. + if ("_payload_" in detail) { + detail = detail._payload_; + } + + debug('fireEventFromMsg: ' + name + ', ' + JSON.stringify(detail)); + let evt = this._createEvent(name, detail, + /* cancelable = */ false); + this._frameElement.dispatchEvent(evt); + }, + + _handleShowModalPrompt: function(data) { + // Fire a showmodalprmopt event on the iframe. When this method is called, + // the child is spinning in a nested event loop waiting for an + // unblock-modal-prompt message. + // + // If the embedder calls preventDefault() on the showmodalprompt event, + // we'll block the child until event.detail.unblock() is called. + // + // Otherwise, if preventDefault() is not called, we'll send the + // unblock-modal-prompt message to the child as soon as the event is done + // dispatching. + + let detail = data.json; + debug('handleShowPrompt ' + JSON.stringify(detail)); + + // Strip off the windowID property from the object we send along in the + // event. + let windowID = detail.windowID; + delete detail.windowID; + debug("Event will have detail: " + JSON.stringify(detail)); + let evt = this._createEvent('showmodalprompt', detail, + /* cancelable = */ true); + + let self = this; + let unblockMsgSent = false; + function sendUnblockMsg() { + if (unblockMsgSent) { + return; + } + unblockMsgSent = true; + + // We don't need to sanitize evt.detail.returnValue (e.g. converting the + // return value of confirm() to a boolean); Gecko does that for us. + + let data = { windowID: windowID, + returnValue: evt.detail.returnValue }; + self._sendAsyncMsg('unblock-modal-prompt', data); + } + + Cu.exportFunction(sendUnblockMsg, evt.detail, { defineAs: 'unblock' }); + + this._frameElement.dispatchEvent(evt); + + if (!evt.defaultPrevented) { + // Unblock the inner frame immediately. Otherwise we'll unblock upon + // evt.detail.unblock(). + sendUnblockMsg(); + } + }, + + // Called when state of accessible caret in child has changed. + // The fields of data is as following: + // - rect: Contains bounding rectangle of selection, Include width, height, + // top, bottom, left and right. + // - commands: Describe what commands can be executed in child. Include canSelectAll, + // canCut, canCopy and canPaste. For example: if we want to check if cut + // command is available, using following code, if (data.commands.canCut) {}. + // - zoomFactor: Current zoom factor in child frame. + // - reason: The reason causes the state changed. Include "visibilitychange", + // "updateposition", "longpressonemptycontent", "taponcaret", "presscaret", + // "releasecaret". + // - collapsed: Indicate current selection is collapsed or not. + // - caretVisible: Indicate the caret visiibility. + // - selectionVisible: Indicate current selection is visible or not. + // - selectionEditable: Indicate current selection is editable or not. + // - selectedTextContent: Contains current selected text content, which is + // equivalent to the string returned by Selection.toString(). + _handleCaretStateChanged: function(data) { + let evt = this._createEvent('caretstatechanged', data.json, + /* cancelable = */ false); + + let self = this; + function sendDoCommandMsg(cmd) { + let data = { command: cmd }; + self._sendAsyncMsg('copypaste-do-command', data); + } + Cu.exportFunction(sendDoCommandMsg, evt.detail, { defineAs: 'sendDoCommandMsg' }); + + this._frameElement.dispatchEvent(evt); + }, + + _handleScrollViewChange: function(data) { + let evt = this._createEvent("scrollviewchange", data.json, + /* cancelable = */ false); + this._frameElement.dispatchEvent(evt); + }, + + _handleFindChange: function(data) { + let evt = this._createEvent("findchange", data.json, + /* cancelable = */ false); + this._frameElement.dispatchEvent(evt); + }, + + _createEvent: function(evtName, detail, cancelable) { + // This will have to change if we ever want to send a CustomEvent with null + // detail. For now, it's OK. + if (detail !== undefined && detail !== null) { + detail = Cu.cloneInto(detail, this._window); + return new this._window.CustomEvent('mozbrowser' + evtName, + { bubbles: true, + cancelable: cancelable, + detail: detail }); + } + + return new this._window.Event('mozbrowser' + evtName, + { bubbles: true, + cancelable: cancelable }); + }, + + /** + * Kick off a DOMRequest in the child process. + * + * We'll fire an event called |msgName| on the child process, passing along + * an object with two fields: + * + * - id: the ID of this request. + * - arg: arguments to pass to the child along with this request. + * + * We expect the child to pass the ID back to us upon completion of the + * request. See _gotDOMRequestResult. + */ + _sendDOMRequest: function(msgName, args) { + let id = 'req_' + this._domRequestCounter++; + let req = Services.DOMRequest.createRequest(this._window); + let self = this; + let send = function() { + if (!self._isAlive()) { + return; + } + if (self._sendAsyncMsg(msgName, {id: id, args: args})) { + self._pendingDOMRequests[id] = req; + } else { + Services.DOMRequest.fireErrorAsync(req, "fail"); + } + }; + if (this._domRequestReady) { + send(); + } else { + // Child haven't been loaded. + this._pendingAPICalls.push(send); + } + return req; + }, + + /** + * Called when the child process finishes handling a DOMRequest. data.json + * must have the fields [id, successRv], if the DOMRequest was successful, or + * [id, errorMsg], if the request was not successful. + * + * The fields have the following meanings: + * + * - id: the ID of the DOM request (see _sendDOMRequest) + * - successRv: the request's return value, if the request succeeded + * - errorMsg: the message to pass to DOMRequest.fireError(), if the request + * failed. + * + */ + _gotDOMRequestResult: function(data) { + let req = this._pendingDOMRequests[data.json.id]; + delete this._pendingDOMRequests[data.json.id]; + + if ('successRv' in data.json) { + debug("Successful gotDOMRequestResult."); + let clientObj = Cu.cloneInto(data.json.successRv, this._window); + Services.DOMRequest.fireSuccess(req, clientObj); + } + else { + debug("Got error in gotDOMRequestResult."); + Services.DOMRequest.fireErrorAsync(req, + Cu.cloneInto(data.json.errorMsg, this._window)); + } + }, + + setVisible: defineNoReturnMethod(function(visible) { + this._sendAsyncMsg('set-visible', {visible: visible}); + this._frameLoader.visible = visible; + }), + + getVisible: defineDOMRequestMethod('get-visible'), + + setActive: defineNoReturnMethod(function(active) { + this._frameLoader.visible = active; + }), + + getActive: function() { + if (!this._isAlive()) { + throw Components.Exception("Dead content process", + Cr.NS_ERROR_DOM_INVALID_STATE_ERR); + } + + return this._frameLoader.visible; + }, + + getChildProcessOffset: function() { + let offset = { x: 0, y: 0 }; + let tabParent = this._frameLoader.tabParent; + if (tabParent) { + let offsetX = {}; + let offsetY = {}; + tabParent.getChildProcessOffset(offsetX, offsetY); + offset.x = offsetX.value; + offset.y = offsetY.value; + } + return offset; + }, + + sendMouseEvent: defineNoReturnMethod(function(type, x, y, button, clickCount, modifiers) { + let offset = this.getChildProcessOffset(); + x += offset.x; + y += offset.y; + + this._sendAsyncMsg("send-mouse-event", { + "type": type, + "x": x, + "y": y, + "button": button, + "clickCount": clickCount, + "modifiers": modifiers + }); + }), + + sendTouchEvent: defineNoReturnMethod(function(type, identifiers, touchesX, touchesY, + radiisX, radiisY, rotationAngles, forces, + count, modifiers) { + + let offset = this.getChildProcessOffset(); + for (var i = 0; i < touchesX.length; i++) { + touchesX[i] += offset.x; + } + for (var i = 0; i < touchesY.length; i++) { + touchesY[i] += offset.y; + } + this._sendAsyncMsg("send-touch-event", { + "type": type, + "identifiers": identifiers, + "touchesX": touchesX, + "touchesY": touchesY, + "radiisX": radiisX, + "radiisY": radiisY, + "rotationAngles": rotationAngles, + "forces": forces, + "count": count, + "modifiers": modifiers + }); + }), + + getCanGoBack: defineDOMRequestMethod('get-can-go-back'), + getCanGoForward: defineDOMRequestMethod('get-can-go-forward'), + getContentDimensions: defineDOMRequestMethod('get-contentdimensions'), + + findAll: defineNoReturnMethod(function(searchString, caseSensitivity) { + return this._sendAsyncMsg('find-all', { + searchString, + caseSensitive: caseSensitivity == Ci.nsIBrowserElementAPI.FIND_CASE_SENSITIVE + }); + }), + + findNext: defineNoReturnMethod(function(direction) { + return this._sendAsyncMsg('find-next', { + backward: direction == Ci.nsIBrowserElementAPI.FIND_BACKWARD + }); + }), + + clearMatch: defineNoReturnMethod(function() { + return this._sendAsyncMsg('clear-match'); + }), + + mute: defineNoReturnMethod(function() { + this._sendAsyncMsg('mute'); + }), + + unmute: defineNoReturnMethod(function() { + this._sendAsyncMsg('unmute'); + }), + + getMuted: defineDOMRequestMethod('get-muted'), + + getVolume: defineDOMRequestMethod('get-volume'), + + setVolume: defineNoReturnMethod(function(volume) { + this._sendAsyncMsg('set-volume', {volume}); + }), + + goBack: defineNoReturnMethod(function() { + this._sendAsyncMsg('go-back'); + }), + + goForward: defineNoReturnMethod(function() { + this._sendAsyncMsg('go-forward'); + }), + + reload: defineNoReturnMethod(function(hardReload) { + this._sendAsyncMsg('reload', {hardReload: hardReload}); + }), + + stop: defineNoReturnMethod(function() { + this._sendAsyncMsg('stop'); + }), + + executeScript: function(script, options) { + if (!this._isAlive()) { + throw Components.Exception("Dead content process", + Cr.NS_ERROR_DOM_INVALID_STATE_ERR); + } + + // Enforcing options.url or options.origin + if (!options.url && !options.origin) { + throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG); + } + return this._sendDOMRequest('execute-script', {script, options}); + }, + + /* + * The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent". + */ + zoom: defineNoReturnMethod(function(zoom) { + zoom *= 100; + zoom = Math.min(getIntPref("zoom.maxPercent", 300), zoom); + zoom = Math.max(getIntPref("zoom.minPercent", 50), zoom); + this._sendAsyncMsg('zoom', {zoom: zoom / 100.0}); + }), + + purgeHistory: defineDOMRequestMethod('purge-history'), + + + download: function(_url, _options) { + if (!this._isAlive()) { + return null; + } + + let uri = Services.io.newURI(_url, null, null); + let url = uri.QueryInterface(Ci.nsIURL); + + debug('original _options = ' + uneval(_options)); + + // Ensure we have _options, we always use it to send the filename. + _options = _options || {}; + if (!_options.filename) { + _options.filename = url.fileName; + } + + debug('final _options = ' + uneval(_options)); + + // Ensure we have a filename. + if (!_options.filename) { + throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG); + } + + let interfaceRequestor = + this._frameLoader.loadContext.QueryInterface(Ci.nsIInterfaceRequestor); + let req = Services.DOMRequest.createRequest(this._window); + + function DownloadListener() { + debug('DownloadListener Constructor'); + } + DownloadListener.prototype = { + extListener: null, + onStartRequest: function(aRequest, aContext) { + debug('DownloadListener - onStartRequest'); + let extHelperAppSvc = + Cc['@mozilla.org/uriloader/external-helper-app-service;1']. + getService(Ci.nsIExternalHelperAppService); + let channel = aRequest.QueryInterface(Ci.nsIChannel); + + // First, we'll ensure the filename doesn't have any leading + // periods. We have to do it here to avoid ending up with a filename + // that's only an extension with no extension (e.g. Sending in + // '.jpeg' without stripping the '.' would result in a filename of + // 'jpeg' where we want 'jpeg.jpeg'. + _options.filename = _options.filename.replace(/^\.+/, ""); + + let ext = null; + let mimeSvc = extHelperAppSvc.QueryInterface(Ci.nsIMIMEService); + try { + ext = '.' + mimeSvc.getPrimaryExtension(channel.contentType, ''); + } catch (e) { ext = null; } + + // Check if we need to add an extension to the filename. + if (ext && !_options.filename.endsWith(ext)) { + _options.filename += ext; + } + // Set the filename to use when saving to disk. + channel.contentDispositionFilename = _options.filename; + + this.extListener = + extHelperAppSvc.doContent( + channel.contentType, + aRequest, + interfaceRequestor, + true); + this.extListener.onStartRequest(aRequest, aContext); + }, + onStopRequest: function(aRequest, aContext, aStatusCode) { + debug('DownloadListener - onStopRequest (aStatusCode = ' + + aStatusCode + ')'); + if (aStatusCode == Cr.NS_OK) { + // Everything looks great. + debug('DownloadListener - Download Successful.'); + Services.DOMRequest.fireSuccess(req, aStatusCode); + } + else { + // In case of failure, we'll simply return the failure status code. + debug('DownloadListener - Download Failed!'); + Services.DOMRequest.fireError(req, aStatusCode); + } + + if (this.extListener) { + this.extListener.onStopRequest(aRequest, aContext, aStatusCode); + } + }, + onDataAvailable: function(aRequest, aContext, aInputStream, + aOffset, aCount) { + this.extListener.onDataAvailable(aRequest, aContext, aInputStream, + aOffset, aCount); + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener, + Ci.nsIRequestObserver]) + }; + + let referrer = Services.io.newURI(_options.referrer, null, null); + let principal = + Services.scriptSecurityManager.createCodebasePrincipal( + referrer, this._frameLoader.loadContext.originAttributes); + + let channel = NetUtil.newChannel({ + uri: url, + loadingPrincipal: principal, + securityFlags: SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS, + contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER + }); + + // XXX We would set private browsing information prior to calling this. + channel.notificationCallbacks = interfaceRequestor; + + // Since we're downloading our own local copy we'll want to bypass the + // cache and local cache if the channel let's us specify this. + let flags = Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS | + Ci.nsIChannel.LOAD_BYPASS_CACHE; + if (channel instanceof Ci.nsICachingChannel) { + debug('This is a caching channel. Forcing bypass.'); + flags |= Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY; + } + + channel.loadFlags |= flags; + + if (channel instanceof Ci.nsIHttpChannel) { + debug('Setting HTTP referrer = ' + (referrer && referrer.spec)); + channel.referrer = referrer; + if (channel instanceof Ci.nsIHttpChannelInternal) { + channel.forceAllowThirdPartyCookie = true; + } + } + + // Set-up complete, let's get things started. + channel.asyncOpen2(new DownloadListener()); + + return req; + }, + + getScreenshot: function(_width, _height, _mimeType) { + if (!this._isAlive()) { + throw Components.Exception("Dead content process", + Cr.NS_ERROR_DOM_INVALID_STATE_ERR); + } + + let width = parseInt(_width); + let height = parseInt(_height); + let mimeType = (typeof _mimeType === 'string') ? + _mimeType.trim().toLowerCase() : 'image/jpeg'; + if (isNaN(width) || isNaN(height) || width < 0 || height < 0) { + throw Components.Exception("Invalid argument", + Cr.NS_ERROR_INVALID_ARG); + } + + return this._sendDOMRequest('get-screenshot', + {width: width, height: height, + mimeType: mimeType}); + }, + + _recvNextPaint: function(data) { + let listeners = this._nextPaintListeners; + this._nextPaintListeners = []; + for (let listener of listeners) { + try { + listener.recvNextPaint(); + } catch (e) { + // If a listener throws we'll continue. + } + } + }, + + addNextPaintListener: function(listener) { + if (!this._isAlive()) { + throw Components.Exception("Dead content process", + Cr.NS_ERROR_DOM_INVALID_STATE_ERR); + } + + let self = this; + let run = function() { + if (self._nextPaintListeners.push(listener) == 1) + self._sendAsyncMsg('activate-next-paint-listener'); + }; + if (!this._domRequestReady) { + this._pendingAPICalls.push(run); + } else { + run(); + } + }, + + removeNextPaintListener: function(listener) { + if (!this._isAlive()) { + throw Components.Exception("Dead content process", + Cr.NS_ERROR_DOM_INVALID_STATE_ERR); + } + + let self = this; + let run = function() { + for (let i = self._nextPaintListeners.length - 1; i >= 0; i--) { + if (self._nextPaintListeners[i] == listener) { + self._nextPaintListeners.splice(i, 1); + break; + } + } + + if (self._nextPaintListeners.length == 0) + self._sendAsyncMsg('deactivate-next-paint-listener'); + }; + if (!this._domRequestReady) { + this._pendingAPICalls.push(run); + } else { + run(); + } + }, + + setInputMethodActive: function(isActive) { + if (!this._isAlive()) { + throw Components.Exception("Dead content process", + Cr.NS_ERROR_DOM_INVALID_STATE_ERR); + } + + if (typeof isActive !== 'boolean') { + throw Components.Exception("Invalid argument", + Cr.NS_ERROR_INVALID_ARG); + } + + return this._sendDOMRequest('set-input-method-active', + {isActive: isActive}); + }, + + getAudioChannelVolume: function(aAudioChannel) { + return this._sendDOMRequest('get-audio-channel-volume', + {audioChannel: aAudioChannel}); + }, + + setAudioChannelVolume: function(aAudioChannel, aVolume) { + return this._sendDOMRequest('set-audio-channel-volume', + {audioChannel: aAudioChannel, + volume: aVolume}); + }, + + getAudioChannelMuted: function(aAudioChannel) { + return this._sendDOMRequest('get-audio-channel-muted', + {audioChannel: aAudioChannel}); + }, + + setAudioChannelMuted: function(aAudioChannel, aMuted) { + return this._sendDOMRequest('set-audio-channel-muted', + {audioChannel: aAudioChannel, + muted: aMuted}); + }, + + isAudioChannelActive: function(aAudioChannel) { + return this._sendDOMRequest('get-is-audio-channel-active', + {audioChannel: aAudioChannel}); + }, + + getWebManifest: defineDOMRequestMethod('get-web-manifest'), + /** + * Called when the visibility of the window which owns this iframe changes. + */ + _ownerVisibilityChange: function() { + this._sendAsyncMsg('owner-visibility-change', + {visible: !this._window.document.hidden}); + }, + + /* + * Called when the child notices that its visibility has changed. + * + * This is sometimes redundant; for example, the child's visibility may + * change in response to a setVisible request that we made here! But it's + * not always redundant; for example, the child's visibility may change in + * response to its parent docshell being hidden. + */ + _childVisibilityChange: function(data) { + debug("_childVisibilityChange(" + data.json.visible + ")"); + this._frameLoader.visible = data.json.visible; + + this._fireEventFromMsg(data); + }, + + _requestedDOMFullscreen: function() { + this._pendingDOMFullscreen = true; + this._windowUtils.remoteFrameFullscreenChanged(this._frameElement); + }, + + _fullscreenOriginChange: function(data) { + Services.obs.notifyObservers( + this._frameElement, "fullscreen-origin-change", data.json.originNoSuffix); + }, + + _exitDomFullscreen: function(data) { + this._windowUtils.remoteFrameFullscreenReverted(); + }, + + _handleOwnerEvent: function(evt) { + switch (evt.type) { + case 'visibilitychange': + this._ownerVisibilityChange(); + break; + case 'fullscreenchange': + if (!this._window.document.fullscreenElement) { + this._sendAsyncMsg('exit-fullscreen'); + } else if (this._pendingDOMFullscreen) { + this._pendingDOMFullscreen = false; + this._sendAsyncMsg('entered-fullscreen'); + } + break; + } + }, + + _fireFatalError: function() { + let evt = this._createEvent('error', {type: 'fatal'}, + /* cancelable = */ false); + this._frameElement.dispatchEvent(evt); + }, + + observe: function(subject, topic, data) { + switch(topic) { + case 'oop-frameloader-crashed': + if (this._isAlive() && subject == this._frameLoader) { + this._fireFatalError(); + } + break; + case 'ask-children-to-execute-copypaste-command': + if (this._isAlive() && this._frameElement == subject.wrappedJSObject) { + this._sendAsyncMsg('copypaste-do-command', { command: data }); + } + break; + case 'back-docommand': + if (this._isAlive() && this._frameLoader.visible) { + this.goBack(); + } + break; + default: + debug('Unknown topic: ' + topic); + break; + }; + }, +}; + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParent]); diff --git a/dom/browser-element/BrowserElementParent.manifest b/dom/browser-element/BrowserElementParent.manifest new file mode 100644 index 000000000..547ff7f3d --- /dev/null +++ b/dom/browser-element/BrowserElementParent.manifest @@ -0,0 +1,2 @@ +component {9f171ac4-0939-4ef8-b360-3408aedc3060} BrowserElementParent.js +contract @mozilla.org/dom/browser-element-api;1 {9f171ac4-0939-4ef8-b360-3408aedc3060} diff --git a/dom/browser-element/BrowserElementPromptService.jsm b/dom/browser-element/BrowserElementPromptService.jsm new file mode 100644 index 000000000..1442304db --- /dev/null +++ b/dom/browser-element/BrowserElementPromptService.jsm @@ -0,0 +1,685 @@ +/* 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/. */ +/* vim: set ft=javascript : */ + +"use strict"; + +var Cu = Components.utils; +var Ci = Components.interfaces; +var Cc = Components.classes; +var Cr = Components.results; +var Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); + +this.EXPORTED_SYMBOLS = ["BrowserElementPromptService"]; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; +const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled"; + +function debug(msg) { + //dump("BrowserElementPromptService - " + msg + "\n"); +} + +function BrowserElementPrompt(win, browserElementChild) { + this._win = win; + this._browserElementChild = browserElementChild; +} + +BrowserElementPrompt.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrompt]), + + alert: function(title, text) { + this._browserElementChild.showModalPrompt( + this._win, {promptType: "alert", title: title, message: text, returnValue: undefined}); + }, + + alertCheck: function(title, text, checkMsg, checkState) { + // Treat this like a normal alert() call, ignoring the checkState. The + // front-end can do its own suppression of the alert() if it wants. + this.alert(title, text); + }, + + confirm: function(title, text) { + return this._browserElementChild.showModalPrompt( + this._win, {promptType: "confirm", title: title, message: text, returnValue: undefined}); + }, + + confirmCheck: function(title, text, checkMsg, checkState) { + return this.confirm(title, text); + }, + + // Each button is described by an object with the following schema + // { + // string messageType, // 'builtin' or 'custom' + // string message, // 'ok', 'cancel', 'yes', 'no', 'save', 'dontsave', + // // 'revert' or a string from caller if messageType was 'custom'. + // } + // + // Expected result from embedder: + // { + // int button, // Index of the button that user pressed. + // boolean checked, // True if the check box is checked. + // } + confirmEx: function(title, text, buttonFlags, button0Title, button1Title, + button2Title, checkMsg, checkState) { + let buttonProperties = this._buildConfirmExButtonProperties(buttonFlags, + button0Title, + button1Title, + button2Title); + let defaultReturnValue = { selectedButton: buttonProperties.defaultButton }; + if (checkMsg) { + defaultReturnValue.checked = checkState.value; + } + let ret = this._browserElementChild.showModalPrompt( + this._win, + { + promptType: "custom-prompt", + title: title, + message: text, + defaultButton: buttonProperties.defaultButton, + buttons: buttonProperties.buttons, + showCheckbox: !!checkMsg, + checkboxMessage: checkMsg, + checkboxCheckedByDefault: !!checkState.value, + returnValue: defaultReturnValue + } + ); + if (checkMsg) { + checkState.value = ret.checked; + } + return buttonProperties.indexToButtonNumberMap[ret.selectedButton]; + }, + + prompt: function(title, text, value, checkMsg, checkState) { + let rv = this._browserElementChild.showModalPrompt( + this._win, + { promptType: "prompt", + title: title, + message: text, + initialValue: value.value, + returnValue: null }); + + value.value = rv; + + // nsIPrompt::Prompt returns true if the user pressed "OK" at the prompt, + // and false if the user pressed "Cancel". + // + // BrowserElementChild returns null for "Cancel" and returns the string the + // user entered otherwise. + return rv !== null; + }, + + promptUsernameAndPassword: function(title, text, username, password, checkMsg, checkState) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + + promptPassword: function(title, text, password, checkMsg, checkState) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + + select: function(title, text, aCount, aSelectList, aOutSelection) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + + _buildConfirmExButtonProperties: function(buttonFlags, button0Title, + button1Title, button2Title) { + let r = { + defaultButton: -1, + buttons: [], + // This map is for translating array index to the button number that + // is recognized by Gecko. This shouldn't be exposed to embedder. + indexToButtonNumberMap: [] + }; + + let defaultButton = 0; // Default to Button 0. + if (buttonFlags & Ci.nsIPrompt.BUTTON_POS_1_DEFAULT) { + defaultButton = 1; + } else if (buttonFlags & Ci.nsIPrompt.BUTTON_POS_2_DEFAULT) { + defaultButton = 2; + } + + // Properties of each button. + let buttonPositions = [ + Ci.nsIPrompt.BUTTON_POS_0, + Ci.nsIPrompt.BUTTON_POS_1, + Ci.nsIPrompt.BUTTON_POS_2 + ]; + + function buildButton(buttonTitle, buttonNumber) { + let ret = {}; + let buttonPosition = buttonPositions[buttonNumber]; + let mask = 0xff * buttonPosition; // 8 bit mask + let titleType = (buttonFlags & mask) / buttonPosition; + + ret.messageType = 'builtin'; + switch(titleType) { + case Ci.nsIPrompt.BUTTON_TITLE_OK: + ret.message = 'ok'; + break; + case Ci.nsIPrompt.BUTTON_TITLE_CANCEL: + ret.message = 'cancel'; + break; + case Ci.nsIPrompt.BUTTON_TITLE_YES: + ret.message = 'yes'; + break; + case Ci.nsIPrompt.BUTTON_TITLE_NO: + ret.message = 'no'; + break; + case Ci.nsIPrompt.BUTTON_TITLE_SAVE: + ret.message = 'save'; + break; + case Ci.nsIPrompt.BUTTON_TITLE_DONT_SAVE: + ret.message = 'dontsave'; + break; + case Ci.nsIPrompt.BUTTON_TITLE_REVERT: + ret.message = 'revert'; + break; + case Ci.nsIPrompt.BUTTON_TITLE_IS_STRING: + ret.message = buttonTitle; + ret.messageType = 'custom'; + break; + default: + // This button is not shown. + return; + } + + // If this is the default button, set r.defaultButton to + // the index of this button in the array. This value is going to be + // exposed to the embedder. + if (defaultButton === buttonNumber) { + r.defaultButton = r.buttons.length; + } + r.buttons.push(ret); + r.indexToButtonNumberMap.push(buttonNumber); + } + + buildButton(button0Title, 0); + buildButton(button1Title, 1); + buildButton(button2Title, 2); + + // If defaultButton is still -1 here, it means the default button won't + // be shown. + if (r.defaultButton === -1) { + throw new Components.Exception("Default button won't be shown", + Cr.NS_ERROR_FAILURE); + } + + return r; + }, +}; + + +function BrowserElementAuthPrompt() { +} + +BrowserElementAuthPrompt.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAuthPrompt2]), + + promptAuth: function promptAuth(channel, level, authInfo) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + + asyncPromptAuth: function asyncPromptAuth(channel, callback, context, level, authInfo) { + debug("asyncPromptAuth"); + + // The cases that we don't support now. + if ((authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) && + (authInfo.flags & Ci.nsIAuthInformation.ONLY_PASSWORD)) { + throw Cr.NS_ERROR_FAILURE; + } + + let frame = this._getFrameFromChannel(channel); + if (!frame) { + debug("Cannot get frame, asyncPromptAuth fail"); + throw Cr.NS_ERROR_FAILURE; + } + + let browserElementParent = + BrowserElementPromptService.getBrowserElementParentForFrame(frame); + + if (!browserElementParent) { + debug("Failed to load browser element parent."); + throw Cr.NS_ERROR_FAILURE; + } + + let consumer = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]), + callback: callback, + context: context, + cancel: function() { + this.callback.onAuthCancelled(this.context, false); + this.callback = null; + this.context = null; + } + }; + + let [hostname, httpRealm] = this._getAuthTarget(channel, authInfo); + let hashKey = level + "|" + hostname + "|" + httpRealm; + let asyncPrompt = this._asyncPrompts[hashKey]; + if (asyncPrompt) { + asyncPrompt.consumers.push(consumer); + return consumer; + } + + asyncPrompt = { + consumers: [consumer], + channel: channel, + authInfo: authInfo, + level: level, + inProgress: false, + browserElementParent: browserElementParent + }; + + this._asyncPrompts[hashKey] = asyncPrompt; + this._doAsyncPrompt(); + return consumer; + }, + + // Utilities for nsIAuthPrompt2 ---------------- + + _asyncPrompts: {}, + _asyncPromptInProgress: new WeakMap(), + _doAsyncPrompt: function() { + // Find the key of a prompt whose browser element parent does not have + // async prompt in progress. + let hashKey = null; + for (let key in this._asyncPrompts) { + let prompt = this._asyncPrompts[key]; + if (!this._asyncPromptInProgress.get(prompt.browserElementParent)) { + hashKey = key; + break; + } + } + + // Didn't find an available prompt, so just return. + if (!hashKey) + return; + + let prompt = this._asyncPrompts[hashKey]; + let [hostname, httpRealm] = this._getAuthTarget(prompt.channel, + prompt.authInfo); + + this._asyncPromptInProgress.set(prompt.browserElementParent, true); + prompt.inProgress = true; + + let self = this; + let callback = function(ok, username, password) { + debug("Async auth callback is called, ok = " + + ok + ", username = " + username); + + // Here we got the username and password provided by embedder, or + // ok = false if the prompt was cancelled by embedder. + delete self._asyncPrompts[hashKey]; + prompt.inProgress = false; + self._asyncPromptInProgress.delete(prompt.browserElementParent); + + // Fill authentication information with username and password provided + // by user. + let flags = prompt.authInfo.flags; + if (username) { + if (flags & Ci.nsIAuthInformation.NEED_DOMAIN) { + // Domain is separated from username by a backslash + let idx = username.indexOf("\\"); + if (idx == -1) { + prompt.authInfo.username = username; + } else { + prompt.authInfo.domain = username.substring(0, idx); + prompt.authInfo.username = username.substring(idx + 1); + } + } else { + prompt.authInfo.username = username; + } + } + + if (password) { + prompt.authInfo.password = password; + } + + for (let consumer of prompt.consumers) { + if (!consumer.callback) { + // Not having a callback means that consumer didn't provide it + // or canceled the notification. + continue; + } + + try { + if (ok) { + debug("Ok, calling onAuthAvailable to finish auth"); + consumer.callback.onAuthAvailable(consumer.context, prompt.authInfo); + } else { + debug("Cancelled, calling onAuthCancelled to finish auth."); + consumer.callback.onAuthCancelled(consumer.context, true); + } + } catch (e) { /* Throw away exceptions caused by callback */ } + } + + // Process the next prompt, if one is pending. + self._doAsyncPrompt(); + }; + + let runnable = { + run: function() { + // Call promptAuth of browserElementParent, to show the prompt. + prompt.browserElementParent.promptAuth( + self._createAuthDetail(prompt.channel, prompt.authInfo), + callback); + } + } + + Services.tm.currentThread.dispatch(runnable, Ci.nsIThread.DISPATCH_NORMAL); + }, + + _getFrameFromChannel: function(channel) { + let loadContext = channel.notificationCallbacks.getInterface(Ci.nsILoadContext); + return loadContext.topFrameElement; + }, + + _createAuthDetail: function(channel, authInfo) { + let [hostname, httpRealm] = this._getAuthTarget(channel, authInfo); + return { + host: hostname, + path: channel.URI.path, + realm: httpRealm, + username: authInfo.username, + isProxy: !!(authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY), + isOnlyPassword: !!(authInfo.flags & Ci.nsIAuthInformation.ONLY_PASSWORD) + }; + }, + + // The code is taken from nsLoginManagerPrompter.js, with slight + // modification for parameter name consistency here. + _getAuthTarget : function (channel, authInfo) { + let hostname, realm; + + // If our proxy is demanding authentication, don't use the + // channel's actual destination. + if (authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) { + if (!(channel instanceof Ci.nsIProxiedChannel)) + throw new Error("proxy auth needs nsIProxiedChannel"); + + let info = channel.proxyInfo; + if (!info) + throw new Error("proxy auth needs nsIProxyInfo"); + + // Proxies don't have a scheme, but we'll use "moz-proxy://" + // so that it's more obvious what the login is for. + var idnService = Cc["@mozilla.org/network/idn-service;1"]. + getService(Ci.nsIIDNService); + hostname = "moz-proxy://" + + idnService.convertUTF8toACE(info.host) + + ":" + info.port; + realm = authInfo.realm; + if (!realm) + realm = hostname; + + return [hostname, realm]; + } + + hostname = this._getFormattedHostname(channel.URI); + + // If a HTTP WWW-Authenticate header specified a realm, that value + // will be available here. If it wasn't set or wasn't HTTP, we'll use + // the formatted hostname instead. + realm = authInfo.realm; + if (!realm) + realm = hostname; + + return [hostname, realm]; + }, + + /** + * Strip out things like userPass and path for display. + */ + _getFormattedHostname : function(uri) { + return uri.scheme + "://" + uri.hostPort; + }, +}; + + +function AuthPromptWrapper(oldImpl, browserElementImpl) { + this._oldImpl = oldImpl; + this._browserElementImpl = browserElementImpl; +} + +AuthPromptWrapper.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAuthPrompt2]), + promptAuth: function(channel, level, authInfo) { + if (this._canGetParentElement(channel)) { + return this._browserElementImpl.promptAuth(channel, level, authInfo); + } else { + return this._oldImpl.promptAuth(channel, level, authInfo); + } + }, + + asyncPromptAuth: function(channel, callback, context, level, authInfo) { + if (this._canGetParentElement(channel)) { + return this._browserElementImpl.asyncPromptAuth(channel, callback, context, level, authInfo); + } else { + return this._oldImpl.asyncPromptAuth(channel, callback, context, level, authInfo); + } + }, + + _canGetParentElement: function(channel) { + try { + let context = channel.notificationCallbacks.getInterface(Ci.nsILoadContext); + let frame = context.topFrameElement; + if (!frame) { + // This function returns a boolean value + return !!context.nestedFrameId; + } + + if (!BrowserElementPromptService.getBrowserElementParentForFrame(frame)) + return false; + + return true; + } catch (e) { + return false; + } + } +}; + +function BrowserElementPromptFactory(toWrap) { + this._wrapped = toWrap; +} + +BrowserElementPromptFactory.prototype = { + classID: Components.ID("{24f3d0cf-e417-4b85-9017-c9ecf8bb1299}"), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptFactory]), + + _mayUseNativePrompt: function() { + try { + return Services.prefs.getBoolPref("browser.prompt.allowNative"); + } catch (e) { + // This properity is default to true. + return true; + } + }, + + _getNativePromptIfAllowed: function(win, iid, err) { + if (this._mayUseNativePrompt()) + return this._wrapped.getPrompt(win, iid); + else { + // Not allowed, throw an exception. + throw err; + } + }, + + getPrompt: function(win, iid) { + // It is possible for some object to get a prompt without passing + // valid reference of window, like nsNSSComponent. In such case, we + // should just fall back to the native prompt service + if (!win) + return this._getNativePromptIfAllowed(win, iid, Cr.NS_ERROR_INVALID_ARG); + + if (iid.number != Ci.nsIPrompt.number && + iid.number != Ci.nsIAuthPrompt2.number) { + debug("We don't recognize the requested IID (" + iid + ", " + + "allowed IID: " + + "nsIPrompt=" + Ci.nsIPrompt + ", " + + "nsIAuthPrompt2=" + Ci.nsIAuthPrompt2 + ")"); + return this._getNativePromptIfAllowed(win, iid, Cr.NS_ERROR_INVALID_ARG); + } + + // Try to find a BrowserElementChild for the window. + let browserElementChild = + BrowserElementPromptService.getBrowserElementChildForWindow(win); + + if (iid.number === Ci.nsIAuthPrompt2.number) { + debug("Caller requests an instance of nsIAuthPrompt2."); + + if (browserElementChild) { + // If we are able to get a BrowserElementChild, it means that + // the auth prompt is for a mozbrowser. Therefore we don't need to + // fall back. + return new BrowserElementAuthPrompt().QueryInterface(iid); + } + + // Because nsIAuthPrompt2 is called in parent process. If caller + // wants nsIAuthPrompt2 and we cannot get BrowserElementchild, + // it doesn't mean that we should fallback. It is possible that we can + // get the BrowserElementParent from nsIChannel that passed to + // functions of nsIAuthPrompt2. + if (this._mayUseNativePrompt()) { + return new AuthPromptWrapper( + this._wrapped.getPrompt(win, iid), + new BrowserElementAuthPrompt().QueryInterface(iid)) + .QueryInterface(iid); + } else { + // Falling back is not allowed, so we don't need wrap the + // BrowserElementPrompt. + return new BrowserElementAuthPrompt().QueryInterface(iid); + } + } + + if (!browserElementChild) { + debug("We can't find a browserElementChild for " + + win + ", " + win.location); + return this._getNativePromptIfAllowed(win, iid, Cr.NS_ERROR_FAILURE); + } + + debug("Returning wrapped getPrompt for " + win); + return new BrowserElementPrompt(win, browserElementChild) + .QueryInterface(iid); + } +}; + +this.BrowserElementPromptService = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsISupportsWeakReference]), + + _initialized: false, + + _init: function() { + if (this._initialized) { + return; + } + + // If the pref is disabled, do nothing except wait for the pref to change. + if (!this._browserFramesPrefEnabled()) { + var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); + prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true); + return; + } + + this._initialized = true; + this._browserElementParentMap = new WeakMap(); + + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + os.addObserver(this, "outer-window-destroyed", /* ownsWeak = */ true); + + // Wrap the existing @mozilla.org/prompter;1 implementation. + var contractID = "@mozilla.org/prompter;1"; + var oldCID = Cm.contractIDToCID(contractID); + var newCID = BrowserElementPromptFactory.prototype.classID; + var oldFactory = Cm.getClassObject(Cc[contractID], Ci.nsIFactory); + + if (oldCID == newCID) { + debug("WARNING: Wrapped prompt factory is already installed!"); + return; + } + + Cm.unregisterFactory(oldCID, oldFactory); + + var oldInstance = oldFactory.createInstance(null, Ci.nsIPromptFactory); + var newInstance = new BrowserElementPromptFactory(oldInstance); + + var newFactory = { + createInstance: function(outer, iid) { + if (outer != null) { + throw Cr.NS_ERROR_NO_AGGREGATION; + } + return newInstance.QueryInterface(iid); + } + }; + Cm.registerFactory(newCID, + "BrowserElementPromptService's prompter;1 wrapper", + contractID, newFactory); + + debug("Done installing new prompt factory."); + }, + + _getOuterWindowID: function(win) { + return win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils) + .outerWindowID; + }, + + _browserElementChildMap: {}, + mapWindowToBrowserElementChild: function(win, browserElementChild) { + this._browserElementChildMap[this._getOuterWindowID(win)] = browserElementChild; + }, + unmapWindowToBrowserElementChild: function(win) { + delete this._browserElementChildMap[this._getOuterWindowID(win)]; + }, + + getBrowserElementChildForWindow: function(win) { + // We only have a mapping for <iframe mozbrowser>s, not their inner + // <iframes>, so we look up win.top below. window.top (when called from + // script) respects <iframe mozbrowser> boundaries. + return this._browserElementChildMap[this._getOuterWindowID(win.top)]; + }, + + mapFrameToBrowserElementParent: function(frame, browserElementParent) { + this._browserElementParentMap.set(frame, browserElementParent); + }, + + getBrowserElementParentForFrame: function(frame) { + return this._browserElementParentMap.get(frame); + }, + + _observeOuterWindowDestroyed: function(outerWindowID) { + let id = outerWindowID.QueryInterface(Ci.nsISupportsPRUint64).data; + debug("observeOuterWindowDestroyed " + id); + delete this._browserElementChildMap[outerWindowID.data]; + }, + + _browserFramesPrefEnabled: function() { + var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); + try { + return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF); + } + catch(e) { + return false; + } + }, + + observe: function(subject, topic, data) { + switch(topic) { + case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: + if (data == BROWSER_FRAMES_ENABLED_PREF) { + this._init(); + } + break; + case "outer-window-destroyed": + this._observeOuterWindowDestroyed(subject); + break; + default: + debug("Observed unexpected topic " + topic); + } + } +}; + +BrowserElementPromptService._init(); diff --git a/dom/browser-element/BrowserElementProxy.js b/dom/browser-element/BrowserElementProxy.js new file mode 100644 index 000000000..852b93358 --- /dev/null +++ b/dom/browser-element/BrowserElementProxy.js @@ -0,0 +1,219 @@ +/* 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/. */ + +'use strict'; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); +Cu.import('resource://gre/modules/Services.jsm'); + +function defineNoReturnMethod(methodName) { + return function noReturnMethod() { + let args = Array.slice(arguments); + this._sendToParent(methodName, args); + }; +} + +function defineDOMRequestMethod(methodName) { + return function domRequestMethod() { + let args = Array.slice(arguments); + return this._sendDOMRequest(methodName, args); + }; +} + +function defineUnimplementedMethod(methodName) { + return function unimplementedMethod() { + throw Components.Exception( + 'Unimplemented method: ' + methodName, Cr.NS_ERROR_FAILURE); + }; +} + +/** + * The BrowserElementProxy talks to the Browser IFrameElement instance on + * behave of the embedded document. It implements all the methods on + * the Browser IFrameElement and the methods will work if they are applicable. + * + * The message is forwarded to BrowserElementParent.js by creating an + * 'browser-element-api:proxy-call' observer message. + * BrowserElementChildPreload will get notified and send the message through + * to the main process through sendAsyncMessage with message of the same name. + * + * The return message will follow the same route. The message name on the + * return route is 'browser-element-api:proxy'. + * + * Both BrowserElementProxy and BrowserElementParent must be modified if there + * is a new method implemented, or a new event added to the Browser + * IFrameElement. + * + * Other details unmentioned here are checks of message sender and recipients + * to identify proxy instance on different innerWindows or ensure the content + * process has the right permission. + */ +function BrowserElementProxy() { + // Pad the 0th element so that DOMRequest ID will always be a truthy value. + this._pendingDOMRequests = [ undefined ]; +} + +BrowserElementProxy.prototype = { + classDescription: 'BrowserElementProxy allowed embedded frame to control ' + + 'it\'s own embedding browser element frame instance.', + classID: Components.ID('{7e95d54c-9930-49c8-9a10-44fe40fe8251}'), + contractID: '@mozilla.org/dom/browser-element-proxy;1', + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIDOMGlobalPropertyInitializer, + Ci.nsIObserver]), + + _window: null, + _innerWindowID: undefined, + + get allowedAudioChannels() { + return this._window.navigator.mozAudioChannelManager ? + this._window.navigator.mozAudioChannelManager.allowedAudioChannels : + null; + }, + + init: function(win) { + this._window = win; + this._innerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils) + .currentInnerWindowID; + + this._sendToParent('_proxyInstanceInit'); + Services.obs.addObserver(this, 'browser-element-api:proxy', false); + }, + + uninit: function(win) { + this._sendToParent('_proxyInstanceUninit'); + + this._window = null; + this._innerWindowID = undefined; + + Services.obs.removeObserver(this, 'browser-element-api:proxy'); + }, + + observe: function(subject, topic, stringifedData) { + let data = JSON.parse(stringifedData); + + if (subject !== this._window || + data.innerWindowID !== data.innerWindowID) { + return; + } + + if (data.eventName) { + this._fireEvent(data.eventName, JSON.parse(data.eventDetailString)); + + return; + } + + if ('domRequestId' in data) { + let req = this._pendingDOMRequests[data.domRequestId]; + this._pendingDOMRequests[data.domRequestId] = undefined; + + if (!req) { + dump('BrowserElementProxy Error: ' + + 'Multiple observer messages for the same DOMRequest result.\n'); + return; + } + + if ('result' in data) { + let clientObj = Cu.cloneInto(data.result, this._window); + Services.DOMRequest.fireSuccess(req, clientObj); + } else { + let clientObj = Cu.cloneInto(data.error, this._window); + Services.DOMRequest.fireSuccess(req, clientObj); + } + + return; + } + + dump('BrowserElementProxy Error: ' + + 'Received unhandled observer messages ' + stringifedData + '.\n'); + }, + + _sendDOMRequest: function(methodName, args) { + let id = this._pendingDOMRequests.length; + let req = Services.DOMRequest.createRequest(this._window); + + this._pendingDOMRequests.push(req); + this._sendToParent(methodName, args, id); + + return req; + }, + + _sendToParent: function(methodName, args, domRequestId) { + let data = { + methodName: methodName, + args: args, + innerWindowID: this._innerWindowID + }; + + if (domRequestId) { + data.domRequestId = domRequestId; + } + + Services.obs.notifyObservers( + this._window, 'browser-element-api:proxy-call', JSON.stringify(data)); + }, + + _fireEvent: function(name, detail) { + let evt = this._createEvent(name, detail, + /* cancelable = */ false); + this.__DOM_IMPL__.dispatchEvent(evt); + }, + + _createEvent: function(evtName, detail, cancelable) { + // This will have to change if we ever want to send a CustomEvent with null + // detail. For now, it's OK. + if (detail !== undefined && detail !== null) { + detail = Cu.cloneInto(detail, this._window); + return new this._window.CustomEvent(evtName, + { bubbles: false, + cancelable: cancelable, + detail: detail }); + } + + return new this._window.Event(evtName, + { bubbles: false, + cancelable: cancelable }); + }, + + setVisible: defineNoReturnMethod('setVisible'), + setActive: defineNoReturnMethod('setActive'), + sendMouseEvent: defineNoReturnMethod('sendMouseEvent'), + sendTouchEvent: defineNoReturnMethod('sendTouchEvent'), + goBack: defineNoReturnMethod('goBack'), + goForward: defineNoReturnMethod('goForward'), + reload: defineNoReturnMethod('reload'), + stop: defineNoReturnMethod('stop'), + zoom: defineNoReturnMethod('zoom'), + findAll: defineNoReturnMethod('findAll'), + findNext: defineNoReturnMethod('findNext'), + clearMatch: defineNoReturnMethod('clearMatch'), + mute: defineNoReturnMethod('mute'), + unmute: defineNoReturnMethod('unmute'), + setVolume: defineNoReturnMethod('setVolume'), + + getVisible: defineDOMRequestMethod('getVisible'), + download: defineDOMRequestMethod('download'), + purgeHistory: defineDOMRequestMethod('purgeHistory'), + getCanGoBack: defineDOMRequestMethod('getCanGoBack'), + getCanGoForward: defineDOMRequestMethod('getCanGoForward'), + getContentDimensions: defineDOMRequestMethod('getContentDimensions'), + setInputMethodActive: defineDOMRequestMethod('setInputMethodActive'), + executeScript: defineDOMRequestMethod('executeScript'), + getMuted: defineDOMRequestMethod('getMuted'), + getVolume: defineDOMRequestMethod('getVolume'), + + getActive: defineUnimplementedMethod('getActive'), + addNextPaintListener: defineUnimplementedMethod('addNextPaintListener'), + removeNextPaintListener: defineUnimplementedMethod('removeNextPaintListener'), + getScreenshot: defineUnimplementedMethod('getScreenshot') +}; + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementProxy]); diff --git a/dom/browser-element/BrowserElementProxy.manifest b/dom/browser-element/BrowserElementProxy.manifest new file mode 100644 index 000000000..b26639523 --- /dev/null +++ b/dom/browser-element/BrowserElementProxy.manifest @@ -0,0 +1,2 @@ +component {7e95d54c-9930-49c8-9a10-44fe40fe8251} BrowserElementProxy.js +contract @mozilla.org/dom/browser-element-proxy;1 {7e95d54c-9930-49c8-9a10-44fe40fe8251} diff --git a/dom/browser-element/mochitest/async.js b/dom/browser-element/mochitest/async.js new file mode 100644 index 000000000..d0007fa09 --- /dev/null +++ b/dom/browser-element/mochitest/async.js @@ -0,0 +1,78 @@ +/* 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 => { + try { + step(gen.throw(error)); + } catch (err) { + throw err; + } + } + ).catch(err => reject(err)); + } + step(gen.next(value)); + } + }); + }; + } + exports.async = async; +}(this || self)); diff --git a/dom/browser-element/mochitest/audio.ogg b/dom/browser-element/mochitest/audio.ogg Binary files differnew file mode 100644 index 000000000..44ab64f81 --- /dev/null +++ b/dom/browser-element/mochitest/audio.ogg diff --git a/dom/browser-element/mochitest/browserElementTestHelpers.js b/dom/browser-element/mochitest/browserElementTestHelpers.js new file mode 100644 index 000000000..004b25333 --- /dev/null +++ b/dom/browser-element/mochitest/browserElementTestHelpers.js @@ -0,0 +1,306 @@ +/* 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() { + return window.location.pathname + .substring(0, window.location.pathname.lastIndexOf('/')) + .replace("/priority", ""); +} + +const browserElementTestHelpers = { + _getBoolPref: function(pref) { + try { + return SpecialPowers.getBoolPref(pref); + } + catch (e) { + return undefined; + } + }, + + _setPref: function(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: function() { + this.lockTestReady(); + SpecialPowers.pushPrefEnv({'set': Array.slice(arguments)}, this.unlockTestReady.bind(this)); + }, + + _testReadyLockCount: 0, + _firedTestReady: false, + lockTestReady: function() { + this._testReadyLockCount++; + }, + + unlockTestReady: function() { + this._testReadyLockCount--; + if (this._testReadyLockCount == 0 && !this._firedTestReady) { + this._firedTestReady = true; + dispatchEvent(new Event("testready")); + } + }, + + enableProcessPriorityManager: function() { + this._setPrefs( + ['dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2], + ['dom.ipc.processPriorityManager.BACKGROUND_PERCEIVABLE.LRUPoolLevels', 2], + ['dom.ipc.processPriorityManager.testMode', true], + ['dom.ipc.processPriorityManager.enabled', true] + ); + }, + + setClipboardPlainTextOnlyPref: function(value) { + this._setPref('clipboard.plainTextOnly', value); + }, + + setEnabledPref: function(value) { + this._setPrefs(['dom.mozBrowserFramesEnabled', value], + ['network.disable.ipc.security', value]); + }, + + setupAccessibleCaretPref: function() { + 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: function() { + return this._getBoolPref("dom.ipc.browser_frames.oop_by_default"); + }, + + addPermission: function() { + this.lockTestReady(); + SpecialPowers.pushPermissions( + [{'type': "browser", 'allow': 1, 'context': document}], + this.unlockTestReady.bind(this)); + }, + + _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: function(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, /* weak = */ false); + this._observers.push([observer, topic]); + }, + + cleanUp: function() { + 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 or rejected the next time the +// process childID changes its priority. We resolve if the expectedPriority +// matches the priority and the LRU parameter matches expectedLRU and we +// reject otherwise. + +function expectPriorityWithLRUSet(childID, expectedPriority, expectedLRU) { + return new Promise(function(resolve, reject) { + var observed = false; + browserElementTestHelpers.addProcessPriorityObserver( + 'process-priority-with-LRU-set', + function(subject, topic, data) { + if (observed) { + return; + } + + var [id, priority, lru] = data.split(":"); + if (id != childID) { + return; + } + + // Make sure we run the is() calls in this observer only once, + // otherwise we'll expect /every/ priority/LRU change to match + // expectedPriority/expectedLRU. + observed = true; + + is(lru, expectedLRU, + 'Expected LRU ' + lru + + ' of childID ' + childID + + ' to change to ' + expectedLRU); + + if ((priority == expectedPriority) && (lru == expectedLRU)) { + 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.indexOf('_inproc_') == -1; + + 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)); +}); diff --git a/dom/browser-element/mochitest/browserElement_ActiveStateChange.js b/dom/browser-element/mochitest/browserElement_ActiveStateChange.js new file mode 100644 index 000000000..cfbc1cb1e --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ActiveStateChange.js @@ -0,0 +1,108 @@ +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var fileURL = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/file_browserElement_ActiveStateChange.html'; +var generator = runTests(); +var testFrame; +var ac; + +function assert(aVal, aMessage) { + return (!aVal) ? error(aMessage) : 0; +} + +function error(aMessage) { + ok(false, "Error : " + aMessage); + finish(); +} + +function continueTest() { + try { + generator.next(); + } catch (e if e instanceof StopIteration) { + error("Stop test because of exception!"); + } +} + +function finish() { + document.body.removeChild(testFrame); + SimpleTest.finish(); +} + +function setCommand(aArg) { + assert(!!ac, "Audio channel doesn't exist!"); + info("# Command = " + aArg); + + testFrame.src = fileURL + '#' + aArg; + var expectedActive = false; + switch (aArg) { + case 'play': + expectedActive = true; + break; + case 'pause': + expectedActive = false; + break; + default : + error("Undefined command!"); + } + + ac.onactivestatechanged = () => { + ac.onactivestatechanged = null; + ac.isActive().onsuccess = (e) => { + is(expectedActive, e.target.result, + "Correct active state = " + expectedActive); + continueTest(); + } + }; +} + +function runTests() { + setCommand('play'); + yield undefined; + + setCommand('pause'); + yield undefined; + + finish(); + yield undefined; +} + +function setupTestFrame() { + testFrame = document.createElement('iframe'); + testFrame.setAttribute('mozbrowser', 'true'); + testFrame.src = fileURL; + + function loadend() { + testFrame.removeEventListener('mozbrowserloadend', loadend); + ok("allowedAudioChannels" in testFrame, "allowedAudioChannels exist"); + var channels = testFrame.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + ac = channels[0]; + + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("isActive" in ac, "isActive exists"); + ok("onactivestatechanged" in ac, "onactivestatechanged exists"); + + generator.next(); + } + + function alertError(e) { + testFrame.removeEventListener('mozbrowsershowmodalprompt', alertError); + var message = e.detail.message + error(message); + } + + testFrame.addEventListener('mozbrowserloadend', loadend); + testFrame.addEventListener('mozbrowsershowmodalprompt', alertError); + document.body.appendChild(testFrame); +} + +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set': [["b2g.system_startup_url", window.location.href]]}, + function() { + SimpleTest.executeSoon(setupTestFrame); + }); +}); + diff --git a/dom/browser-element/mochitest/browserElement_Alert.js b/dom/browser-element/mochitest/browserElement_Alert.js new file mode 100644 index 000000000..3c7c50720 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Alert.js @@ -0,0 +1,304 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that alert works. +"use strict"; + +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 loadend() { + iframe.removeEventListener('mozbrowserloadend', loadend); + iframe.src = browserElementTestHelpers.emptyPage1; + + iframe.addEventListener('mozbrowserloadend', function loadend2() { + iframe.removeEventListener('mozbrowserloadend', loadend2); + SimpleTest.executeSoon(test1); + }); + }); + +} + +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); diff --git a/dom/browser-element/mochitest/browserElement_AlertInFrame.js b/dom/browser-element/mochitest/browserElement_AlertInFrame.js new file mode 100644 index 000000000..e9b606154 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_AlertInFrame.js @@ -0,0 +1,24 @@ +/* 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"; + +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); diff --git a/dom/browser-element/mochitest/browserElement_AudioChannel.js b/dom/browser-element/mochitest/browserElement_AudioChannel.js new file mode 100644 index 000000000..20f7b4e47 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_AudioChannel.js @@ -0,0 +1,199 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1113086 - tests for AudioChannel API into BrowserElement + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function noaudio() { + info("Test : no-audio"); + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.src = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/file_empty.html'; + + function noaudio_loadend() { + ok("mute" in iframe, "iframe.mute exists"); + ok("unmute" in iframe, "iframe.unmute exists"); + ok("getMuted" in iframe, "iframe.getMuted exists"); + ok("getVolume" in iframe, "iframe.getVolume exists"); + ok("setVolume" in iframe, "iframe.setVolume exists"); + + ok("allowedAudioChannels" in iframe, "allowedAudioChannels exist"); + var channels = iframe.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + var ac = channels[0]; + + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("getVolume" in ac, "ac.getVolume exists"); + ok("setVolume" in ac, "ac.setVolume exists"); + ok("getMuted" in ac, "ac.getMuted exists"); + ok("setMuted" in ac, "ac.setMuted exists"); + ok("isActive" in ac, "ac.isActive exists"); + + new Promise(function(r, rr) { + var req = ac.getVolume(); + ok(req instanceof DOMRequest, "This is a domRequest."); + req.onsuccess = function(e) { + is(e.target.result, 1.0, "The default volume should be 1.0"); + r(); + } + }) + + .then(function() { + return new Promise(function(resolve) { + iframe.mute(); + iframe.getMuted() + .then(result => is(result, true, "iframe.getMuted should be true.")) + .then(resolve); + }); + }) + + .then(function() { + return new Promise(function(resolve) { + iframe.unmute(); + iframe.getMuted() + .then(result => is(result, false, "iframe.getMuted should be false.")) + .then(resolve); + }); + }) + + .then(function() { + return new Promise(function(resolve) { + iframe.setVolume(0); + iframe.getVolume() + .then(result => is(result, 0, "iframe.getVolume should be 0.")) + .then(resolve); + }); + }) + + .then(function() { + return new Promise(function(resolve) { + iframe.setVolume(1); + iframe.getVolume() + .then(result => is(result, 1, "iframe.getVolume should be 1.")) + .then(resolve); + }); + }) + + .then(function() { + return new Promise(function(r, rr) { + ac.getMuted().onsuccess = function(e) { + is(e.target.result, false, "The default muted value should be false"); + r(); + } + }); + }) + + .then(function() { + return new Promise(function(r, rr) { + ac.setVolume(0.8).onsuccess = function() { r(); } + }); + }) + + .then(function() { + return new Promise(function(r, rr) { + ac.getVolume().onsuccess = function(e) { + // the actual value is 0.800000011920929.. + ok(Math.abs(0.8 - e.target.result) < 0.01, "The new volume should be 0.8: " + e.target.result); + r(); + } + }); + }) + + .then(function() { + return new Promise(function(r, rr) { + ac.setVolume(1.0).onsuccess = function() { r(); } + }); + }) + + .then(function() { + return new Promise(function(r, rr) { + ac.setMuted(true).onsuccess = function() { r(); } + }); + }) + + .then(function() { + return new Promise(function(r, rr) { + ac.getMuted().onsuccess = function(e) { + is(e.target.result, true, "The new muted value should be true"); + r(); + } + }); + }) + + .then(function() { + return new Promise(function(r, rr) { + ac.isActive().onsuccess = function(e) { + is(e.target.result, false, "ac.isActive is false: no audio element active."); + r(); + } + }); + }) + + .then(runTests); + } + + iframe.addEventListener('mozbrowserloadend', noaudio_loadend); + document.body.appendChild(iframe); +} + +function audio() { + info("Test : audio"); + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.src = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/iframe_file_audio.html'; + + function audio_loadend() { + ok("mute" in iframe, "iframe.mute exists"); + ok("unmute" in iframe, "iframe.unmute exists"); + ok("getMuted" in iframe, "iframe.getMuted exists"); + ok("getVolume" in iframe, "iframe.getVolume exists"); + ok("setVolume" in iframe, "iframe.setVolume exists"); + + ok("allowedAudioChannels" in iframe, "allowedAudioChannels exist"); + var channels = iframe.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + var ac = channels[0]; + + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("getVolume" in ac, "ac.getVolume exists"); + ok("setVolume" in ac, "ac.setVolume exists"); + ok("getMuted" in ac, "ac.getMuted exists"); + ok("setMuted" in ac, "ac.setMuted exists"); + ok("isActive" in ac, "ac.isActive exists"); + + ac.onactivestatechanged = function() { + ok(true, "activestatechanged event received."); + ac.onactivestatechanged = null; + document.body.removeChild(iframe); + runTests(); + } + } + + iframe.addEventListener('mozbrowserloadend', audio_loadend); + document.body.appendChild(iframe); +} + +var tests = [ noaudio, audio ]; + +function runTests() { + if (tests.length == 0) { + SimpleTest.finish(); + return; + } + + var test = tests.shift(); + test(); +} + +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set': [["b2g.system_startup_url", window.location.href]]}, + function() { + SimpleTest.executeSoon(runTests); + }); +}); diff --git a/dom/browser-element/mochitest/browserElement_AudioChannelMutedByDefault.js b/dom/browser-element/mochitest/browserElement_AudioChannelMutedByDefault.js new file mode 100644 index 000000000..897c4318a --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_AudioChannelMutedByDefault.js @@ -0,0 +1,103 @@ +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var fileURL = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/file_browserElement_AudioChannelMutedByDefault.html'; +var testFrame; +var ac; + +function alertListener(e) { + var message = e.detail.message + if (/^OK/.exec(message)) { + ok(true, "Message from file : " + message); + } else if (/^KO/.exec(message)) { + error(message); + } else if (/DONE/.exec(message)) { + ok(true, "Audio playback success!"); + finish(); + } else { + error("Undefined event."); + } +} + +function assert(aVal, aMessage) { + return (!aVal) ? error(aMessage) : 0; +} + +function error(aMessage) { + ok(false, "Error : " + aMessage); + finish(); +} + +function finish() { + testFrame.removeEventListener('mozbrowsershowmodalprompt', alertListener); + document.body.removeChild(testFrame); + SimpleTest.finish(); +} + +function setCommand(aArg) { + assert(!!ac, "Audio channel doesn't exist!"); + info("# Command = " + aArg); + testFrame.src = fileURL + '#' + aArg; + + switch (aArg) { + case 'play': + ac.onactivestatechanged = () => { + ac.onactivestatechanged = null; + ok(true, "activestatechanged event received."); + + new Promise(function(r, rr) { + ac.getMuted().onsuccess = function(e) { + is(e.target.result, true, "Muted channel by default"); + r(); + } + }).then(function() { + ac.setMuted(false).onsuccess = function(e) { + ok(true, "Unmuted the channel."); + } + }); + }; + break; + default : + error("Undefined command!"); + } +} + +function runTests() { + setCommand('play'); +} + +function setupTestFrame() { + testFrame = document.createElement('iframe'); + testFrame.setAttribute('mozbrowser', 'true'); + testFrame.src = fileURL; + + function loadend() { + testFrame.removeEventListener('mozbrowserloadend', loadend); + ok("allowedAudioChannels" in testFrame, "allowedAudioChannels exist"); + var channels = testFrame.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + ac = channels[0]; + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("getMuted" in ac, "ac.getMuted exists"); + ok("setMuted" in ac, "ac.setMuted exists"); + ok("onactivestatechanged" in ac, "onactivestatechanged exists"); + + runTests(); + } + + info("Set EventListeners."); + testFrame.addEventListener('mozbrowsershowmodalprompt', alertListener); + testFrame.addEventListener('mozbrowserloadend', loadend); + document.body.appendChild(testFrame); +} + +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set': [["b2g.system_startup_url", window.location.href], + ["dom.audiochannel.mutedByDefault", true]]}, + function() { + SimpleTest.executeSoon(setupTestFrame); + }); +}); diff --git a/dom/browser-element/mochitest/browserElement_AudioChannelSeeking.js b/dom/browser-element/mochitest/browserElement_AudioChannelSeeking.js new file mode 100644 index 000000000..f354a9d82 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_AudioChannelSeeking.js @@ -0,0 +1,128 @@ +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var fileURL = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/file_browserElement_AudioChannelSeeking.html'; +var generator = runTests(); +var testFrame; +var ac; + +function alertListener(e) { + var message = e.detail.message + if (/^OK/.exec(message)) { + ok(true, "Message from file : " + message); + continueTest(); + } else if (/^KO/.exec(message)) { + error(message); + } else if (/^INFO/.exec(message)) { + info("Message from file : " + message); + } else { + error("Undefined event."); + } +} + +function assert(aVal, aMessage) { + return (!aVal) ? error(aMessage) : 0; +} + +function error(aMessage) { + ok(false, "Error : " + aMessage); + finish(); +} + +function continueTest() { + try { + generator.next(); + } catch (e if e instanceof StopIteration) { + error("Stop test because of exception!"); + } +} + +function finish() { + testFrame.removeEventListener('mozbrowsershowmodalprompt', alertListener); + ok(true, "Remove event-listener."); + document.body.removeChild(testFrame); + ok(true, "Remove test-frame from document."); + SimpleTest.finish(); +} + +function setCommand(aArg) { + assert(!!ac, "Audio channel doesn't exist!"); + info("# Command = " + aArg); + testFrame.src = fileURL + '#' + aArg; + + switch (aArg) { + case 'play': + ac.onactivestatechanged = () => { + ac.onactivestatechanged = null; + ok(true, "Receive onactivestatechanged after audio started."); + continueTest(); + }; + break; + case 'seeking': + ac.onactivestatechanged = () => { + ac.onactivestatechanged = null; + error("Should not receive onactivestatechanged during seeking!"); + }; + break; + case 'pause': + ac.onactivestatechanged = null; + break; + default : + error("Undefined command!"); + } +} + +function runTests() { + setCommand('play'); + yield undefined; + + setCommand('seeking'); + yield undefined; + + setCommand('seeking'); + yield undefined; + + setCommand('seeking'); + yield undefined; + + setCommand('pause'); + yield undefined; + + finish(); + yield undefined; +} + +function setupTestFrame() { + testFrame = document.createElement('iframe'); + testFrame.setAttribute('mozbrowser', 'true'); + testFrame.src = fileURL; + + function loadend() { + testFrame.removeEventListener('mozbrowserloadend', loadend); + ok("allowedAudioChannels" in testFrame, "allowedAudioChannels exist"); + var channels = testFrame.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + ac = channels[0]; + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("onactivestatechanged" in ac, "onactivestatechanged exists"); + + continueTest(); + } + + testFrame.addEventListener('mozbrowsershowmodalprompt', alertListener); + testFrame.addEventListener('mozbrowserloadend', loadend); + ok(true, "Add event-listeners."); + + document.body.appendChild(testFrame); + ok(true, "Append test-frame to document."); +} + +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set': [["b2g.system_startup_url", window.location.href]]}, + function() { + SimpleTest.executeSoon(setupTestFrame); + }); +}); diff --git a/dom/browser-element/mochitest/browserElement_AudioChannel_nested.js b/dom/browser-element/mochitest/browserElement_AudioChannel_nested.js new file mode 100644 index 000000000..2ed432b2a --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_AudioChannel_nested.js @@ -0,0 +1,69 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1113086 - tests for AudioChannel API into BrowserElement + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTests() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + var listener = function(e) { + var message = e.detail.message; + if (/^OK/.exec(message)) { + ok(true, "Message from app: " + message); + } else if (/^KO/.exec(message)) { + ok(false, "Message from app: " + message); + } else if (/DONE/.exec(message)) { + ok(true, "Messaging from app complete"); + iframe.removeEventListener('mozbrowsershowmodalprompt', listener); + SimpleTest.finish(); + } + } + + function audio_loadend() { + ok("mute" in iframe, "iframe.mute exists"); + ok("unmute" in iframe, "iframe.unmute exists"); + ok("getMuted" in iframe, "iframe.getMuted exists"); + ok("getVolume" in iframe, "iframe.getVolume exists"); + ok("setVolume" in iframe, "iframe.setVolume exists"); + + ok("allowedAudioChannels" in iframe, "allowedAudioChannels exist"); + var channels = iframe.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + var ac = channels[0]; + + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("getVolume" in ac, "ac.getVolume exists"); + ok("setVolume" in ac, "ac.setVolume exists"); + ok("getMuted" in ac, "ac.getMuted exists"); + ok("setMuted" in ac, "ac.setMuted exists"); + ok("isActive" in ac, "ac.isActive exists"); + + info("Setting the volume..."); + ac.setVolume(0.5); + + ac.onactivestatechanged = function() { + ok(true, "activestatechanged event received."); + ac.onactivestatechanged = null; + } + } + + iframe.addEventListener('mozbrowserloadend', audio_loadend); + iframe.addEventListener('mozbrowsershowmodalprompt', listener, false); + document.body.appendChild(iframe); + + iframe.src = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/file_browserElement_AudioChannel_nested.html'; +} + +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set': [["b2g.system_startup_url", window.location.href]]}, + function() { + SimpleTest.executeSoon(runTests); + }); +}); diff --git a/dom/browser-element/mochitest/browserElement_AudioPlayback.js b/dom/browser-element/mochitest/browserElement_AudioPlayback.js new file mode 100644 index 000000000..bcbe89cb1 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_AudioPlayback.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test the mozbrowseraudioplaybackchange event is fired correctly. +'use strict'; + +const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm'); + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +/** + * Content script passed to the child iframe + */ +function playAudioScript() { + var audio = new content.Audio(); + content.document.body.appendChild(audio); + audio.oncanplay = function() { + audio.play(); + }; + audio.src = 'audio.ogg'; +} + +/** + * Creates a simple mozbrowser frame + */ +function createFrame() { + let iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + return iframe; +} + +function runTest() { + SimpleTest.waitForExplicitFinish(); + + let iframe = createFrame(); + let iframe2 = createFrame(); + + // When the first iframe is finished loading inject a script to create + // an audio element and play it. + iframe.addEventListener('mozbrowserloadend', () => { + let mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + mm.loadFrameScript('data:,(' + playAudioScript.toString() + ')();', false); + }); + + // Two events should come in, when the audio starts, and stops playing. + // The first one should have a detail of 'active' and the second one + // should have a detail of 'inactive-pause'. + let expectedNextData = 'active'; + iframe.addEventListener('mozbrowseraudioplaybackchange', (e) => { + is(e.detail, expectedNextData, 'Audio detail should be correct') + is(e.target, iframe, 'event target should be the first iframe') + if (e.detail === 'inactive-pause') { + SimpleTest.finish(); + } + expectedNextData = 'inactive-pause'; + }); + + // Make sure an event only goes to the first iframe. + iframe2.addEventListener('mozbrowseraudioplaybackchange', (e) => { + ok(false, + 'mozbrowseraudioplaybackchange should dispatch to the correct browser'); + }); + + // Load a simple page to get the process started. + iframe.src = browserElementTestHelpers.fileEmptyPage1; +} + +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set': [["b2g.system_startup_url", window.location.href]]}, + function() { + SimpleTest.executeSoon(runTest); + }); +}); diff --git a/dom/browser-element/mochitest/browserElement_Auth.js b/dom/browser-element/mochitest/browserElement_Auth.js new file mode 100644 index 000000000..ef95409be --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Auth.js @@ -0,0 +1,246 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that auth prompt works. +"use strict"; + +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 loadend() { + iframe.removeEventListener('mozbrowserloadend', loadend); + 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'; + }); + }); +} + +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 onTitleChange(e) { + iframe.removeEventListener("mozbrowsertitlechange", onTitleChange); + iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail); + is(e.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'; + }); + }); + + 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 onTitleChange(e) { + iframe.removeEventListener("mozbrowsertitlechange", onTitleChange); + iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail); + is(e.detail, 'http auth success', 'expect authentication to succeed'); + SimpleTest.executeSoon(testProxyAuth); + }); + + 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(e) { + // 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 onTitleChange(e) { + iframe.removeEventListener("mozbrowsertitlechange", onTitleChange); + iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail); + is(e.detail, 'http auth success', 'expect authentication to succeed'); + SimpleTest.executeSoon(testAuthJarNoInterfere); + }); + + 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({ + QueryInterface: function (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: function (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) { + var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1'] + .getService(SpecialPowers.Ci.nsIHttpAuthManager); + var secMan = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"] + .getService(SpecialPowers.Ci.nsIScriptSecurityManager); + var ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"] + .getService(SpecialPowers.Ci.nsIIOService); + var uri = ioService.newURI("http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs", null, null); + + // Set a bunch of auth data that should not conflict with the correct auth data already + // stored in the cache. + var attrs = {appId: 1}; + var principal = secMan.createCodebasePrincipal(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 = {appId: 1, inIsolatedMozBrowser: true}; + principal = secMan.createCodebasePrincipal(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.createCodebasePrincipal(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 onTitleChange(e) { + iframe.removeEventListener("mozbrowsertitlechange", onTitleChange); + iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail); + is(e.detail, 'http auth success', 'expected authentication success'); + SimpleTest.executeSoon(testAuthJarInterfere); + }); + + // 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) { + var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1'] + .getService(SpecialPowers.Ci.nsIHttpAuthManager); + var secMan = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"] + .getService(SpecialPowers.Ci.nsIScriptSecurityManager); + var ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"] + .getService(SpecialPowers.Ci.nsIIOService); + var uri = ioService.newURI("http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs", null, null); + + // Set some auth data that should overwrite the successful stored details. + var principal = secMan.createCodebasePrincipal(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 onTitleChange(e) { + iframe.removeEventListener("mozbrowsertitlechange", onTitleChange); + iframe.removeEventListener("mozbrowserusernameandpasswordrequired", + onUserNameAndPasswordRequired); + ok(gotusernamepasswordrequired, + "Should have dispatched mozbrowserusernameandpasswordrequired event"); + testFinish(); + }); + + // 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. + var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1'] + .getService(SpecialPowers.Ci.nsIHttpAuthManager); + authMgr.clearAll(); + + var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"] + .getService(SpecialPowers.Ci.nsILoginManager); + pwmgr.removeAllLogins(); + + SimpleTest.finish(); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_BackForward.js b/dom/browser-element/mochitest/browserElement_BackForward.js new file mode 100644 index 000000000..26b6344c4 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_BackForward.js @@ -0,0 +1,104 @@ +/* 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"; +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().onsuccess = function(e) { + is(seenCanGoBackResult, false, "onsuccess handler shouldn't be called twice."); + seenCanGoBackResult = true; + is(e.target.result, canGoBack); + maybeRunNextTest(); + }; + + var seenCanGoForwardResult = false; + iframe.getCanGoForward().onsuccess = function(e) { + is(seenCanGoForwardResult, false, "onsuccess handler shouldn't be called twice."); + seenCanGoForwardResult = true; + is(e.target.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); diff --git a/dom/browser-element/mochitest/browserElement_BadScreenshot.js b/dom/browser-element/mochitest/browserElement_BadScreenshot.js new file mode 100644 index 000000000..7b194da86 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_BadScreenshot.js @@ -0,0 +1,71 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 800170 - Test that we get errors when we pass bad arguments to +// mozbrowser's getScreenshot. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var iframe; +var numPendingTests = 0; + +// Call iframe.getScreenshot with the given args. If expectSuccess is true, we +// expect the screenshot's onsuccess handler to fire. Otherwise, we expect +// getScreenshot() to throw an exception. +function checkScreenshotResult(expectSuccess, args) { + var req; + try { + req = iframe.getScreenshot.apply(iframe, args); + } + catch(e) { + ok(!expectSuccess, "getScreenshot(" + JSON.stringify(args) + ") threw an exception."); + return; + } + + numPendingTests++; + req.onsuccess = function() { + ok(expectSuccess, "getScreenshot(" + JSON.stringify(args) + ") succeeded."); + numPendingTests--; + if (numPendingTests == 0) { + SimpleTest.finish(); + } + }; + + // We never expect to see onerror. + req.onerror = function() { + ok(false, "getScreenshot(" + JSON.stringify(args) + ") ran onerror."); + numPendingTests--; + if (numPendingTests == 0) { + SimpleTest.finish(); + } + }; +} + +function runTest() { + iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + iframe.src = 'data:text/html,<html>' + + '<body style="background:green">hello</body></html>'; + + iframe.addEventListener('mozbrowserfirstpaint', function() { + // This one should succeed. + checkScreenshotResult(true, [100, 100]); + + // These should fail. + checkScreenshotResult(false, []); + checkScreenshotResult(false, [100]); + checkScreenshotResult(false, ['a', 100]); + checkScreenshotResult(false, [100, 'a']); + checkScreenshotResult(false, [-1, 100]); + checkScreenshotResult(false, [100, -1]); + + if (numPendingTests == 0) { + SimpleTest.finish(); + } + }); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_BrowserWindowNamespace.js b/dom/browser-element/mochitest/browserElement_BrowserWindowNamespace.js new file mode 100644 index 000000000..87c4a216c --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_BrowserWindowNamespace.js @@ -0,0 +1,57 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 780351 - Test that mozbrowser does /not/ divide the window name namespace. +// Multiple mozbrowsers inside the same app are like multiple browser tabs; +// they share a window name namespace. + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + + // Two mozbrowser frames with the same code both do the same + // window.open("foo", "bar") call. We should only get one + // mozbrowseropenwindow event. + + iframe1.addEventListener('mozbrowseropenwindow', function(e) { + ok(true, "Got first mozbrowseropenwindow event."); + document.body.appendChild(e.detail.frameElement); + + e.detail.frameElement.addEventListener('mozbrowserlocationchange', function(e) { + if (e.detail.url == "http://example.com/#2") { + ok(true, "Got locationchange to http://example.com/#2"); + SimpleTest.finish(); + } + else { + ok(true, "Got locationchange to " + e.detail.url); + } + }); + + SimpleTest.executeSoon(function() { + var iframe2 = document.createElement('iframe'); + // Make sure that iframe1 and iframe2 are in the same TabGroup by linking + // them through opener. Right now this API requires chrome privileges, as + // it is on MozFrameLoaderOwner. + SpecialPowers.wrap(iframe2).presetOpenerWindow(iframe1.contentWindow); + iframe2.setAttribute('mozbrowser', 'true'); + + iframe2.addEventListener('mozbrowseropenwindow', function(e) { + ok(false, "Got second mozbrowseropenwindow event."); + }); + + document.body.appendChild(iframe2); + iframe2.src = 'file_browserElement_BrowserWindowNamespace.html#2'; + }); + }); + + document.body.appendChild(iframe1); + iframe1.src = 'file_browserElement_BrowserWindowNamespace.html#1'; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js b/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js new file mode 100644 index 000000000..420b4bc34 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 891763 - Test the mozbrowserresize event +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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); diff --git a/dom/browser-element/mochitest/browserElement_Close.js b/dom/browser-element/mochitest/browserElement_Close.js new file mode 100644 index 000000000..57bdf384d --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Close.js @@ -0,0 +1,24 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that window.close() works. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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()</scr"+"ipt></body></html>"; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_CloseFromOpener.js b/dom/browser-element/mochitest/browserElement_CloseFromOpener.js new file mode 100644 index 000000000..65ea4d1b7 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_CloseFromOpener.js @@ -0,0 +1,33 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 764718 - Test that window.close() works from the opener window. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowseropenwindow', function(e) { + ok(true, "got openwindow event."); + document.body.appendChild(e.detail.frameElement); + + e.detail.frameElement.addEventListener("mozbrowserclose", function(e) { + ok(true, "got mozbrowserclose event."); + SimpleTest.finish(); + }); + }); + + + document.body.appendChild(iframe); + + // file_browserElement_CloseFromOpener opens a new window and then calls + // close() on it. + iframe.src = "file_browserElement_CloseFromOpener.html"; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js b/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js new file mode 100644 index 000000000..66aa8e015 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js @@ -0,0 +1,351 @@ +'use strict'; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.setClipboardPlainTextOnlyPref(false); +browserElementTestHelpers.addPermission(); + +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': selector, 'src': 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': 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 }); + 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); diff --git a/dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js b/dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js new file mode 100644 index 000000000..32f877786 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js @@ -0,0 +1,51 @@ +/* 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"; + +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); +}); diff --git a/dom/browser-element/mochitest/browserElement_CopyPaste.js b/dom/browser-element/mochitest/browserElement_CopyPaste.js new file mode 100644 index 000000000..b23feef59 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_CopyPaste.js @@ -0,0 +1,339 @@ +/* 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"; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.setupAccessibleCaretPref(); +browserElementTestHelpers.addPermission(); +const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm'); + +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) { + gTextarea.value = str; + SpecialPowers.wrap(gTextarea).editor.selectAll(); + SpecialPowers.wrap(gTextarea).editor.copy(); +} + +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 onloadend(e) { + iframeOuter.removeEventListener("mozbrowserloadend", onloadend); + + if (createEmbededFrame) { + var contentWin = SpecialPowers.wrap(iframeOuter) + .QueryInterface(SpecialPowers.Ci.nsIFrameLoaderOwner) + .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 onloadendinner(e) { + iframeInner.removeEventListener("mozbrowserloadend", onloadendinner); + mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner); + dispatchTest(e); + }); + } else { + iframeInner = iframeOuter; + mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner); + dispatchTest(e); + } + }); +} + +function doCommand(cmd) { + var COMMAND_MAP = { + 'cut': 'cmd_cut', + 'copy': 'cmd_copyAndCollapseToEnd', + '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 onloadend2(e) { + iframeInner.removeEventListener("mozbrowserloadend", onloadend2); + iframeInner.focus(); + SimpleTest.executeSoon(function() { testSelectAll(e); }); + }); + + 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.Cc["@mozilla.org/xre/app-info;1"] + .getService(SpecialPowers.Ci.nsIXULRuntime) + .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 caretchangeforselectall(e) { + iframeOuter.removeEventListener(eventName, caretchangeforselectall, true); + ok(true, "got mozbrowsercaretstatechanged event." + stateMeaning); + ok(e.detail, "event.detail is not null." + stateMeaning); + ok(e.detail.width != 0, "event.detail.width is not zero" + stateMeaning); + ok(e.detail.height != 0, "event.detail.height is not zero" + stateMeaning); + SimpleTest.executeSoon(function() { testCopy1(e); }); + }, 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: { + appId: principal.appId, + inIsolatedMozBrowser: true }}; + +addEventListener('testready', function() { + SpecialPowers.pushPermissions([ + {type: 'browser', allow: 1, context: context} + ], runTest); +}); + diff --git a/dom/browser-element/mochitest/browserElement_DOMRequestError.js b/dom/browser-element/mochitest/browserElement_DOMRequestError.js new file mode 100644 index 000000000..040cb81fd --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_DOMRequestError.js @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test if DOMRequest returned by an iframe gets an error callback when +// the iframe is not in the DOM. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + iframe1.src = 'data:text/html,<html>' + + '<body style="background:green">hello</body></html>'; + document.body.appendChild(iframe1); + + function testIframe(beforeRun, isErrorExpected, nextTest) { + return function() { + var error = false; + if (beforeRun) + beforeRun(); + function testEnd() { + is(isErrorExpected, error); + SimpleTest.executeSoon(nextTest); + } + + var domRequest = iframe1.getScreenshot(1000, 1000); + domRequest.onsuccess = function(e) { + testEnd(); + } + domRequest.onerror = function(e) { + error = true; + testEnd(); + } + }; + } + + function iframeLoadedHandler() { + iframe1.removeEventListener('mozbrowserloadend', iframeLoadedHandler); + // Test 1: iframe is in the DOM. + // Test 2: iframe is removed from the DOM. + // Test 3: iframe is added back into the DOM. + var test3 = testIframe( + function() { + document.body.appendChild(iframe1); + }, false, + function() { + SimpleTest.finish(); + }) + ; + var test2 = testIframe(function() { + document.body.removeChild(iframe1); + }, true, test3); + var test1 = testIframe(null, false, test2); + SimpleTest.executeSoon(test1); + } + + iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_DataURI.js b/dom/browser-element/mochitest/browserElement_DataURI.js new file mode 100644 index 000000000..f57f4566a --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_DataURI.js @@ -0,0 +1,68 @@ +/* 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"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + iframe1.id = 'iframe1'; + iframe1.addEventListener('mozbrowserloadend', function if1_loadend() { + iframe1.removeEventListener('mozbrowserloadend', if1_loadend); + ok(true, 'Got first loadend event.'); + SimpleTest.executeSoon(runTest2); + }); + 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); diff --git a/dom/browser-element/mochitest/browserElement_DocumentFirstPaint.js b/dom/browser-element/mochitest/browserElement_DocumentFirstPaint.js new file mode 100644 index 000000000..16618829e --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_DocumentFirstPaint.js @@ -0,0 +1,69 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 829486 - Add mozdocumentbrowserfirstpaint event. +"use strict"; + +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); diff --git a/dom/browser-element/mochitest/browserElement_Download.js b/dom/browser-element/mochitest/browserElement_Download.js new file mode 100644 index 000000000..965387657 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Download.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 983747 - Test 'download' method on iframe. + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +var iframe; +var downloadURL = 'http://test/tests/dom/browser-element/mochitest/file_download_bin.sjs'; + +function runTest() { + iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowserloadend', loadend); + iframe.src = 'data:text/html,<html><body>hello</body></html>'; + iframe.setAttribute('remote', 'true'); + + document.body.appendChild(iframe); +} + +function loadend() { + var req = iframe.download(downloadURL, { filename: 'test.bin' }); + req.onsuccess = function() { + ok(true, 'Download finished as expected.'); + SimpleTest.finish(); + } + req.onerror = function() { + ok(false, 'Expected no error, got ' + req.error); + } +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_ErrorSecurity.js b/dom/browser-element/mochitest/browserElement_ErrorSecurity.js new file mode 100644 index 000000000..c13a37140 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ErrorSecurity.js @@ -0,0 +1,58 @@ +/* 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"; + +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); diff --git a/dom/browser-element/mochitest/browserElement_ExecuteScript.js b/dom/browser-element/mochitest/browserElement_ExecuteScript.js new file mode 100644 index 000000000..901964999 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ExecuteScript.js @@ -0,0 +1,119 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1174733 - Browser API: iframe.executeScript + +'use strict'; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + + const origin = 'http://example.org'; + const url = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_ExecuteScript.html'; + + // Test if all key=>value pairs in o1 are present in o2. + const c = (o1, o2) => Object.keys(o1).every(k => o1[k] == o2[k]); + + let scriptId = 0; + + const bail = () => { + ok(false, `scriptId: ${scriptId++}`); + } + + SpecialPowers.pushPermissions([ + {type: 'browser', allow: 1, context: document}, + {type: 'browser:universalxss', allow: 1, context: document} + ], function() { + let iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.addEventListener('mozbrowserloadend', function onload() { + iframe.removeEventListener('mozbrowserloadend', onload); + onReady(iframe); + }); + iframe.src = url; + document.body.appendChild(iframe); + }); + + + function onReady(iframe) { + iframe.executeScript('4 + 4', {url}).then(rv => { + is(rv, 8, `scriptId: ${scriptId++}`); + return iframe.executeScript('(() => {return {a:42}})()', {url}) + }, bail).then(rv => { + ok(c(rv, {a:42}), `scriptId: ${scriptId++}`); + return iframe.executeScript('(() => {return {a:42}})()', {origin}) + }, bail).then(rv => { + ok(c(rv, {a:42}), `scriptId: ${scriptId++}`); + return iframe.executeScript('(() => {return {a:42}})()', {origin, url}) + }, bail).then(rv => { + ok(c(rv, {a:42}), `scriptId: ${scriptId++}`); + return iframe.executeScript(` + new Promise((resolve, reject) => { + resolve(document.body.textContent.trim()); + }); + `, {url}) + }, bail).then(rv => { + is(rv, 'foo', `scriptId: ${scriptId++}`); + return iframe.executeScript(` + new Promise((resolve, reject) => { + resolve({a:43,b:34}); + }); + `, {url}) + }, bail).then(rv => { + ok(c(rv, {a:43,b:34}), `scriptId: ${scriptId++}`); + return iframe.executeScript(` + … syntax error + `, {url}); + }, bail).then(bail, (error) => { + is(error.name, 'SyntaxError: illegal character', `scriptId: ${scriptId++}`); + return iframe.executeScript(` + window + `, {url}); + }).then(bail, (error) => { + is(error.name, 'Script last expression must be a promise or a JSON object', `scriptId: ${scriptId++}`); + return iframe.executeScript(` + new Promise((resolve, reject) => { + reject('BOOM'); + }); + `, {url}); + }).then(bail, (error) => { + is(error.name, 'BOOM', `scriptId: ${scriptId++}`); + return iframe.executeScript(` + new Promise((resolve, reject) => { + resolve(window); + }); + `, {url}); + }).then(bail, (error) => { + is(error.name, 'Value returned (resolve) by promise is not a valid JSON object', `scriptId: ${scriptId++}`); + return iframe.executeScript('window.btoa("a")', {url}) + }, bail).then(rv => { + ok(c(rv, 'YQ=='), `scriptId: ${scriptId++}`); + return iframe.executeScript('window.wrappedJSObject.btoa("a")', {url}) + }, bail).then(bail, (error) => { + is(error.name, 'TypeError: window.wrappedJSObject is undefined', `scriptId: ${scriptId++}`); + return iframe.executeScript('42', {}) + }).then(bail, error => { + is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`); + return iframe.executeScript('42'); + }).then(bail, error => { + is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`); + return iframe.executeScript('43', { url: 'http://foo.com' }); + }).then(bail, (error) => { + is(error.name, 'URL mismatches', `scriptId: ${scriptId++}`); + return iframe.executeScript('43', { url: '_' }); + }, bail).then(bail, (error) => { + is(error.name, 'Malformed URL', `scriptId: ${scriptId++}`); + return iframe.executeScript('43', { origin: 'http://foo.com' }); + }, bail).then(bail, (error) => { + is(error.name, 'Origin mismatches', `scriptId: ${scriptId++}`); + return iframe.executeScript('43', { origin: 'https://example.org' }); + }, bail).then(bail, (error) => { + is(error.name, 'Origin mismatches', `scriptId: ${scriptId++}`); + SimpleTest.finish(); + }); + } +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_ExposableURI.js b/dom/browser-element/mochitest/browserElement_ExposableURI.js new file mode 100644 index 000000000..435e11a80 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ExposableURI.js @@ -0,0 +1,55 @@ +/* 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"; +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 testWyciwyg() { + var locationChangeCount = 0; + + function locationchange(e) { + // locationChangeCount: + // 0 - the first load. + // 1 - after document.write(). + if (locationChangeCount == 0) { + locationChangeCount ++; + } else if (locationChangeCount == 1) { + var uri = e.detail.url; + is(uri, 'http://mochi.test:8888/tests/dom/browser-element/mochitest/file_wyciwyg.html', "Scheme in string shouldn't be wyciwyg"); + iframe.removeEventListener('mozbrowserlocationchange', locationchange); + SimpleTest.executeSoon(testPassword); + } + } + + // file_wyciwyg.html calls document.write() to create a wyciwyg channel. + iframe.src = 'file_wyciwyg.html'; + iframe.addEventListener('mozbrowserlocationchange', locationchange); +} + +function runTest() { + iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + testWyciwyg(); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_Find.js b/dom/browser-element/mochitest/browserElement_Find.js new file mode 100644 index 000000000..3a4968119 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Find.js @@ -0,0 +1,145 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1163961 - Test search API + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + + let iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.src = 'data:text/html,foo bar foo XXX Foo BAR foobar foobar'; + + const once = (eventName) => { + return new Promise((resolve) => { + iframe.addEventListener(eventName, function onEvent(...args) { + iframe.removeEventListener(eventName, onEvent); + resolve(...args); + }); + }); + } + + // Test if all key=>value pairs in o1 are present in o2. + const c = (o1, o2) => Object.keys(o1).every(k => o1[k] == o2[k]); + + let testCount = 0; + + once('mozbrowserloadend').then(() => { + iframe.findAll('foo', 'case-insensitive'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'foo', + searchLimit: 1000, + activeMatchOrdinal: 1, + numberOfMatches: 5, + }), `test ${testCount++}`); + iframe.findNext('forward'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'foo', + searchLimit: 1000, + activeMatchOrdinal: 2, + numberOfMatches: 5, + }), `test ${testCount++}`); + iframe.findNext('backward'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'foo', + searchLimit: 1000, + activeMatchOrdinal: 1, + numberOfMatches: 5, + }), `test ${testCount++}`); + iframe.findAll('xxx', 'case-sensitive'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'xxx', + searchLimit: 1000, + activeMatchOrdinal: 0, + numberOfMatches: 0, + }), `test ${testCount++}`); + iframe.findAll('bar', 'case-insensitive'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'bar', + searchLimit: 1000, + activeMatchOrdinal: 1, + numberOfMatches: 4, + }), `test ${testCount++}`); + iframe.findNext('forward'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'bar', + searchLimit: 1000, + activeMatchOrdinal: 2, + numberOfMatches: 4, + }), `test ${testCount++}`); + iframe.findNext('forward'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'bar', + searchLimit: 1000, + activeMatchOrdinal: 3, + numberOfMatches: 4, + }), `test ${testCount++}`); + iframe.findNext('forward'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'bar', + searchLimit: 1000, + activeMatchOrdinal: 4, + numberOfMatches: 4, + }), `test ${testCount++}`); + iframe.findNext('forward'); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: true, + searchString: 'bar', + searchLimit: 1000, + activeMatchOrdinal: 1, + numberOfMatches: 4, + }), `test ${testCount++}`); + iframe.clearMatch(); + return once('mozbrowserfindchange'); + }).then(({detail}) => { + ok(c(detail, { + msg_name: "findchange", + active: false + }), `test ${testCount++}`); + SimpleTest.finish(); + }); + + document.body.appendChild(iframe); + +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_FirstPaint.js b/dom/browser-element/mochitest/browserElement_FirstPaint.js new file mode 100644 index 000000000..ad67abc3a --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_FirstPaint.js @@ -0,0 +1,43 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 787378 - Add mozbrowserfirstpaint event. +"use strict"; + +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); diff --git a/dom/browser-element/mochitest/browserElement_ForwardName.js b/dom/browser-element/mochitest/browserElement_ForwardName.js new file mode 100644 index 000000000..326c1ef24 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ForwardName.js @@ -0,0 +1,43 @@ +/* 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"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.setAttribute('name', 'foo'); + + iframe.addEventListener("mozbrowseropenwindow", function(e) { + ok(false, 'Got mozbrowseropenwindow, but should not have.'); + }); + + 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); diff --git a/dom/browser-element/mochitest/browserElement_FrameWrongURI.js b/dom/browser-element/mochitest/browserElement_FrameWrongURI.js new file mode 100644 index 000000000..c3f37b4c8 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_FrameWrongURI.js @@ -0,0 +1,52 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 804446 - Test that window.open(javascript:..) works with <iframe mozbrowser>. + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframeJS = document.createElement('iframe'); + iframeJS.setAttribute('mozbrowser', 'true'); + + iframeJS.addEventListener('mozbrowserloadstart', function(e) { + ok(false, "This should not happen!"); + }); + + iframeJS.addEventListener('mozbrowserloadend', function(e) { + ok(false, "This should not happen!"); + }); + + iframeJS.src = 'javascript:alert("Foo");'; + document.body.appendChild(iframeJS); + + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + var gotPopup = false; + iframe.addEventListener('mozbrowseropenwindow', function(e) { + is(gotPopup, false, 'Should get just one popup.'); + gotPopup = true; + + document.body.appendChild(e.detail.frameElement); + }); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + ok(gotPopup, 'Got mozbrowseropenwindow event before showmodalprompt event.'); + if (e.detail.message.indexOf("success") == 0) { + ok(true, e.detail.message); + SimpleTest.finish(); + } + else { + ok(false, "Got invalid message: " + e.detail.message); + } + }); + + iframe.src = 'file_browserElement_FrameWrongURI.html'; + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_GetContentDimensions.js b/dom/browser-element/mochitest/browserElement_GetContentDimensions.js new file mode 100644 index 000000000..722c42b77 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_GetContentDimensions.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 757859 - Test the getContentDimensions functionality of mozbrowser + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var resizeContent = function() { + var innerBox = content.document.getElementById('abox'); + innerBox.style.width = '800px'; + innerBox.style.height = '800px'; +} + +function runTest() { + + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + + var iframeWidth = 400; + var iframeHeight = 400; + var numIframeLoaded = 0; + var numResizeEvents = 0; + var mm; + + iframe1.src = 'data:text/html,<html><body><div id=\'abox\' ' + + 'style=\'background:blue;width:200px;height:200px\'>test</div></body></html>'; + iframe1.style.width = iframeWidth + 'px'; + iframe1.style.height = iframeHeight + 'px'; + document.body.appendChild(iframe1); + + function iframeScrollAreaChanged(e) { + numResizeEvents++; + if (numResizeEvents === 1) { + ok(true, 'Resize event when changing content size'); + ok(e.detail.width > iframeWidth, 'Iframes content is larger than iframe'); + ok(e.detail.height > iframeHeight, 'Iframes content is larger than iframe'); + iframe1.src = 'data:text/html,<html><body><div id=\'abox\' ' + + 'style=\'background:blue;width:200px;height:200px\'>test</div></body></html>'; + } else if (numResizeEvents === 2) { + ok(true, 'Resize event when changing src'); + iframe1.removeEventListener('mozbrowserresize', iframeScrollAreaChanged); + SimpleTest.finish(); + } + } + + function iframeLoadedHandler() { + iframe1.removeEventListener('mozbrowserloadend', iframeLoadedHandler); + mm = SpecialPowers.getBrowserFrameMessageManager(iframe1); + iframe1.getContentDimensions().onsuccess = function(e) { + ok(typeof e.target.result.width === 'number', 'Received width'); + ok(typeof e.target.result.height === 'number', 'Received height'); + ok(e.target.result.height <= iframeHeight, 'Iframes content is smaller than iframe'); + ok(e.target.result.width <= iframeWidth, 'Iframes content is smaller than iframe'); + iframe1.addEventListener('mozbrowserscrollareachanged', iframeScrollAreaChanged); + mm.loadFrameScript('data:,(' + resizeContent.toString() + ')();', false); + } + } + + iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler); +} + +addEventListener('load', function() { + SimpleTest.executeSoon(runTest); +}); diff --git a/dom/browser-element/mochitest/browserElement_GetScreenshot.js b/dom/browser-element/mochitest/browserElement_GetScreenshot.js new file mode 100644 index 000000000..75d70f04c --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_GetScreenshot.js @@ -0,0 +1,117 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test the getScreenshot property for mozbrowser +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + + iframe1.src = 'data:text/html,<html>' + + '<body style="background:green">hello</body></html>'; + document.body.appendChild(iframe1); + + var screenshotImageDatas = []; + + function screenshotTaken(aScreenshotImageData) { + screenshotImageDatas.push(aScreenshotImageData); + + if (screenshotImageDatas.length === 1) { + ok(true, 'Got initial non blank screenshot'); + + var view = aScreenshotImageData.data; + if (view[3] !== 255) { + ok(false, 'The first pixel of initial screenshot is not opaque'); + SimpleTest.finish(); + return; + } + ok(true, 'Verified the first pixel of initial screenshot is opaque'); + + iframe1.src = 'data:text/html,<html>' + + '<body style="background:transparent">hello</body></html>'; + + iframe1.addEventListener('mozbrowserloadend', ()=>takeScreenshot('image/png')); + + } + else if (screenshotImageDatas.length === 2) { + ok(true, 'Got updated screenshot after source page changed'); + + var view = aScreenshotImageData.data; + if (view[3] !== 0) { + // The case here will always fail when oop'd on Firefox Desktop, + // but not on B2G Emulator + // See https://bugzil.la/878003#c20 + + var isB2G = (navigator.platform === ''); + info('navigator.platform: ' + navigator.platform); + if (!isB2G && browserElementTestHelpers.getOOPByDefaultPref()) { + todo(false, 'The first pixel of updated screenshot is not transparent'); + } else { + ok(false, 'The first pixel of updated screenshot is not transparent'); + } + SimpleTest.finish(); + return; + } + + ok(true, 'Verified the first pixel of updated screenshot is transparent'); + SimpleTest.finish(); + } + } + + // We continually take screenshots until we get one that we are + // happy with. + function takeScreenshot(mimeType) { + function gotImage(e) { + // |this| is the Image. + + URL.revokeObjectURL(this.src); + + if (e.type === 'error' || !this.width || !this.height) { + ok(false, "load image error"); + SimpleTest.finish(); + return; + } + + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1000; + var ctx = canvas.getContext('2d'); + ctx.drawImage(this, 0, 0); + var imageData = ctx.getImageData(0, 0, 1000, 1000); + + screenshotTaken(imageData); + } + + function getScreenshotImageData(e) { + var blob = e.target.result; + if (blob.type !== mimeType) { + ok(false, 'MIME type of screenshot taken incorrect'); + SimpleTest.finish(); + } + + if (blob.size === 0) { + ok(false, "get screenshot image error"); + SimpleTest.finish(); + } + + var img = new Image(); + img.src = URL.createObjectURL(blob); + img.onload = img.onerror = gotImage; + } + + iframe1.getScreenshot(1000, 1000, mimeType).onsuccess = + getScreenshotImageData; + } + + function iframeLoadedHandler(e) { + iframe1.removeEventListener('mozbrowserloadend', iframeLoadedHandler); + takeScreenshot('image/jpeg'); + } + + iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_GetScreenshotDppx.js b/dom/browser-element/mochitest/browserElement_GetScreenshotDppx.js new file mode 100644 index 000000000..1d61f6afc --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_GetScreenshotDppx.js @@ -0,0 +1,107 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test the getScreenshot property for mozbrowser +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + var dppxPref = 'layout.css.devPixelsPerPx'; + var cssPixelWidth = 600; + var cssPixelHeight = 400; + + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('width', cssPixelWidth); + iframe1.setAttribute('height', cssPixelHeight); + iframe1.setAttribute('mozbrowser', 'true'); + + iframe1.src = 'data:text/html,<html><body>hello</body></html>'; + document.body.appendChild(iframe1); + + var images = []; + + function screenshotTaken(image) { + images.push(image); + if (images.length === 1) { + ok(true, 'Got initial non blank screenshot'); + + if (image.width !== cssPixelWidth || image.height !== cssPixelHeight) { + ok(false, 'The pixel width of the image received is not correct'); + SimpleTest.finish(); + return; + } + ok(true, 'The pixel width of the image received is correct'); + + SpecialPowers.pushPrefEnv( + {'set': [['layout.css.devPixelsPerPx', 2]]}, takeScreenshot); + } + else if (images.length === 2) { + ok(true, 'Got updated screenshot after source page changed'); + + if (image.width !== cssPixelWidth * 2 || + image.height !== cssPixelHeight * 2) { + ok(false, 'The pixel width of the 2dppx image received is not correct'); + SimpleTest.finish(); + return; + } + ok(true, 'The pixel width of the 2dppx image received is correct'); + SimpleTest.finish(); + } + } + + function takeScreenshot() { + function gotImage(e) { + // |this| is the Image. + + URL.revokeObjectURL(this.src); + + if (e.type === 'error' || !this.width || !this.height) { + tryAgain(); + + return; + } + + screenshotTaken(this); + } + + function tryAgain() { + if (--attempts === 0) { + ok(false, 'Timed out waiting for correct screenshot'); + SimpleTest.finish(); + } else { + setTimeout(function() { + iframe1.getScreenshot(cssPixelWidth, cssPixelHeight).onsuccess = + getScreenshotImageData; + }, 200); + } + } + + function getScreenshotImageData(e) { + var blob = e.target.result; + if (blob.size === 0) { + tryAgain(); + + return; + } + + var img = new Image(); + img.src = URL.createObjectURL(blob); + img.onload = img.onerror = gotImage; + } + + var attempts = 10; + iframe1.getScreenshot(cssPixelWidth, cssPixelHeight).onsuccess = + getScreenshotImageData; + } + + function iframeLoadedHandler() { + SpecialPowers.pushPrefEnv( + {'set': [['layout.css.devPixelsPerPx', 1]]}, takeScreenshot); + } + + iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_Iconchange.js b/dom/browser-element/mochitest/browserElement_Iconchange.js new file mode 100644 index 000000000..367a2de15 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Iconchange.js @@ -0,0 +1,129 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the onmozbrowsericonchange event works. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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); diff --git a/dom/browser-element/mochitest/browserElement_LoadEvents.js b/dom/browser-element/mochitest/browserElement_LoadEvents.js new file mode 100644 index 000000000..8b43d8e75 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_LoadEvents.js @@ -0,0 +1,120 @@ +/* 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"; +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.'); + ok(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.'); + ok(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, 'transparent', 'Expected background color reported') + }); + + iframe.src = browserElementTestHelpers.emptyPage2; + + function waitForAllCallbacks() { + if (!seenLoadStart || !seenLoadEnd || !seenLocationChange) { + SimpleTest.executeSoon(waitForAllCallbacks); + return; + } + + SimpleTest.finish(); + } + + waitForAllCallbacks(); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_Manifestchange.js b/dom/browser-element/mochitest/browserElement_Manifestchange.js new file mode 100644 index 000000000..22cf8fe7c --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Manifestchange.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the onmozbrowsermanifestchange event works. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function createHtml(manifest) { + return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + manifest + '<body></body></html>'; +} + +function createManifest(href) { + return '<link rel="manifest" href="' + href + '">'; +} + +function runTest() { + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe1); + + // iframe2 is a red herring; we modify its manifest link elements but don't + // listen for manifestchanges; we want to make sure that its manifestchange + // 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 manifestchange events on it. + var iframe3 = document.createElement('iframe'); + document.body.appendChild(iframe3); + + var numManifestChanges = 0; + + iframe1.addEventListener('mozbrowsermanifestchange', function(e) { + + numManifestChanges++; + + if (numManifestChanges == 1) { + is(e.detail.href, 'manifest.1', 'manifest.1 matches'); + + // We should receive manifestchange events when the user creates new + // manifests + SpecialPowers.getBrowserFrameMessageManager(iframe1) + .loadFrameScript("data:,content.document.title='New title';", + /* allowDelayedLoad = */ false); + + SpecialPowers.getBrowserFrameMessageManager(iframe1) + .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=manifest href=manifest.2>')", + /* allowDelayedLoad = */ false); + + SpecialPowers.getBrowserFrameMessageManager(iframe2) + .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=manifest href=manifest.2>')", + /* allowDelayedLoad = */ false); + } + else if (numManifestChanges == 2) { + is(e.detail.href, 'manifest.2', 'manifest.2 matches'); + + // Full new pages should trigger manifestchange events + iframe1.src = createHtml(createManifest('manifest.3')); + } + else if (numManifestChanges == 3) { + is(e.detail.href, 'manifest.3', 'manifest.3 matches'); + + // Test setting a page with multiple manifest link elements + iframe1.src = createHtml(createManifest('manifest.4a') + createManifest('manifest.4b')); + } + else if (numManifestChanges == 4) { + is(e.detail.href, 'manifest.4a', 'manifest.4a matches'); + // 2 events will be triggered by previous test, wait for next + } + else if (numManifestChanges == 5) { + is(e.detail.href, 'manifest.4b', 'manifest.4b matches'); + SimpleTest.finish(); + } else { + ok(false, 'Too many manifestchange events.'); + } + }); + + iframe3.addEventListener('mozbrowsermanifestchange', function(e) { + ok(false, 'Should not get a manifestchange event for iframe3.'); + }); + + + iframe1.src = createHtml(createManifest('manifest.1')); + // We should not receive manifest change events for either of the below iframes + iframe2.src = createHtml(createManifest('manifest.1')); + iframe3.src = createHtml(createManifest('manifest.1')); + +} + +addEventListener('testready', runTest); + diff --git a/dom/browser-element/mochitest/browserElement_Metachange.js b/dom/browser-element/mochitest/browserElement_Metachange.js new file mode 100644 index 000000000..7789a3e18 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Metachange.js @@ -0,0 +1,177 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the onmozbrowsermetachange event works. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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); diff --git a/dom/browser-element/mochitest/browserElement_NextPaint.js b/dom/browser-element/mochitest/browserElement_NextPaint.js new file mode 100644 index 000000000..749a8efe3 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_NextPaint.js @@ -0,0 +1,43 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 808231 - Add mozbrowsernextpaint event. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + + // Add a first listener that we'll remove shortly after. + iframe.addNextPaintListener(wrongListener); + + var gotFirstNextPaintEvent = false; + iframe.addNextPaintListener(function () { + ok(!gotFirstNextPaintEvent, 'got the first nextpaint event'); + + // Make sure we're only called once. + gotFirstNextPaintEvent = true; + + iframe.addNextPaintListener(function () { + info('got the second nextpaint event'); + SimpleTest.finish(); + }); + + // Force the iframe to repaint. + SimpleTest.executeSoon(() => iframe.src += '#next'); + }); + + // Remove the first listener to make sure it's not called. + iframe.removeNextPaintListener(wrongListener); + iframe.src = 'file_browserElement_NextPaint.html'; +} + +function wrongListener() { + ok(false, 'first listener should have been removed'); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_NoAudioTrack.js b/dom/browser-element/mochitest/browserElement_NoAudioTrack.js new file mode 100644 index 000000000..47f0fd524 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_NoAudioTrack.js @@ -0,0 +1,96 @@ +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var fileURL = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/file_browserElement_NoAudioTrack.html'; +var generator = runTests(); +var testFrame; + +function alertListener(e) { + var message = e.detail.message; + if (/^OK/.exec(message)) { + ok(true, "Message from file : " + message); + continueTest(); + } else if (/^KO/.exec(message)) { + error(message); + } else { + error("Undefined event."); + } +} + +function error(aMessage) { + ok(false, "Error : " + aMessage); + finish(); +} + +function continueTest() { + try { + generator.next(); + } catch (e if e instanceof StopIteration) { + error("Stop test because of exception!"); + } +} + +function finish() { + testFrame.removeEventListener('mozbrowsershowmodalprompt', alertListener); + ok(true, "Remove event-listener."); + document.body.removeChild(testFrame); + ok(true, "Remove test-frame from document."); + SimpleTest.finish(); +} + +function setCommand(aArg) { + info("# Command = " + aArg); + testFrame.src = fileURL + '#' + aArg; +} + +function runTests() { + setCommand('play'); + yield undefined; + + // wait a second to make sure that onactivestatechanged isn't dispatched. + setCommand('idle'); + yield undefined; + + finish(); + yield undefined; +} + +function setupTestFrame() { + testFrame = document.createElement('iframe'); + testFrame.setAttribute('mozbrowser', 'true'); + testFrame.src = fileURL; + + function loadend() { + testFrame.removeEventListener('mozbrowserloadend', loadend); + ok("allowedAudioChannels" in testFrame, "allowedAudioChannels exist"); + var channels = testFrame.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + var ac = channels[0]; + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("onactivestatechanged" in ac, "onactivestatechanged exists"); + + ac.onactivestatechanged = () => { + ac.onactivestatechanged = null; + ok(true, "Should receive onactivestatechanged!"); + }; + + continueTest(); + } + + testFrame.addEventListener('mozbrowserloadend', loadend); + testFrame.addEventListener('mozbrowsershowmodalprompt', alertListener); + ok(true, "Add event-listeners."); + + document.body.appendChild(testFrame); + ok(true, "Append test-frame to document."); +} + +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set': [["b2g.system_startup_url", window.location.href]]}, + function() { + SimpleTest.executeSoon(setupTestFrame); + }); +}); diff --git a/dom/browser-element/mochitest/browserElement_OpenMixedProcess.js b/dom/browser-element/mochitest/browserElement_OpenMixedProcess.js new file mode 100644 index 000000000..c5cde7f50 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenMixedProcess.js @@ -0,0 +1,105 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 776129 - If a window w calls window.open, the resultant window should be +// remote iff w is remote. +// +// <iframe mozbrowser> can be default-OOP or default-in-process. But we can +// override this default by setting remote=true or remote=false on the iframe. +// +// This bug arises when we are default-in-process and a OOP iframe calls +// window.open, or when we're default-OOP and an in-process iframe calls +// window.open. In either case, if the opened iframe gets the default +// remotness, it will not match its opener's remoteness, which is bad. +// +// Since the name of the test determines the OOP-by-default pref, the "inproc" +// version of this test opens an OOP frame, and the "oop" version opens an +// in-process frame. Enjoy. :) + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + // We're going to open a remote frame if OOP off by default. If OOP is on by + // default, we're going to open an in-process frame. + var remote = !browserElementTestHelpers.getOOPByDefaultPref(); + + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.setAttribute('remote', remote); + + // The page we load does window.open, then checks some things and reports + // back using alert(). Finally, it calls alert('finish'). + // + // Bug 776129 in particular manifests itself such that the popup frame loads + // and the tests in file_browserElement_OpenMixedProcess pass, but the + // content of the frame is invisible. To catch this case, we take a + // screenshot after we load the content into the popup, and ensure that it's + // not blank. + var popup; + iframe.addEventListener('mozbrowseropenwindow', function(e) { + popup = document.body.appendChild(e.detail.frameElement); + }); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + if (e.detail.message.startsWith('pass')) { + ok(true, e.detail.message); + } + else if (e.detail.message.startsWith('fail')) { + ok(false, e.detail.message); + } + else if (e.detail.message == 'finish') { + // We assume here that iframe is completely blank, and spin until popup's + // screenshot is not the same as iframe. + iframe.getScreenshot(1000, 1000).onsuccess = function(e) { + var fr = new FileReader(); + fr.onloadend = function() { test2(popup, fr.result); }; + fr.readAsArrayBuffer(e.target.result); + }; + } + else { + ok(false, e.detail.message, "Unexpected message!"); + } + }); + + document.body.appendChild(iframe); + iframe.src = 'file_browserElement_OpenMixedProcess.html'; +} + +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 test2(popup, blankScreenshotArrayBuffer) { + // Take screenshots of popup until it doesn't equal blankScreenshot (or we + // time out). + popup.getScreenshot(1000, 1000).onsuccess = function(e) { + var fr = new FileReader(); + fr.onloadend = function() { + if (!arrayBuffersEqual(blankScreenshotArrayBuffer, fr.result)) { + ok(true, "Finally got a non-blank screenshot."); + SimpleTest.finish(); + return; + } + + SimpleTest.executeSoon(function() { test2(popup, blankScreenshot) }); + }; + fr.readAsArrayBuffer(e.target.result); + }; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenNamed.js b/dom/browser-element/mochitest/browserElement_OpenNamed.js new file mode 100644 index 000000000..aed5617e9 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenNamed.js @@ -0,0 +1,57 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 742944 - In <iframe mozbrowser>, test that if we call window.open twice +// with the same name, we get only one mozbrowseropenwindow event. + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +var iframe; +var popupFrame; +function runTest() { + iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + var gotPopup = false; + iframe.addEventListener('mozbrowseropenwindow', function(e) { + is(gotPopup, false, 'Should get just one popup.'); + gotPopup = true; + popupFrame = e.detail.frameElement; + is(popupFrame.getAttribute('name'), 'OpenNamed'); + + // Called when file_browserElement_OpenNamed2.html loads into popupFrame. + popupFrame.addEventListener('mozbrowsershowmodalprompt', function promptlistener(e) { + popupFrame.removeEventListener('mozbrowsershowmodalprompt', promptlistener); + + ok(gotPopup, 'Got openwindow event before showmodalprompt event.'); + is(e.detail.message, 'success: loaded'); + SimpleTest.executeSoon(test2); + }); + + document.body.appendChild(popupFrame); + }); + + // OpenNamed.html will call + // + // window.open('file_browserElement_OpenNamed2.html', 'OpenNamed'). + // + // Once that popup loads, we reload OpenNamed.html. That will call + // window.open again, but we shouldn't get another openwindow event, because + // we're opening into the same named window. + iframe.src = 'file_browserElement_OpenNamed.html'; + document.body.appendChild(iframe); +} + +function test2() { + popupFrame.addEventListener('mozbrowsershowmodalprompt', function(e) { + is(e.detail.message, 'success: loaded'); + SimpleTest.finish(); + }); + + iframe.src = 'file_browserElement_OpenNamed.html?test2'; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenTab.js b/dom/browser-element/mochitest/browserElement_OpenTab.js new file mode 100644 index 000000000..d01927e9b --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenTab.js @@ -0,0 +1,69 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1144015 - test middle/ctrl/cmd-click on a link. + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + let iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + + let x = 2; + let y = 2; + // First we force a reflow so that getChildProcessOffset actually returns + // meaningful data. + iframe.getBoundingClientRect(); + // We need to make sure the event coordinates are actually inside the iframe, + // relative to the chome window. + let tabParent = SpecialPowers.wrap(iframe) + .QueryInterface(SpecialPowers.Ci.nsIFrameLoaderOwner) + .frameLoader.tabParent; + if (tabParent) { + let offsetX = {}; + let offsetY = {}; + tabParent.getChildProcessOffset(offsetX, offsetY); + x -= offsetX.value; + y -= offsetY.value; + } + + let sendCtrlClick = () => { + let nsIDOMWindowUtils = SpecialPowers.Ci.nsIDOMWindowUtils; + let mod = nsIDOMWindowUtils.MODIFIER_META | + nsIDOMWindowUtils.MODIFIER_CONTROL; + iframe.sendMouseEvent('mousedown', x, y, 0, 1, mod); + iframe.sendMouseEvent('mouseup', x, y, 0, 1, mod); + } + + let onCtrlClick = e => { + is(e.detail.url, 'http://example.com/', 'URL matches'); + iframe.removeEventListener('mozbrowseropentab', onCtrlClick); + iframe.addEventListener('mozbrowseropentab', onMiddleClick); + sendMiddleClick(); + } + + let sendMiddleClick = () => { + iframe.sendMouseEvent('mousedown', x, y, 1, 1, 0); + iframe.sendMouseEvent('mouseup', x, y, 1, 1, 0); + } + + let onMiddleClick = e => { + is(e.detail.url, 'http://example.com/', 'URL matches'); + iframe.removeEventListener('mozbrowseropentab', onMiddleClick); + SimpleTest.finish(); + } + + iframe.addEventListener('mozbrowserloadend', e => { + iframe.addEventListener('mozbrowseropentab', onCtrlClick); + sendCtrlClick(); + }); + + + iframe.src = 'data:text/html,<body style="margin:0"><a href="http://example.com"><span>click here</span></a></body>'; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenWindow.js b/dom/browser-element/mochitest/browserElement_OpenWindow.js new file mode 100644 index 000000000..65de11a26 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenWindow.js @@ -0,0 +1,58 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 742944 - Test that window.open works with <iframe mozbrowser>. + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + var gotPopup = false; + iframe.addEventListener('mozbrowseropenwindow', function(e) { + is(gotPopup, false, 'Should get just one popup.'); + gotPopup = true; + + document.body.appendChild(e.detail.frameElement); + + ok(/file_browserElement_Open2\.html$/.test(e.detail.url), + "Popup's URL (got " + e.detail.url + ")"); + is(e.detail.name, "name"); + is(e.detail.features, "dialog=1"); + }); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + ok(gotPopup, 'Got mozbrowseropenwindow event before showmodalprompt event.'); + if (e.detail.message.indexOf("success:") == 0) { + ok(true, e.detail.message); + } + else if (e.detail.message.indexOf("failure:") == 0) { + ok(false, e.detail.message); + } + else if (e.detail.message == "finish") { + SimpleTest.finish(); + } + else { + ok(false, "Got invalid message: " + e.detail.message); + } + }); + + /** + * file_browserElementOpen1 does + * + * window.open('file_browserElement_Open2.html', 'name', 'dialog=1') + * + * then adds an event listener to the opened window and waits for onload. + * + * Onload, we fire a few alerts saying "success:REASON" or "failure:REASON". + * Finally, we fire a "finish" alert, which ends the test. + */ + iframe.src = 'file_browserElement_Open1.html'; + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenWindowDifferentOrigin.js b/dom/browser-element/mochitest/browserElement_OpenWindowDifferentOrigin.js new file mode 100644 index 000000000..650ef17f5 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenWindowDifferentOrigin.js @@ -0,0 +1,41 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 769182 - window.open to a different origin should load the page. + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowseropenwindow', function(e) { + ok(true, 'Got first window.open call'); + + e.detail.frameElement.addEventListener('mozbrowseropenwindow', function(e) { + ok(true, 'Got second window.open call'); + document.body.appendChild(e.detail.frameElement); + }); + + e.detail.frameElement.addEventListener('mozbrowsershowmodalprompt', function(e) { + ok(true, 'Got alert from second window.'); + SimpleTest.finish(); + }); + + document.body.appendChild(e.detail.frameElement); + }); + + // DifferentOrigin.html?1 calls + // + // window.open('http://example.com/.../DifferentOrigin.html?2'), + // + // which calls alert(). + + iframe.src = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_OpenWindowDifferentOrigin.html?1'; + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenWindowEmpty.js b/dom/browser-element/mochitest/browserElement_OpenWindowEmpty.js new file mode 100644 index 000000000..6b8dd0340 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenWindowEmpty.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1216937 - Test that window.open with null/empty URL should use +// about:blank as default + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + var gotPopup = false; + iframe.addEventListener('mozbrowseropenwindow', function(e) { + is(gotPopup, false, 'Should get just one popup.'); + gotPopup = true; + + is(e.detail.url, 'about:blank', "Popup's has correct URL"); + e.preventDefault(); + + SimpleTest.finish(); + }); + + iframe.src = 'file_browserElement_OpenWindowEmpty.html'; + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenWindowInFrame.js b/dom/browser-element/mochitest/browserElement_OpenWindowInFrame.js new file mode 100644 index 000000000..5559bbcb8 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenWindowInFrame.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 766871 - Test that window.open works from an <iframe> within <iframe mozbrowser>. +// +// This is basically the same as browserElement_OpenWindow, except that instead +// of loading file_browserElement_Open1.html directly inside the <iframe +// mozbrowser>, we load file_browserElement_OpenWindowInFrame.html into the +// mozbrowser. OpenWindowInFrame loads file_browserElement_Open1.html inside +// an iframe. + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + var gotPopup = false; + iframe.addEventListener('mozbrowseropenwindow', function(e) { + is(gotPopup, false, 'Should get just one popup.'); + gotPopup = true; + + document.body.appendChild(e.detail.frameElement); + + ok(/file_browserElement_Open2\.html$/.test(e.detail.url), + "Popup's URL (got " + e.detail.url + ")"); + is(e.detail.name, "name"); + is(e.detail.features, "dialog=1"); + }); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + ok(gotPopup, 'Got mozbrowseropenwindow event before showmodalprompt event.'); + if (e.detail.message.indexOf("success:") == 0) { + ok(true, e.detail.message); + } + else if (e.detail.message.indexOf("failure:") == 0) { + ok(false, e.detail.message); + } + else if (e.detail.message == "finish") { + SimpleTest.finish(); + } + else { + ok(false, "Got invalid message: " + e.detail.message); + } + }); + + /** + * file_browserElement_OpenWindowInFrame.html loads + * file_browserElement_Open1.html in an iframe. Open1.html does + * + * window.open('file_browserElement_Open2.html', 'name', 'dialog=1') + * + * then adds an event listener to the opened window and waits for onload. + * + * Onload, we fire a few alerts saying "success:REASON" or "failure:REASON". + * Finally, we fire a "finish" alert, which ends the test. + */ + iframe.src = 'file_browserElement_OpenWindowInFrame.html'; + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js b/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js new file mode 100644 index 000000000..f5ef97260 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 742944 - Do window.open from inside <iframe mozbrowser>. But then +// reject the call. This shouldn't cause problems (crashes, leaks). + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowseropenwindow', function(e) { + ok(e.detail.url.indexOf('does_not_exist.html') != -1, + 'Opened URL; got ' + e.detail.url); + is(e.detail.name, ''); + is(e.detail.features, ''); + + // Don't add e.detail.frameElement to the DOM, so the window.open is + // effectively blocked. + e.preventDefault(); + }); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + var msg = e.detail.message; + if (msg.indexOf('success:') == 0) { + ok(true, msg); + } + else if (msg == 'finish') { + SimpleTest.finish(); + } + else { + ok(false, msg); + } + }); + + iframe.src = 'file_browserElement_OpenWindowRejected.html'; + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_OpenWindowRejected2.js b/dom/browser-element/mochitest/browserElement_OpenWindowRejected2.js new file mode 100644 index 000000000..acea6813e --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_OpenWindowRejected2.js @@ -0,0 +1,47 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 742944 - Do window.open from inside <iframe mozbrowser>. But then +// reject the call. This shouldn't cause problems (crashes, leaks). +// +// This is the same as OpenWindowRejected, except we "reject" the popup by not +// adding the iframe element to our DOM, instead of by not calling +// preventDefault() on the event. + +"use strict"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowseropenwindow', function(e) { + ok(e.detail.url.indexOf('does_not_exist.html') != -1, + 'Opened URL; got ' + e.detail.url); + is(e.detail.name, ''); + is(e.detail.features, ''); + + // Call preventDefault, but don't add the iframe to the DOM. This still + // amounts to rejecting the popup. + e.preventDefault(); + }); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + var msg = e.detail.message; + if (msg.indexOf('success:') == 0) { + ok(true, msg); + } + else if (msg == 'finish') { + SimpleTest.finish(); + } + else { + ok(false, msg); + } + }); + + iframe.src = 'file_browserElement_OpenWindowRejected.html'; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_Opensearch.js b/dom/browser-element/mochitest/browserElement_Opensearch.js new file mode 100644 index 000000000..8df44d2a9 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Opensearch.js @@ -0,0 +1,109 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the onmozbrowseropensearch event works. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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); diff --git a/dom/browser-element/mochitest/browserElement_PrivateBrowsing.js b/dom/browser-element/mochitest/browserElement_PrivateBrowsing.js new file mode 100644 index 000000000..c32edcc37 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_PrivateBrowsing.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the mozprivatebrowsing attribute works. +"use strict"; + +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); diff --git a/dom/browser-element/mochitest/browserElement_PromptCheck.js b/dom/browser-element/mochitest/browserElement_PromptCheck.js new file mode 100644 index 000000000..d6edde09f --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_PromptCheck.js @@ -0,0 +1,59 @@ +/* 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"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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(); + } + }); + + 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>'; +} + +// 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); +}); diff --git a/dom/browser-element/mochitest/browserElement_PromptConfirm.js b/dom/browser-element/mochitest/browserElement_PromptConfirm.js new file mode 100644 index 000000000..c01836a25 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_PromptConfirm.js @@ -0,0 +1,87 @@ +/* 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"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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(); + } + } + }); + + 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>'; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_Proxy.js b/dom/browser-element/mochitest/browserElement_Proxy.js new file mode 100644 index 000000000..227b40c5f --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Proxy.js @@ -0,0 +1,163 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + let frameUrl = SimpleTest.getTestFileURL('/file_empty.html'); + SpecialPowers.pushPermissions([{ + type: 'browser:embedded-system-app', + allow: true, + context: { + url: frameUrl, + originAttributes: { + inIsolatedMozBrowser: true + } + } + },{ + type: 'browser', + allow: true, + context: { + url: frameUrl, + originAttributes: { + inIsolatedMozBrowser: true + } + } + }], createFrame); +} + +var frame; +var mm; + +function createFrame() { + let loadEnd = function() { + // The frame script running in the frame where the input is hosted. + let appFrameScript = function appFrameScript() { + let i = 1; + + addMessageListener('test:next', function() { + try { + switch (i) { + case 1: + content.document.addEventListener( + 'visibilitychange', function fn() { + content.document.removeEventListener('visibilitychange', fn); + sendAsyncMessage('test:done', { + ok: true, + msg: 'setVisible()' + }); + }); + + // Test a no return method + content.navigator.mozBrowserElementProxy.setVisible(false); + + break; + case 2: + // Test a DOMRequest method + var req = content.navigator.mozBrowserElementProxy.getVisible(); + req.onsuccess = function() { + sendAsyncMessage('test:done', { + ok: true, + msg: 'getVisible()' + }); + }; + + req.onerror = function() { + sendAsyncMessage('test:done', { + ok: false, + msg: 'getVisible() DOMRequest return error.' + }); + }; + + break; + case 3: + // Test an unimplemented method + try { + content.navigator.mozBrowserElementProxy.getActive(); + sendAsyncMessage('test:done', { + ok: false, + msg: 'getActive() should throw.' + }); + + } catch (e) { + sendAsyncMessage('test:done', { + ok: true, + msg: 'getActive() throws.' + }); + } + + break; + case 4: + content.navigator.mozBrowserElementProxy + .addEventListener( + 'mozbrowserlocationchange', + function() { + content.navigator.mozBrowserElementProxy + .onmozbrowserlocationchange = null; + + sendAsyncMessage('test:done', { + ok: true, + msg: 'mozbrowserlocationchange' + }); + }); + + // Test event + content.location.hash = '#foo'; + + break; + } + } catch (e) { + sendAsyncMessage('test:done', { + ok: false, msg: 'thrown: ' + e.toString() }); + } + + i++; + }); + + sendAsyncMessage('test:done', {}); + } + + mm = SpecialPowers.getBrowserFrameMessageManager(frame); + mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false); + mm.addMessageListener("test:done", next); + }; + + frame = document.createElement('iframe'); + frame.setAttribute('mozbrowser', 'true'); + frame.src = 'file_empty.html'; + document.body.appendChild(frame); + frame.addEventListener('mozbrowserloadend', loadEnd); +} + +var i = 0; +function next(msg) { + let wrappedMsg = SpecialPowers.wrap(msg); + let isOK = wrappedMsg.data.ok; + let msgString = wrappedMsg.data.msg; + + switch (i) { + case 0: + mm.sendAsyncMessage('test:next'); + break; + + case 1: + case 2: + case 3: + ok(isOK, msgString); + mm.sendAsyncMessage('test:next'); + break; + + case 4: + ok(isOK, msgString); + SimpleTest.finish(); + break; + } + + i++; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_PurgeHistory.js b/dom/browser-element/mochitest/browserElement_PurgeHistory.js new file mode 100644 index 000000000..4815f03e7 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_PurgeHistory.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 807056 - [Browser] Clear History doesn't clear back/forward history in open tabs +// <iframe mozbrowser>. + +"use strict"; +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'); + // FIXME: Bug 1270790 + iframe.setAttribute('remote', 'true'); + + addOneShotIframeEventListener('mozbrowserloadend', function() { + SimpleTest.executeSoon(test2); + }); + + iframe.src = browserElementTestHelpers.emptyPage1; + document.body.appendChild(iframe); +} + +function purgeHistory(nextTest) { + var seenCanGoBackResult = false; + var seenCanGoForwardResult = false; + + iframe.purgeHistory().onsuccess = function(e) { + ok(true, "The history has been purged"); + + iframe.getCanGoBack().onsuccess = function(e) { + is(e.target.result, false, "Iframe cannot go back"); + seenCanGoBackResult = true; + maybeRunNextTest(); + }; + + iframe.getCanGoForward().onsuccess = function(e) { + is(e.target.result, false, "Iframe cannot go forward"); + seenCanGoForwardResult = true; + maybeRunNextTest(); + }; + }; + + function maybeRunNextTest() { + if (seenCanGoBackResult && seenCanGoForwardResult) { + nextTest(); + } + } +} + +function test2() { + purgeHistory(test3); +} + +function test3() { + addOneShotIframeEventListener('mozbrowserloadend', function() { + purgeHistory(test4); + }); + + SimpleTest.executeSoon(function() { + iframe.src = browserElementTestHelpers.emptyPage2; + }); +} + +function test4() { + addOneShotIframeEventListener('mozbrowserlocationchange', function(e) { + is(e.detail.url, browserElementTestHelpers.emptyPage3); + purgeHistory(SimpleTest.finish); + }); + + SimpleTest.executeSoon(function() { + iframe.src = browserElementTestHelpers.emptyPage3; + }); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_Reload.js b/dom/browser-element/mochitest/browserElement_Reload.js new file mode 100644 index 000000000..9ef6d8e7e --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Reload.js @@ -0,0 +1,59 @@ +/* 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"; +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); diff --git a/dom/browser-element/mochitest/browserElement_ReloadPostRequest.js b/dom/browser-element/mochitest/browserElement_ReloadPostRequest.js new file mode 100644 index 000000000..614ed7c49 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ReloadPostRequest.js @@ -0,0 +1,116 @@ +/* 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"; +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 bundleService = SpecialPowers.Cc['@mozilla.org/intl/stringbundle;1']. + getService(SpecialPowers.Ci.nsIStringBundleService); + let appBundle = bundleService.createBundle("chrome://global/locale/appstrings.properties"); + let brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties"); + try { + let brandName = brandBundle.GetStringFromName("brandShortName"); + result.message = appBundle.formatStringFromName("confirmRepostPrompt", + [brandName], 1); + } 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); diff --git a/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js b/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js new file mode 100644 index 000000000..583d58734 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js @@ -0,0 +1,30 @@ +/* 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"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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); diff --git a/dom/browser-element/mochitest/browserElement_ScrollEvent.js b/dom/browser-element/mochitest/browserElement_ScrollEvent.js new file mode 100644 index 000000000..5c4b4dcf9 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ScrollEvent.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that scroll event bubbles up. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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."); + ok(e.detail.top === 4000, "top position is correct."); + ok(e.detail.left === 4000, "left position is correct."); + SimpleTest.finish(); + }); + + iframe.src = "data:text/html,<html><body style='min-height: 5000px; min-width: 5000px;'></body><script>window.scrollTo(4000, 4000);</script></html>"; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_SecurityChange.js b/dom/browser-element/mochitest/browserElement_SecurityChange.js new file mode 100644 index 000000000..0ef64b3fa --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_SecurityChange.js @@ -0,0 +1,82 @@ +/* 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"; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm'); +const { UrlClassifierTestUtils } = SpecialPowers.Cu.import('resource://testing-common/UrlClassifierTestUtils.jsm', {}); + +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.trackingContent, false); + is(lastSecurityState.mixedContent, false); + iframe.src = "http://example.com/" + filepath; + break; + case 2: + is(lastSecurityState.state, 'insecure'); + is(lastSecurityState.extendedValidation, false); + is(lastSecurityState.trackingContent, 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.trackingContent, false); + is(lastSecurityState.mixedContent, true); + iframe.src = "http://example.com/" + filepath + '?tracking'; + break; + case 4: + is(lastSecurityState.state, 'insecure'); + is(lastSecurityState.extendedValidation, false); + // TODO: I'm having trouble getting the tracking protection + // test changes to be enabled in the child process, so this + // isn't currently blocked in tests, but it works when + // manually testing. + // is(lastSecurityState.trackingContent, true); + is(lastSecurityState.mixedContent, false); + SimpleTest.finish(); + } + }); + + iframe.src = "https://example.com/" + filepath; + document.body.appendChild(iframe); +} + +addEventListener('testready', function() { + SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers); + SpecialPowers.pushPrefEnv({"set" : [ + ["privacy.trackingprotection.enabled", true], + ["privacy.trackingprotection.pbmode.enabled", false], + ["browser.safebrowsing.phishing.enabled", false], + ["browser.safebrowsing.malware.enabled", false], + ]}, () => { + SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers); + UrlClassifierTestUtils.addTestTrackers().then(() => { + runTest(); + }); + }); +}); + diff --git a/dom/browser-element/mochitest/browserElement_SendEvent.js b/dom/browser-element/mochitest/browserElement_SendEvent.js new file mode 100644 index 000000000..a65d6f24f --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_SendEvent.js @@ -0,0 +1,85 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that sendMouseEvent dispatch events. +"use strict"; + +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; + // First we force a reflow so that getChildProcessOffset actually returns + // meaningful data. + iframe.getBoundingClientRect(); + // We need to make sure the event coordinates are actually inside the iframe, + // relative to the chome window. + var tabParent = SpecialPowers.wrap(iframe) + .QueryInterface(SpecialPowers.Ci.nsIFrameLoaderOwner) + .frameLoader.tabParent; + if (tabParent) { + let offsetX = {}; + let offsetY = {}; + tabParent.getChildProcessOffset(offsetX, offsetY); + x -= offsetX.value; + y -= offsetY.value; + } + + iframe.addEventListener("mozbrowserloadend", function onloadend(e) { + 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."); + if (SpecialPowers.getIntPref("dom.w3c_touch_events.enabled") != 0) { + iframe.sendTouchEvent("touchstart", [1], [x], [y], [2], [2], + [20], [0.5], 1, 0); + } else { + iframe.removeEventListener('mozbrowserlocationchange', onlocchange); + SimpleTest.finish(); + } + break; + case "#touchstart": + ok(true, "Receive a touchstart event."); + iframe.sendTouchEvent("touchmove", [1], [x], [y], [2], [2], + [20], [0.5], 1, 0); + case "#touchmove": + ok(true, "Receive a touchmove event."); + iframe.sendTouchEvent("touchend", [1], [x], [y], [2], [2], + [20], [0.5], 1, 0); + break; + case "#touchend": + ok(true, "Receive a touchend event."); + iframe.sendTouchEvent("touchcancel", [1], [x], [y], [2], [2], + [20], [0.5], 1, 0); + iframe.removeEventListener('mozbrowserlocationchange', onlocchange); + SimpleTest.finish(); + break; + } + }); + + iframe.src = "file_browserElement_SendEvent.html"; + +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js b/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js new file mode 100644 index 000000000..2b94f5cda --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js @@ -0,0 +1,323 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 905573 - Add setInputMethodActive to browser elements to allow gaia +// system set the active IME app. +'use strict'; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +// We'll need to get the appId from the current document, +// it's either SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID when +// we are not running inside an app (e.g. Firefox Desktop), +// or the appId of Mochitest app when we are running inside that app +// (e.g. Emulator). +var currentAppId = SpecialPowers.wrap(document).nodePrincipal.appId; +var inApp = + currentAppId !== SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID; +// We will also need the manifest URL and set it on iframes. +var currentAppManifestURL; + +if (inApp) { + let appsService = SpecialPowers.Cc["@mozilla.org/AppsService;1"] + .getService(SpecialPowers.Ci.nsIAppsService); + + currentAppManifestURL = appsService.getManifestURLByLocalId(currentAppId); +}; + +info('appId=' + currentAppId); +info('manifestURL=' + currentAppManifestURL); + +function setup() { + let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'] + .getService(SpecialPowers.Ci.nsIXULAppInfo); + if (appInfo.name != 'B2G') { + SpecialPowers.Cu.import("resource://gre/modules/Keyboard.jsm", window); + } + + SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", true); + SpecialPowers.addPermission('input-manage', true, document); +} + +function tearDown() { + SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", false); + SpecialPowers.removePermission('input-manage', document); + SimpleTest.finish(); +} + +function runTest() { + createFrames(); +} + +var gInputMethodFrames = []; +var gInputFrame; + +function createFrames() { + // Create two input method iframes. + let loadendCount = 0; + let countLoadend = function() { + loadendCount++; + if (loadendCount === 3) { + setPermissions(); + } + }; + + // Create an input field to receive string from input method iframes. + gInputFrame = document.createElement('iframe'); + gInputFrame.setAttribute('mozbrowser', 'true'); + gInputFrame.src = 'file_browserElement_SetInputMethodActive.html'; + document.body.appendChild(gInputFrame); + gInputFrame.addEventListener('mozbrowserloadend', countLoadend); + + for (let i = 0; i < 2; i++) { + let frame = gInputMethodFrames[i] = document.createElement('iframe'); + frame.setAttribute('mozbrowser', 'true'); + if (currentAppManifestURL) { + frame.setAttribute('mozapp', currentAppManifestURL); + } + frame.addEventListener('mozbrowserloadend', countLoadend); + frame.src = 'file_empty.html#' + i; + document.body.appendChild(frame); + } + } + +function setPermissions() { + let permissions = [{ + type: 'input', + allow: true, + context: { + url: SimpleTest.getTestFileURL('/file_empty.html'), + originAttributes: { + appId: currentAppId, + inIsolatedMozBrowser: true + } + } + }]; + + if (inApp) { + // The current document would also need to be given access for IPC to + // recognize our permission (why)? + permissions.push({ + type: 'input', allow: true, context: document }); + } + + SpecialPowers.pushPermissions(permissions, + SimpleTest.waitForFocus.bind(SimpleTest, startTest)); +} + + function startTest() { + // The frame script running in the frame where the input is hosted. + let appFrameScript = function appFrameScript() { + let input = content.document.body.firstElementChild; + input.oninput = function() { + sendAsyncMessage('test:InputMethod:oninput', { + from: 'input', + value: this.value + }); + }; + + input.onblur = function() { + // "Expected" lost of focus since the test is finished. + if (input.value === 'hello#0#1') { + return; + } + + sendAsyncMessage('test:InputMethod:oninput', { + from: 'input', + error: true, + value: 'Unexpected lost of focus on the input frame!' + }); + }; + + input.focus(); + }; + + // Inject frame script to receive input. + let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame); + mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false); + mm.addMessageListener("test:InputMethod:oninput", next); + + gInputMethodFrames.forEach((frame) => { + ok(frame.setInputMethodActive, 'Can access setInputMethodActive.'); + + // The frame script running in the input method frames. + let appFrameScript = function appFrameScript() { + let im = content.navigator.mozInputMethod; + im.oninputcontextchange = function() { + let ctx = im.inputcontext; + // Report back to parent frame on status of ctx gotten. + // (A setTimeout() here to ensure this always happens after + // DOMRequest succeed.) + content.setTimeout(() => { + sendAsyncMessage('test:InputMethod:imFrameMessage', { + from: 'im', + value: content.location.hash + !!ctx + }); + }); + + // If there is a context, send out the hash. + if (ctx) { + ctx.replaceSurroundingText(content.location.hash); + } + }; + }; + + // Inject frame script to receive message. + let mm = SpecialPowers.getBrowserFrameMessageManager(frame); + mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false); + mm.addMessageListener("test:InputMethod:imFrameMessage", next); + }); + + // Set focus to the input field and wait for input methods' inputting. + SpecialPowers.DOMWindowUtils.focus(gInputFrame); + + let req0 = gInputMethodFrames[0].setInputMethodActive(true); + req0.onsuccess = function() { + ok(true, 'setInputMethodActive succeeded (0).'); + }; + + req0.onerror = function() { + ok(false, 'setInputMethodActive failed (0): ' + this.error.name); + }; +} + +var gCount = 0; + +var gFrameMsgCounts = { + 'input': 0, + 'im0': 0, + 'im1': 0 +}; + +function next(msg) { + let wrappedMsg = SpecialPowers.wrap(msg); + let from = wrappedMsg.data.from; + let value = wrappedMsg.data.value; + + if (wrappedMsg.data.error) { + ok(false, wrappedMsg.data.value); + + return; + } + + let fromId = from; + if (from === 'im') { + fromId += value[1]; + } + gFrameMsgCounts[fromId]++; + + // The texts sent from the first and the second input method are '#0' and + // '#1' respectively. + switch (gCount) { + case 0: + switch (fromId) { + case 'im0': + if (gFrameMsgCounts.im0 === 1) { + is(value, '#0true', 'First frame should get the context first.'); + } else { + ok(false, 'Unexpected multiple messages from im0.') + } + + break; + + case 'im1': + is(false, 'Shouldn\'t be hearing anything from second frame.'); + + break; + + case 'input': + if (gFrameMsgCounts.input === 1) { + is(value, '#0hello', + 'Failed to get correct input from the first iframe.'); + } else { + ok(false, 'Unexpected multiple messages from input.') + } + + break; + } + + if (gFrameMsgCounts.input !== 1 || + gFrameMsgCounts.im0 !== 1 || + gFrameMsgCounts.im1 !== 0) { + return; + } + + gCount++; + + let req0 = gInputMethodFrames[0].setInputMethodActive(false); + req0.onsuccess = function() { + ok(true, 'setInputMethodActive succeeded (0).'); + }; + req0.onerror = function() { + ok(false, 'setInputMethodActive failed (0): ' + this.error.name); + }; + let req1 = gInputMethodFrames[1].setInputMethodActive(true); + req1.onsuccess = function() { + ok(true, 'setInputMethodActive succeeded (1).'); + }; + req1.onerror = function() { + ok(false, 'setInputMethodActive failed (1): ' + this.error.name); + }; + + break; + + case 1: + switch (fromId) { + case 'im0': + if (gFrameMsgCounts.im0 === 2) { + is(value, '#0false', 'First frame should have the context removed.'); + } else { + ok(false, 'Unexpected multiple messages from im0.') + } + break; + + case 'im1': + if (gFrameMsgCounts.im1 === 1) { + is(value, '#1true', 'Second frame should get the context.'); + } else { + ok(false, 'Unexpected multiple messages from im0.') + } + + break; + + case 'input': + if (gFrameMsgCounts.input === 2) { + is(value, '#0#1hello', + 'Failed to get correct input from the second iframe.'); + } else { + ok(false, 'Unexpected multiple messages from input.') + } + break; + } + + if (gFrameMsgCounts.input !== 2 || + gFrameMsgCounts.im0 !== 2 || + gFrameMsgCounts.im1 !== 1) { + return; + } + + gCount++; + + // Receive the second input from the second iframe. + // Deactive the second iframe. + let req3 = gInputMethodFrames[1].setInputMethodActive(false); + req3.onsuccess = function() { + ok(true, 'setInputMethodActive(false) succeeded (2).'); + }; + req3.onerror = function() { + ok(false, 'setInputMethodActive(false) failed (2): ' + this.error.name); + }; + break; + + case 2: + is(fromId, 'im1', 'Message sequence unexpected (3).'); + is(value, '#1false', 'Second frame should have the context removed.'); + + tearDown(); + break; + } +} + +setup(); +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_SetVisible.js b/dom/browser-element/mochitest/browserElement_SetVisible.js new file mode 100644 index 000000000..dac8d7e42 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_SetVisible.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test the setVisible property for mozbrowser +"use strict"; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +browserElementTestHelpers.setEnabledPref(true); + +var iframeScript = function() { + content.document.addEventListener("visibilitychange", function() { + sendAsyncMessage('test:visibilitychange', { + hidden: content.document.hidden + }); + }, false); +} + +function runTest() { + var mm; + var numEvents = 0; + var iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + iframe1.src = 'data:text/html,1'; + + document.body.appendChild(iframe1); + + function recvVisibilityChanged(msg) { + msg = SpecialPowers.wrap(msg); + numEvents++; + if (numEvents === 1) { + ok(true, 'iframe recieved visibility changed'); + ok(msg.json.hidden === true, 'hidden attribute correctly set'); + iframe1.setVisible(false); + iframe1.setVisible(true); + } else if (numEvents === 2) { + ok(msg.json.hidden === false, 'hidden attribute correctly set'); + // Allow some time in case we generate too many events + setTimeout(function() { + mm.removeMessageListener('test:visibilitychange', recvVisibilityChanged); + SimpleTest.finish(); + }, 100); + } else { + ok(false, 'Too many visibilitychange events'); + } + } + + function iframeLoaded() { + testGetVisible(); + } + + function testGetVisible() { + iframe1.setVisible(false); + iframe1.getVisible().onsuccess = function(evt) { + ok(evt.target.result === false, 'getVisible() responds false after setVisible(false)'); + + iframe1.setVisible(true); + iframe1.getVisible().onsuccess = function(evt) { + ok(evt.target.result === true, 'getVisible() responds true after setVisible(true)'); + testVisibilityChanges(); + }; + }; + } + + function testVisibilityChanges() { + mm = SpecialPowers.getBrowserFrameMessageManager(iframe1); + mm.addMessageListener('test:visibilitychange', recvVisibilityChanged); + mm.loadFrameScript('data:,(' + iframeScript.toString() + ')();', false); + iframe1.setVisible(false); + } + + iframe1.addEventListener('mozbrowserloadend', iframeLoaded); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_SetVisibleFrames.js b/dom/browser-element/mochitest/browserElement_SetVisibleFrames.js new file mode 100644 index 000000000..721248ab9 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_SetVisibleFrames.js @@ -0,0 +1,89 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 762939 - Test that visibility propagates down properly through +// hierarchies of <iframe mozbrowser>. +// +// In this test, we modify the parent's visibility and check that the child's +// visibility is changed as appopriate. We test modifying the child's +// visibility in a separate testcase. + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var iframe; + +function runTest() { + iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + // Our test involves three <iframe mozbrowser>'s, parent, child1, and child2. + // child1 and child2 are contained inside parent. child1 is visibile, and + // child2 is not. + // + // For the purposes of this test, we want there to be a process barrier + // between child{1,2} and parent. Therefore parent must be a non-remote + // <iframe mozbrowser>, until bug 761935 is resolved and we can have nested + // content processes. + iframe.remote = false; + + iframe.addEventListener('mozbrowsershowmodalprompt', checkMessage); + expectMessage('parent:ready', test1); + + document.body.appendChild(iframe); + iframe.src = 'file_browserElement_SetVisibleFrames_Outer.html'; +} + +function test1() { + expectMessage('child1:hidden', getVisibleTest1); + iframe.setVisible(false); +} + +function getVisibleTest1() { + iframe.getVisible().onsuccess = function(evt) { + ok(evt.target.result === false, 'getVisible shows a hidden frame'); + test2(); + }; +} + +function test2() { + expectMessage('child1:visible', getVisibleTest2); + iframe.setVisible(true); +} + +function getVisibleTest2() { + iframe.getVisible().onsuccess = function(evt) { + ok(evt.target.result === true, 'getVisible shows a displayed frame'); + finish(); + }; +} + +function finish() { + // We need to remove this listener because when this test finishes and the + // iframe containing this document is navigated, we'll fire a + // visibilitychange(false) event on all child iframes. That's OK and + // expected, but if we don't remove our listener, then we'll end up causing + // the /next/ test to fail! + iframe.removeEventListener('mozbrowsershowmodalprompt', checkMessage); + SimpleTest.finish(); +} + +var expectedMsg = null; +var expectedMsgCallback = null; +function expectMessage(msg, next) { + expectedMsg = msg; + expectedMsgCallback = next; +} + +function checkMessage(e) { + var msg = e.detail.message; + is(msg, expectedMsg); + if (msg == expectedMsg) { + expectedMsg = null; + SimpleTest.executeSoon(function() { expectedMsgCallback() }); + } +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_SetVisibleFrames2.js b/dom/browser-element/mochitest/browserElement_SetVisibleFrames2.js new file mode 100644 index 000000000..cf841a470 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_SetVisibleFrames2.js @@ -0,0 +1,55 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 762939 - Test that setting a <iframe mozbrowser> to invisible / visible +// inside an invisible <iframe mozbrowser> doesn't trigger any events. + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + // We need remote = false here until bug 761935 is fixed; see + // SetVisibleFrames.js for an explanation. + iframe.remote = false; + + iframe.addEventListener('mozbrowserloadend', function loadEnd(e) { + iframe.removeEventListener('mozbrowserloadend', loadEnd); + iframe.setVisible(false); + iframe.src = 'file_browserElement_SetVisibleFrames2_Outer.html'; + }); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + if (e.detail.message == 'parent:finish') { + ok(true, "Got parent:finish"); + + // Give any extra events a chance to fire, then end the test. + SimpleTest.executeSoon(function() { + SimpleTest.executeSoon(function() { + SimpleTest.executeSoon(function() { + SimpleTest.executeSoon(function() { + SimpleTest.executeSoon(function() { + finish(); + }); + }); + }); + }); + }); + } + else { + ok(false, "Got unexpected message: " + e.detail.message); + } + }); + + document.body.appendChild(iframe); +} + +function finish() { + SimpleTest.finish(); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_Stop.js b/dom/browser-element/mochitest/browserElement_Stop.js new file mode 100644 index 000000000..67720c148 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Stop.js @@ -0,0 +1,52 @@ +/* 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"; +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); diff --git a/dom/browser-element/mochitest/browserElement_TargetBlank.js b/dom/browser-element/mochitest/browserElement_TargetBlank.js new file mode 100644 index 000000000..89c2f33c1 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_TargetBlank.js @@ -0,0 +1,26 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 764718 - Test that clicking a link with _target=blank works. + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowseropenwindow', function(e) { + is(e.detail.url, 'http://example.com/'); + e.preventDefault(); + SimpleTest.finish(); + }); + + iframe.src = "file_browserElement_TargetBlank.html"; + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_TargetTop.js b/dom/browser-element/mochitest/browserElement_TargetTop.js new file mode 100644 index 000000000..54bad9c42 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_TargetTop.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 771273 - Check that window.open(url, '_top') works properly with <iframe +// mozbrowser>. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowseropenwindow', function(e) { + ok(false, 'Not expecting an openwindow event.'); + }); + + iframe.addEventListener('mozbrowserlocationchange', function(e) { + if (/file_browserElement_TargetTop.html\?2$/.test(e.detail.url)) { + ok(true, 'Got the locationchange we were looking for.'); + SimpleTest.finish(); + } + }); + + document.body.appendChild(iframe); + iframe.src = 'file_browserElement_TargetTop.html'; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_ThemeColor.js b/dom/browser-element/mochitest/browserElement_ThemeColor.js new file mode 100644 index 000000000..01e9c5c36 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_ThemeColor.js @@ -0,0 +1,85 @@ +/* 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"; + +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); + diff --git a/dom/browser-element/mochitest/browserElement_Titlechange.js b/dom/browser-element/mochitest/browserElement_Titlechange.js new file mode 100644 index 000000000..78c939ad8 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Titlechange.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the onmozbrowsertitlechange event works. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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); diff --git a/dom/browser-element/mochitest/browserElement_TopBarrier.js b/dom/browser-element/mochitest/browserElement_TopBarrier.js new file mode 100644 index 000000000..3bd68854c --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_TopBarrier.js @@ -0,0 +1,81 @@ +/* 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"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +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); diff --git a/dom/browser-element/mochitest/browserElement_Viewmode.js b/dom/browser-element/mochitest/browserElement_Viewmode.js new file mode 100644 index 000000000..51627d9a8 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_Viewmode.js @@ -0,0 +1,71 @@ +/* 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"; + +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); + diff --git a/dom/browser-element/mochitest/browserElement_VisibilityChange.js b/dom/browser-element/mochitest/browserElement_VisibilityChange.js new file mode 100644 index 000000000..d7db5f45d --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_VisibilityChange.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the onmozbrowservisibilitychange event works. +'use strict'; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +var iframe1 = null; +function runTest() { + iframe1 = document.createElement('iframe'); + iframe1.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe1); + + iframe1.src = 'data:text/html,<html><head><title>Title</title></head><body></body></html>'; + checkVisibilityFalse(); +} + +function checkVisibilityFalse() { + iframe1.addEventListener('mozbrowservisibilitychange', function onvisibilitychange(e) { + iframe1.removeEventListener(e.type, onvisibilitychange); + + is(e.detail.visible, false, 'Visibility should be false'); + checkVisibilityTrue(); + }); + + iframe1.setVisible(false); +} + +function checkVisibilityTrue() { + iframe1.addEventListener('mozbrowservisibilitychange', function onvisibilitychange(e) { + iframe1.removeEventListener(e.type, onvisibilitychange); + + is(e.detail.visible, true, 'Visibility should be true'); + SimpleTest.finish(); + }); + + iframe1.setVisible(true); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_XFrameOptions.js b/dom/browser-element/mochitest/browserElement_XFrameOptions.js new file mode 100644 index 000000000..391c2cb95 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_XFrameOptions.js @@ -0,0 +1,26 @@ +/* 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"; + +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); diff --git a/dom/browser-element/mochitest/browserElement_XFrameOptionsAllowFrom.js b/dom/browser-element/mochitest/browserElement_XFrameOptionsAllowFrom.js new file mode 100644 index 000000000..3657d9732 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_XFrameOptionsAllowFrom.js @@ -0,0 +1,60 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 690168 - Support Allow-From notation for X-Frame-Options header. +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +var initialScreenshotArrayBuffer = null; + +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 count = 0; + + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.height = '1000px'; + + var step1, stepfinish; + // The innermost page we load will fire an alert when it successfully loads. + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + switch (e.detail.message) { + case 'step 1': + step1 = SpecialPowers.snapshotWindow(iframe.contentWindow); + break; + case 'step 2': + ok(false, 'cross origin page loaded'); + break; + case 'finish': + // The page has now attempted to load the X-Frame-Options page; take + // another screenshot. + stepfinish = SpecialPowers.snapshotWindow(iframe.contentWindow); + ok(step1.toDataURL() == stepfinish.toDataURL(), "Screenshots should be identical"); + SimpleTest.finish(); + } + }); + + document.body.appendChild(iframe); + + iframe.src = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.html'; +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/browserElement_XFrameOptionsDeny.js b/dom/browser-element/mochitest/browserElement_XFrameOptionsDeny.js new file mode 100644 index 000000000..bf307cc19 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_XFrameOptionsDeny.js @@ -0,0 +1,63 @@ +/* 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"; + +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', function(e) { + switch (e.detail.message) { + case 'step 1': + step1 = SpecialPowers.snapshotWindow(iframe.contentWindow); + break; + case 'step 2': + // The page has now attempted to load the X-Frame-Options page; take + // another screenshot. + stepfinish = 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); diff --git a/dom/browser-element/mochitest/browserElement_XFrameOptionsSameOrigin.js b/dom/browser-element/mochitest/browserElement_XFrameOptionsSameOrigin.js new file mode 100644 index 000000000..35e4ca8f0 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_XFrameOptionsSameOrigin.js @@ -0,0 +1,28 @@ +/* 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"; + +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); diff --git a/dom/browser-element/mochitest/browserElement_getWebManifest.js b/dom/browser-element/mochitest/browserElement_getWebManifest.js new file mode 100644 index 000000000..c2b8f96f3 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_getWebManifest.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +/*globals async, ok, is, SimpleTest, browserElementTestHelpers*/ + +// Bug 1169633 - getWebManifest tests +'use strict'; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); + +// request to load a manifest from a page that doesn't have a manifest. +// The expected result to be null. +var test1 = async(function* () { + var manifest = yield requestManifest('file_empty.html'); + is(manifest, null, 'it should be null.'); +}); + +// request to load a manifest from a page that has a manifest. +// The expected manifest to have a property name whose value is 'pass'. +var test2 = async(function* () { + var manifest = yield requestManifest('file_web_manifest.html'); + is(manifest && manifest.name, 'pass', 'it should return a manifest with name pass.'); +}); + +// Cause an exception by attempting to fetch a file URL, +// expect onerror to be called. +var test3 = async(function* () { + var gotError = false; + try { + yield requestManifest('file_illegal_web_manifest.html'); + } catch (err) { + gotError = true; + } + ok(gotError, 'onerror was called on the DOMRequest.'); +}); + +// Run the tests +addEventListener('testready', () => { + Promise + .all([test1(), test2(), test3()]) + .then(SimpleTest.finish); +}); + +function requestManifest(url) { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.src = url; + document.body.appendChild(iframe); + return new Promise((resolve, reject) => { + iframe.addEventListener('mozbrowserloadend', function loadend() { + iframe.removeEventListener('mozbrowserloadend', loadend); + SimpleTest.executeSoon(() => { + var req = iframe.getWebManifest(); + req.onsuccess = () => { + document.body.removeChild(iframe); + resolve(req.result); + }; + req.onerror = () => { + document.body.removeChild(iframe); + reject(new Error(req.error)); + }; + }); + }); + }); +} diff --git a/dom/browser-element/mochitest/chrome.ini b/dom/browser-element/mochitest/chrome.ini new file mode 100644 index 000000000..2b0561df8 --- /dev/null +++ b/dom/browser-element/mochitest/chrome.ini @@ -0,0 +1,92 @@ +[DEFAULT] +skip-if = e10s || toolkit == 'android' # Bug 1287720: takes too long on android + +support-files = + audio.ogg + async.js + browserElementTestHelpers.js + browserElement_ActiveStateChange.js + browserElement_AudioChannelSeeking.js + browserElement_AudioChannelMutedByDefault.js + browserElement_AudioPlayback.js + browserElement_AudioChannel.js + browserElement_AudioChannel_nested.js + browserElement_BackForward.js + browserElement_BadScreenshot.js + browserElement_DocumentFirstPaint.js + browserElement_DOMRequestError.js + browserElement_ExecuteScript.js + browserElement_Find.js + browserElement_GetContentDimensions.js + browserElement_GetScreenshot.js + browserElement_GetScreenshotDppx.js + browserElement_getWebManifest.js + browserElement_NextPaint.js + browserElement_NoAudioTrack.js + browserElement_PurgeHistory.js + browserElement_ReloadPostRequest.js + browserElement_SendEvent.js + browserElement_SetInputMethodActive.js + browserElement_SetVisible.js + browserElement_SetVisibleFrames.js + browserElement_SetVisibleFrames2.js + browserElement_Stop.js + browserElement_VisibilityChange.js + file_audio.html + file_browserElement_ActiveStateChange.html + file_browserElement_AudioChannelSeeking.html + file_browserElement_AudioChannel_nested.html + file_browserElement_AudioChannelMutedByDefault.html + file_browserElement_ExecuteScript.html + file_browserElement_NextPaint.html + file_browserElement_NoAudioTrack.html + file_browserElement_SendEvent.html + file_browserElement_SetInputMethodActive.html + file_browserElement_SetVisibleFrames2_Outer.html + file_browserElement_SetVisibleFrames_Inner.html + file_browserElement_SetVisibleFrames_Outer.html + file_bug709759.sjs + file_empty.html + file_post_request.html + file_web_manifest.html + file_web_manifest.json + file_illegal_web_manifest.html + iframe_file_audio.html + +[test_browserElement_inproc_ActiveStateChange.html] +tags = audiochannel +[test_browserElement_inproc_AudioChannelMutedByDefault.html] +tags = audiochannel +skip-if = toolkit == 'android' +[test_browserElement_inproc_AudioChannelSeeking.html] +tags = audiochannel +[test_browserElement_inproc_AudioPlayback.html] +[test_browserElement_inproc_AudioChannel.html] +tags = audiochannel +[test_browserElement_inproc_AudioChannel_nested.html] +tags = audiochannel +[test_browserElement_inproc_BackForward.html] +[test_browserElement_inproc_BadScreenshot.html] +[test_browserElement_inproc_DocumentFirstPaint.html] +[test_browserElement_inproc_DOMRequestError.html] +[test_browserElement_inproc_ExecuteScript.html] +[test_browserElement_inproc_Find.html] +[test_browserElement_inproc_GetContentDimensions.html] +[test_browserElement_inproc_GetScreenshot.html] +[test_browserElement_inproc_GetScreenshotDppx.html] +[test_browserElement_inproc_getWebManifest.html] +[test_browserElement_inproc_NextPaint.html] +[test_browserElement_inproc_NoAudioTrack.html] +tags = audiochannel +[test_browserElement_inproc_PurgeHistory.html] +[test_browserElement_inproc_ReloadPostRequest.html] +disabled = no modal prompt on POST reload for chrome window +[test_browserElement_inproc_SendEvent.html] +# The setInputMethodActive() tests will timed out on Android +[test_browserElement_inproc_SetInputMethodActive.html] +skip-if = true +[test_browserElement_inproc_SetVisible.html] +[test_browserElement_inproc_SetVisibleFrames.html] +[test_browserElement_inproc_SetVisibleFrames2.html] +[test_browserElement_inproc_Stop.html] +[test_browserElement_inproc_VisibilityChange.html] diff --git a/dom/browser-element/mochitest/createNewTest.py b/dom/browser-element/mochitest/createNewTest.py new file mode 100644 index 000000000..309ff9534 --- /dev/null +++ b/dom/browser-element/mochitest/createNewTest.py @@ -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;version=1.7" 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) diff --git a/dom/browser-element/mochitest/file_audio.html b/dom/browser-element/mochitest/file_audio.html new file mode 100644 index 000000000..0e4a8d7c6 --- /dev/null +++ b/dom/browser-element/mochitest/file_audio.html @@ -0,0 +1,15 @@ +<html> +<body> +<audio src="chrome://mochitests/content/chrome/dom/browser-element/mochitest/audio.ogg" id="audio" /> +<script> +var audio = document.getElementById('audio'); +audio.play(); +audio.onended = function() { + setTimeout(function() { + audio.play(); + }, 0); +} +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_ActiveStateChange.html b/dom/browser-element/mochitest/file_browserElement_ActiveStateChange.html new file mode 100644 index 000000000..5228d67bf --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_ActiveStateChange.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<body> +<script type="application/javascript;version=1.7"> +var audio = new Audio(); +audio.src = "audio.ogg"; +audio.loop = true; + +function runCommands() +{ + switch(location.hash) { + case '#play': + audio.play(); + break; + case '#pause': + audio.pause(); + break; + default : + alert("Undefined command!"); + } +} +window.addEventListener('hashchange', runCommands); +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/file_browserElement_AlertInFrame.html b/dom/browser-element/mochitest/file_browserElement_AlertInFrame.html new file mode 100644 index 000000000..8bdac1d25 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_AlertInFrame.html @@ -0,0 +1,6 @@ +<html> +<body> +I'm file_browserElement_AlertInFrame.html. +<iframe src='file_browserElement_AlertInFrame_Inner.html'></iframe> +<body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_AlertInFrame_Inner.html b/dom/browser-element/mochitest/file_browserElement_AlertInFrame_Inner.html new file mode 100644 index 000000000..958413f2d --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_AlertInFrame_Inner.html @@ -0,0 +1,12 @@ +<html> +<body> +I'm file_browserElement_AlertInFrame_Inner.html. + +<script> +addEventListener('load', function() { + alert("Hello"); +}); +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_AudioChannelMutedByDefault.html b/dom/browser-element/mochitest/file_browserElement_AudioChannelMutedByDefault.html new file mode 100644 index 000000000..ea4f3bde1 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_AudioChannelMutedByDefault.html @@ -0,0 +1,65 @@ +<html> +<body> +<script> +var audio = new Audio("audio.ogg"); +var context = new AudioContext(); +var node = context.createMediaElementSource(audio); +var sp = context.createScriptProcessor(2048, 1); +node.connect(sp); +var expectedSamplesCount; +var nonzeroSamplesCount = 0; +var isStarted = false; + +function ok(aVal, aMsg) { + alert((!!aVal ? "OK" : "KO") + ", " + aMsg); +} + +function finish() { + audio.onended = null; + audio.pause(); + alert("DONE"); +} + +function processSamples(e) { + var buf = e.inputBuffer.getChannelData(0); + for (var i = 0; i < buf.length; ++i) { + if (buf[i] != 0) { + if (!isStarted) { + isStarted = true; + ok(true, "Start process audio sample."); + } + nonzeroSamplesCount++; + } + } + + if (nonzeroSamplesCount >= expectedSamplesCount) { + finish(); + } +} + +audio.oncanplaythrough = function() { + var testDuration = audio.duration > 1.0 ? 1.0 : audio.duration * 0.5; + expectedSamplesCount = Math.floor(testDuration * context.sampleRate); + sp.onaudioprocess = processSamples; +}; + +function runCommands() +{ + switch(location.hash) { + case '#play': + ok(true, "Audio starts playing.") + audio.play(); + audio.onended = () => { + audio.onended = null; + ok(false, "Audio shouldn't go ended in this test!") + }; + break; + default : + ok(false, "Undefined command!"); + } +} + +window.addEventListener('hashchange', runCommands); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_AudioChannelSeeking.html b/dom/browser-element/mochitest/file_browserElement_AudioChannelSeeking.html new file mode 100644 index 000000000..293f6cadc --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_AudioChannelSeeking.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> +<body> +<script type="application/javascript;version=1.7"> +var audio = new Audio(); +audio.src = "audio.ogg"; +audio.loop = true; + +function assert(aVal, aMessage) { + return (!aVal) ? ok(false, aMessage) : 0; +} + +function ok(aVal, aMsg) { + alert((!!aVal ? "OK" : "KO") + ", " + aMsg); +} + +function info(aMsg) { + alert("INFO" + ", " + aMsg); +} + +function randomSeeking() { + var seekingPosition = Math.random() * audio.duration; + assert(seekingPosition < audio.duration, "Seeking position out of range!") + audio.currentTime = seekingPosition; + audio.onseeked = () => { + audio.onseeked = null; + location.hash = '#idle'; + ok(true, "Seeking complete, position = " + seekingPosition); + }; +} + +function runCommands() +{ + switch(location.hash) { + case '#play': + audio.play(); + audio.onplay = () => { + audio.onplay = null; + info("Start playing, duration = " + audio.duration); + }; + break; + case '#seeking': + randomSeeking(); + break; + case '#pause': + audio.pause(); + audio.onpause = () => { + audio.onpause = null; + ok(true, "Stop playing."); + }; + break; + case '#idle': + break; + default : + ok(false, "Undefined command!"); + } +} + +window.addEventListener('hashchange', runCommands); +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/file_browserElement_AudioChannel_nested.html b/dom/browser-element/mochitest/file_browserElement_AudioChannel_nested.html new file mode 100644 index 000000000..c37a642e2 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_AudioChannel_nested.html @@ -0,0 +1,63 @@ +<html> +<head> +<script type="text/javascript"> + + function ok(a, msg) { + alert((!!a ? "OK" : "KO") + " " + msg); + } + + function is(a, b, msg) { + ok(a === b, msg); + } + + function finish(a, b, msg) { + alert("DONE"); + } + + addEventListener('load', function(e) { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + // set 'remote' to true here will make the the iframe remote in _inproc_ + // test and in-process in _oop_ test. + iframe.setAttribute('remote', 'true'); + iframe.setAttribute('mozapp', 'http://example.org/manifest.webapp'); + + iframe.addEventListener('mozbrowserloadend', function(e) { + ok("mute" in iframe, "iframe.mute exists"); + ok("unmute" in iframe, "iframe.unmute exists"); + ok("getMuted" in iframe, "iframe.getMuted exists"); + ok("getVolume" in iframe, "iframe.getVolume exists"); + ok("setVolume" in iframe, "iframe.setVolume exists"); + + ok("allowedAudioChannels" in iframe, "allowedAudioChannels exist"); + var channels = iframe.allowedAudioChannels; + is(channels.length, 9, "9 audio channel by default"); + + var ac = channels[0]; + + ok(ac instanceof BrowserElementAudioChannel, "Correct class"); + ok("getVolume" in ac, "ac.getVolume exists"); + ok("setVolume" in ac, "ac.setVolume exists"); + ok("getMuted" in ac, "ac.getMuted exists"); + ok("setMuted" in ac, "ac.setMuted exists"); + ok("isActive" in ac, "ac.isActive exists"); + + ac.onactivestatechanged = function() { + ok(true, "activestatechanged event received."); + + ac.getVolume().onsuccess = function(e) { + ok(e.target.result, 1, "Default volume is 1"); + }; + + finish(); + } + }); + + document.body.appendChild(iframe); + iframe.src = 'chrome://mochitests/content/chrome/dom/browser-element/mochitest/file_audio.html'; + }); +</script> +</head> +<body> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_BrowserWindowNamespace.html b/dom/browser-element/mochitest/file_browserElement_BrowserWindowNamespace.html new file mode 100644 index 000000000..7903a63b8 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_BrowserWindowNamespace.html @@ -0,0 +1,9 @@ +<html> +<body> +<script> +addEventListener('load', function() { + window.open("http://example.com/" + location.hash, "foo"); +}); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_CloseFromOpener.html b/dom/browser-element/mochitest/file_browserElement_CloseFromOpener.html new file mode 100644 index 000000000..4a08c2792 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_CloseFromOpener.html @@ -0,0 +1,8 @@ +<html> +<body> +<script> +var win = window.open('file_empty.html'); +win.close(); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html b/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html new file mode 100644 index 000000000..62f39d8ff --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html @@ -0,0 +1,25 @@ +<html> +<body> +file_browserElement_CookiesNotThirdParty.html + +<script type='text/javascript;version=1.7'> +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> diff --git a/dom/browser-element/mochitest/file_browserElement_ExecuteScript.html b/dom/browser-element/mochitest/file_browserElement_ExecuteScript.html new file mode 100644 index 000000000..d2c364aeb --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_ExecuteScript.html @@ -0,0 +1,8 @@ +<html> +<head> + <script> +window.btoa = () => "fake btoa"; + </script> +</head> +<body>foo</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_ForwardName.html b/dom/browser-element/mochitest/file_browserElement_ForwardName.html new file mode 100644 index 000000000..60b41bbc6 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_ForwardName.html @@ -0,0 +1,15 @@ +<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> diff --git a/dom/browser-element/mochitest/file_browserElement_FrameWrongURI.html b/dom/browser-element/mochitest/file_browserElement_FrameWrongURI.html new file mode 100644 index 000000000..1a6cfde0a --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_FrameWrongURI.html @@ -0,0 +1,5 @@ +<script> + function testSucceeded() { alert("success"); } + function callback() { return "<script>opener.testSucceeded()</" + "script>"; } + var w = window.open("javascript:opener.callback();"); +</script> diff --git a/dom/browser-element/mochitest/file_browserElement_LoadEvents.html b/dom/browser-element/mochitest/file_browserElement_LoadEvents.html new file mode 100644 index 000000000..7e0705e9d --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_LoadEvents.html @@ -0,0 +1,14 @@ +<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> +document.getElementById('url').innerHTML = window.location; +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_Metachange.sjs b/dom/browser-element/mochitest/file_browserElement_Metachange.sjs new file mode 100644 index 000000000..c63a047f7 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_Metachange.sjs @@ -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>'); +} diff --git a/dom/browser-element/mochitest/file_browserElement_NextPaint.html b/dom/browser-element/mochitest/file_browserElement_NextPaint.html new file mode 100644 index 000000000..d460fc5b9 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_NextPaint.html @@ -0,0 +1,9 @@ +<html> +<body> +<script> +addEventListener("hashchange", function () { + document.body.style.backgroundColor = "red"; +}); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_NoAudioTrack.html b/dom/browser-element/mochitest/file_browserElement_NoAudioTrack.html new file mode 100644 index 000000000..14304e469 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_NoAudioTrack.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<body> +<script type="application/javascript;version=1.7"> +var audio = new Audio(); +audio.src = "noaudio.webm"; +audio.preload = "none"; +audio.loop = true; + +function ok(aVal, aMsg) { + alert((!!aVal ? "OK" : "KO") + ", " + aMsg); +} + +function runCommands() +{ + switch(location.hash) { + case '#play': + audio.play(); + ok(true, "Start playing a video without audio track!"); + break; + case '#idle': + ok(!audio.paused, "Video is still playing!"); + break; + default : + ok(false, "Undefined command!"); + } +} + +window.addEventListener('hashchange', runCommands); +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/file_browserElement_Open1.html b/dom/browser-element/mochitest/file_browserElement_Open1.html new file mode 100644 index 000000000..c74415e2e --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_Open1.html @@ -0,0 +1,34 @@ +<html> +<body> +<script> + +// Because this file is inside <iframe mozbrowser>, the alert() calls below +// don't trigger actual dialogs. Instead, the document which contans the +// iframe receives mozbrowsershowmodalprompt events, which the document uses +// to determine test success/failure. + +function is(x, y, reason) { + if (x === y) { + alert("success: " + x + " === " + y + ", " + reason); + } + else { + alert("failure: " + x + " !== " + y + ", " + reason); + } +} + +function ok(bool, reason) { + alert((bool ? "success: " : "failure: ") + reason); +} + +// Send "dialog=1" as a test for bug 783644. It shouldn't have any effect. +var w = window.open("file_browserElement_Open2.html", "name", "dialog=1"); +w.addEventListener("load", function() { + ok(true, "got load"); + is(w.opener, window, 'opener property'); + is(w.location.href, location.href.replace('Open1', 'Open2'), 'correct location'); + is(w.document.getElementById('testElem').innerHTML, 'test', 'elem innerHTML'); + alert("finish"); +}); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_Open2.html b/dom/browser-element/mochitest/file_browserElement_Open2.html new file mode 100644 index 000000000..af9d2b6cd --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_Open2.html @@ -0,0 +1,5 @@ +<html> +<body> +<div id='testElem'>test</div> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_OpenMixedProcess.html b/dom/browser-element/mochitest/file_browserElement_OpenMixedProcess.html new file mode 100644 index 000000000..873a99f1a --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_OpenMixedProcess.html @@ -0,0 +1,22 @@ +<html> +<body> + +<!-- The test relies on the fact that this file is completely empty. --> + +<script> + +function ok(b, msg) +{ + alert((b ? 'pass:' : 'fail:') + msg); +} + +var w = window.open("file_empty.html"); +w.addEventListener('load', function() { + ok(true, 'Got load.'); + ok(w.document.getElementById('url'), 'Found element with id "url"'); + alert('finish'); +}); +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_OpenNamed.html b/dom/browser-element/mochitest/file_browserElement_OpenNamed.html new file mode 100644 index 000000000..7d2a7661c --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_OpenNamed.html @@ -0,0 +1,7 @@ +<html> +<body> +<script> +window.open('file_browserElement_OpenNamed2.html', 'OpenNamed'); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_OpenNamed2.html b/dom/browser-element/mochitest/file_browserElement_OpenNamed2.html new file mode 100644 index 000000000..6bf37bb53 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_OpenNamed2.html @@ -0,0 +1,7 @@ +<html> +<body> +<script> +alert('success: loaded'); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_OpenWindowDifferentOrigin.html b/dom/browser-element/mochitest/file_browserElement_OpenWindowDifferentOrigin.html new file mode 100644 index 000000000..dc08f341c --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_OpenWindowDifferentOrigin.html @@ -0,0 +1,18 @@ +<html> +<body> + +<div id='name'></div> + +<script> +if (location.search == "?1") { + open("http://example.com/tests/dom/browser-element/mochitest/file_browserElement_OpenWindowDifferentOrigin.html?2"); +} +else if (location.search == "?2") { + alert("finish"); +} + +document.getElementById('name').innerHTML = location.search; +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_OpenWindowEmpty.html b/dom/browser-element/mochitest/file_browserElement_OpenWindowEmpty.html new file mode 100644 index 000000000..fefd6f6ca --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_OpenWindowEmpty.html @@ -0,0 +1,7 @@ +<html> +<body> +<script> +window.open(); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_OpenWindowInFrame.html b/dom/browser-element/mochitest/file_browserElement_OpenWindowInFrame.html new file mode 100644 index 000000000..c1c1cecd3 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_OpenWindowInFrame.html @@ -0,0 +1,6 @@ +<html> +<body> +I'm file_browserElement_OpenInFrame.html. +<iframe src='file_browserElement_Open1.html'></iframe> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_OpenWindowRejected.html b/dom/browser-element/mochitest/file_browserElement_OpenWindowRejected.html new file mode 100644 index 000000000..eb6786979 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_OpenWindowRejected.html @@ -0,0 +1,16 @@ +<html> +<body> + +<script> +var w = window.open('does_not_exist.html'); +if (!w) { + alert("success:w is null"); +} +else { + alert("failure:w is not null -- " + w); +} +alert("finish"); +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_PrivateBrowsing.html b/dom/browser-element/mochitest/file_browserElement_PrivateBrowsing.html new file mode 100644 index 000000000..40ff9d8af --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_PrivateBrowsing.html @@ -0,0 +1,15 @@ +<html> +<body> +<script> + +if (location.href.indexOf("clear=true") != -1) { + localStorage.removeItem("foo"); + alert("CLEAR"); +} else { + var initialValue = localStorage.getItem("foo") || "EMPTY"; + localStorage.setItem("foo", "bar"); + alert(initialValue); +} +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_SecurityChange.html b/dom/browser-element/mochitest/file_browserElement_SecurityChange.html new file mode 100644 index 000000000..09c006e7c --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_SecurityChange.html @@ -0,0 +1,21 @@ +<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); +} else if (location.search === '?tracking') { + var img = document.createElement('img'); + img.src = 'http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg'; + document.body.appendChild(img); +} +</script> +</head> + +<body> +file_browserElement_SecurityChange.html. +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_SendEvent.html b/dom/browser-element/mochitest/file_browserElement_SendEvent.html new file mode 100644 index 000000000..3c510180d --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_SendEvent.html @@ -0,0 +1,15 @@ +<html><body> +<button>send[Mouse|Touch]Event</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); +window.addEventListener('touchstart', changeHash); +window.addEventListener('touchmove', changeHash); +window.addEventListener('touchend', changeHash); +window.addEventListener('touchcancel', changeHash); +</script></html> diff --git a/dom/browser-element/mochitest/file_browserElement_SetInputMethodActive.html b/dom/browser-element/mochitest/file_browserElement_SetInputMethodActive.html new file mode 100644 index 000000000..5eb17e5f1 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_SetInputMethodActive.html @@ -0,0 +1,2 @@ +<input autofocus value="hello" /> +<p>This is targetted mozbrowser frame.</p> diff --git a/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames2_Outer.html b/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames2_Outer.html new file mode 100644 index 000000000..c4fa25d26 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames2_Outer.html @@ -0,0 +1,25 @@ +<html> +<body> +<script> + +var iframe = document.createElement('iframe'); +iframe.setAttribute("mozbrowser", "true"); + +iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + if (e.detail.message == 'child:ready') { + setTimeout(function() { + iframe.setVisible(false); + iframe.setVisible(true); + setTimeout(function() { + alert('parent:finish'); + }, 0); + }, 0); + } +}); + +document.body.appendChild(iframe); +iframe.src = 'file_browserElement_SetVisibleFrames_Inner.html?child'; + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames_Inner.html b/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames_Inner.html new file mode 100644 index 000000000..8f9b871d6 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames_Inner.html @@ -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> diff --git a/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames_Outer.html b/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames_Outer.html new file mode 100644 index 000000000..6abcc6b0c --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_SetVisibleFrames_Outer.html @@ -0,0 +1,45 @@ +<html> +<body> + +<script> + +var numPrompts = 0; +function handlePrompt(e) { + numPrompts++; + + // The first two prompts should be "child1:ready" and "child2:ready". Once + // we get both of these, forward the child's prompt up to our parent. + if (numPrompts == 2) { + // This has to happen here, because setVisibile doesn't exist on the iframe + // until BrowserElementChild.js is loaded in it. (That's pretty broken...) + iframe2.setVisible(false); + } + else if (numPrompts == 3) { + if (e.detail.message != 'child2:hidden') { + alert("parent:fail Didn't get expected 'child2:hidden'."); + } + + alert('parent:ready'); + } + else if (numPrompts == 4 || numPrompts == 5) { + alert(e.detail.message); + } +} + +var iframe1 = document.createElement('iframe'); +iframe1.setAttribute("mozbrowser", "true"); +iframe1.addEventListener('mozbrowsershowmodalprompt', handlePrompt); + +var iframe2 = document.createElement('iframe'); +iframe2.setAttribute("mozbrowser", "true"); +iframe2.addEventListener('mozbrowsershowmodalprompt', handlePrompt); + +iframe1.src = 'file_browserElement_SetVisibleFrames_Inner.html?child1'; +iframe2.src = 'file_browserElement_SetVisibleFrames_Inner.html?child2'; +document.body.appendChild(iframe1); +document.body.appendChild(iframe2); + +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_TargetBlank.html b/dom/browser-element/mochitest/file_browserElement_TargetBlank.html new file mode 100644 index 000000000..860573a3e --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_TargetBlank.html @@ -0,0 +1,18 @@ +<html> +<body> +<a id='link' target='_blank' href="http://example.com">Click me</a> + +<script> +function clickLink() { + // See testcase in bug 666604. + var e = document.createEvent("MouseEvent"); + e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, + false, false, false, false, 0, null); + document.getElementById('link').dispatchEvent(e); +} + +addEventListener('load', function() { setTimeout(clickLink, 0) }); +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_TargetTop.html b/dom/browser-element/mochitest/file_browserElement_TargetTop.html new file mode 100644 index 000000000..aad06361d --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_TargetTop.html @@ -0,0 +1,12 @@ +<html> +<body> +<div id='url'></div> + +<script> +if (location.search == '') { + window.open('file_browserElement_TargetTop.html?2', '_top'); +} +document.getElementById('url').innerHTML = document.location.href; +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_ThemeColor.html b/dom/browser-element/mochitest/file_browserElement_ThemeColor.html new file mode 100644 index 000000000..f8fb9f116 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_ThemeColor.html @@ -0,0 +1,8 @@ +<html> + <head> + <meta name="theme-color" content="pink"> + </head> + + <body> + </body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_Viewmode.html b/dom/browser-element/mochitest/file_browserElement_Viewmode.html new file mode 100644 index 000000000..422279e0a --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_Viewmode.html @@ -0,0 +1,8 @@ +<html> + <head> + <meta name="viewmode" content="projection=stereo"> + </head> + + <body> + </body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_XFrameOptions.sjs b/dom/browser-element/mochitest/file_browserElement_XFrameOptions.sjs new file mode 100644 index 000000000..7e2375680 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_XFrameOptions.sjs @@ -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>"); +} diff --git a/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.html b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.html new file mode 100644 index 000000000..12a6fd31e --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.html @@ -0,0 +1,43 @@ +<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 iframe1Load() { + iframe1.removeEventListener('load', iframe1Load); + // This causes our embedder to take a screenshot (and blocks until the + // screenshot is completed). + var iframe2Loaded = false; + iframe2.addEventListener('load', function iframe2Load() { + iframe2.removeEventListener('load', iframe2Load); + iframe2Loaded = true; + alert('finish'); + }); + + document.body.appendChild(iframe2); + iframe2.src = frame_src; +}); + + +iframe1.src = frame_src + '?iframe1'; +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.sjs b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.sjs new file mode 100644 index 000000000..4a5dbaace --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.sjs @@ -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>"); +} diff --git a/dom/browser-element/mochitest/file_browserElement_XFrameOptionsDeny.html b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsDeny.html new file mode 100644 index 000000000..338275aa3 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsDeny.html @@ -0,0 +1,57 @@ +<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 iframe1Load() { + iframe1.removeEventListener('load', iframe1Load); + iframe1Loaded = true; + waitForBothLoads(); +}); + +var iframe2Loaded = false; +iframe2.addEventListener('load', function iframe2Load() { + iframe2.removeEventListener('load', iframe2Load); + iframe2Loaded = true; + waitForBothLoads(); +}); + +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> diff --git a/dom/browser-element/mochitest/file_browserElement_XFrameOptionsSameOrigin.html b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsSameOrigin.html new file mode 100644 index 000000000..11e75f141 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsSameOrigin.html @@ -0,0 +1,5 @@ +<html> +<body> +<iframe src='file_browserElement_XFrameOptions.sjs?SAMEORIGIN'></iframe> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_bug709759.sjs b/dom/browser-element/mochitest/file_bug709759.sjs new file mode 100644 index 000000000..ce78b188b --- /dev/null +++ b/dom/browser-element/mochitest/file_bug709759.sjs @@ -0,0 +1,5 @@ +function handleRequest(request, response) +{ + response.processAsync(); + response.setHeader("Content-Type", "image/jpeg", false); +}
\ No newline at end of file diff --git a/dom/browser-element/mochitest/file_bug741717.sjs b/dom/browser-element/mochitest/file_bug741717.sjs new file mode 100644 index 000000000..bde9ddfae --- /dev/null +++ b/dom/browser-element/mochitest/file_bug741717.sjs @@ -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>'); +} diff --git a/dom/browser-element/mochitest/file_download_bin.sjs b/dom/browser-element/mochitest/file_download_bin.sjs new file mode 100644 index 000000000..fd394ea0a --- /dev/null +++ b/dom/browser-element/mochitest/file_download_bin.sjs @@ -0,0 +1,4 @@ +function handleRequest(request, response) { + response.setHeader("Content-Type", "application/octet-stream", false); + response.write("BIN"); +}
\ No newline at end of file diff --git a/dom/browser-element/mochitest/file_empty.html b/dom/browser-element/mochitest/file_empty.html new file mode 100644 index 000000000..ed21305b9 --- /dev/null +++ b/dom/browser-element/mochitest/file_empty.html @@ -0,0 +1,14 @@ +<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> +document.getElementById('url').innerHTML = window.location; +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/file_empty_script.js b/dom/browser-element/mochitest/file_empty_script.js new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/dom/browser-element/mochitest/file_empty_script.js diff --git a/dom/browser-element/mochitest/file_focus.html b/dom/browser-element/mochitest/file_focus.html new file mode 100644 index 000000000..0bd3f7aa4 --- /dev/null +++ b/dom/browser-element/mochitest/file_focus.html @@ -0,0 +1,24 @@ +<html> +<body> + +Aloha! My URL is <span id='url'></span>. +<script> +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 == SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE && + alreadyBlocked == false) { + alreadyBlocked = true; + e.preventDefault(); + } + }); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/file_http_401_response.sjs b/dom/browser-element/mochitest/file_http_401_response.sjs new file mode 100644 index 000000000..c40a252c3 --- /dev/null +++ b/dom/browser-element/mochitest/file_http_401_response.sjs @@ -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>"); + } +}
\ No newline at end of file diff --git a/dom/browser-element/mochitest/file_http_407_response.sjs b/dom/browser-element/mochitest/file_http_407_response.sjs new file mode 100644 index 000000000..da2f27620 --- /dev/null +++ b/dom/browser-element/mochitest/file_http_407_response.sjs @@ -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>"); + } +} diff --git a/dom/browser-element/mochitest/file_illegal_web_manifest.html b/dom/browser-element/mochitest/file_illegal_web_manifest.html new file mode 100644 index 000000000..d9075b3fc --- /dev/null +++ b/dom/browser-element/mochitest/file_illegal_web_manifest.html @@ -0,0 +1,7 @@ +<!doctype html> +<meta charset=utf-8> +<head> +<!-- FIXME: we should keep file:// here ... --> +<link rel="manifest" href="sshfs://this_is_not_allowed!"> +</head> +<h1>Support Page for Web Manifest Tests</h1> diff --git a/dom/browser-element/mochitest/file_post_request.html b/dom/browser-element/mochitest/file_post_request.html new file mode 100644 index 000000000..773193067 --- /dev/null +++ b/dom/browser-element/mochitest/file_post_request.html @@ -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> diff --git a/dom/browser-element/mochitest/file_web_manifest.html b/dom/browser-element/mochitest/file_web_manifest.html new file mode 100644 index 000000000..783da0f47 --- /dev/null +++ b/dom/browser-element/mochitest/file_web_manifest.html @@ -0,0 +1,6 @@ +<!doctype html> +<meta charset=utf-8> +<head> +<link rel="manifest" href="file_web_manifest.json"> +</head> +<h1>Support Page for Web Manifest Tests</h1> diff --git a/dom/browser-element/mochitest/file_web_manifest.json b/dom/browser-element/mochitest/file_web_manifest.json new file mode 100644 index 000000000..57d0c3d42 --- /dev/null +++ b/dom/browser-element/mochitest/file_web_manifest.json @@ -0,0 +1 @@ +{"name": "pass"} diff --git a/dom/browser-element/mochitest/file_wyciwyg.html b/dom/browser-element/mochitest/file_wyciwyg.html new file mode 100644 index 000000000..f53216144 --- /dev/null +++ b/dom/browser-element/mochitest/file_wyciwyg.html @@ -0,0 +1,14 @@ +<html> +<head> +<title>test</title> +<script type="text/javascript"> +addEventListener('load', function() { + window.setTimeout(function() { + document.write("test"); + }, 0); +}); +</script> +</head> +<body> +</body> +</html> diff --git a/dom/browser-element/mochitest/iframe_file_audio.html b/dom/browser-element/mochitest/iframe_file_audio.html new file mode 100644 index 000000000..605ce2870 --- /dev/null +++ b/dom/browser-element/mochitest/iframe_file_audio.html @@ -0,0 +1,5 @@ +<html> +<body> +<iframe src="file_audio.html"></iframe> +</body> +</html> diff --git a/dom/browser-element/mochitest/mochitest-oop.ini b/dom/browser-element/mochitest/mochitest-oop.ini new file mode 100644 index 000000000..70d38c532 --- /dev/null +++ b/dom/browser-element/mochitest/mochitest-oop.ini @@ -0,0 +1,135 @@ +[DEFAULT] +# Both the "inproc" and "oop" versions of OpenMixedProcess open remote frames, +# so we don't run that test on platforms which don't support OOP tests. +skip-if = os == "android" || e10s +support-files = + browserElement_OpenMixedProcess.js + file_browserElement_ExecuteScript.html + file_browserElement_OpenMixedProcess.html + browserElement_ExecuteScript.js + browserElement_Find.js + browserElement_OpenTab.js + +[test_browserElement_oop_AudioChannelSeeking.html] +tags = audiochannel +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_Viewmode.html] +[test_browserElement_oop_ThemeColor.html] +[test_browserElement_inproc_ErrorSecurity.html] +[test_browserElement_inproc_OpenMixedProcess.html] +disabled = disabled for bug 1266035 +[test_browserElement_oop_Alert.html] +[test_browserElement_oop_AlertInFrame.html] +[test_browserElement_oop_AudioChannelMutedByDefault.html] +tags = audiochannel +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_Auth.html] +[test_browserElement_oop_BackForward.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_BadScreenshot.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_BrowserWindowResize.html] +[test_browserElement_oop_Close.html] +[test_browserElement_oop_CookiesNotThirdParty.html] +[test_browserElement_oop_CopyPaste.html] +subsuite = clipboard +[test_browserElement_oop_DOMRequestError.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_DataURI.html] +[test_browserElement_oop_DocumentFirstPaint.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_Download.html] +disabled = bug 1022281 +[test_browserElement_oop_ErrorSecurity.html] +[test_browserElement_oop_ExecuteScript.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_Find.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_FirstPaint.html] +[test_browserElement_oop_ForwardName.html] +[test_browserElement_oop_FrameWrongURI.html] +[test_browserElement_oop_GetScreenshot.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_GetScreenshotDppx.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_Iconchange.html] +[test_browserElement_oop_LoadEvents.html] +[test_browserElement_oop_Manifestchange.html] +[test_browserElement_oop_Metachange.html] +[test_browserElement_oop_NoAudioTrack.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_AudioPlayback.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_OpenMixedProcess.html] +disabled = disabled for bug 1266035 +[test_browserElement_oop_OpenNamed.html] +[test_browserElement_oop_OpenWindow.html] +[test_browserElement_oop_OpenWindowDifferentOrigin.html] +[test_browserElement_oop_OpenWindowInFrame.html] +[test_browserElement_oop_OpenWindowRejected.html] +[test_browserElement_oop_Opensearch.html] +[test_browserElement_oop_OpenTab.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_PrivateBrowsing.html] +[test_browserElement_oop_PromptCheck.html] +[test_browserElement_oop_PromptConfirm.html] +[test_browserElement_oop_Proxy.html] +[test_browserElement_oop_PurgeHistory.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_Reload.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_ReloadPostRequest.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[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 +[test_browserElement_oop_SetInputMethodActive.html] +# skip-if = (os == "android") +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_SetVisible.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_SetVisibleFrames.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_SetVisibleFrames2.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_Stop.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_TargetBlank.html] +[test_browserElement_oop_TargetTop.html] +[test_browserElement_oop_Titlechange.html] +[test_browserElement_oop_TopBarrier.html] +[test_browserElement_oop_VisibilityChange.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_XFrameOptions.html] +[test_browserElement_oop_XFrameOptionsAllowFrom.html] +disabled = Disabling some OOP tests for WebIDL scope changes +# bug 1189592 +skip-if = asan +[test_browserElement_oop_XFrameOptionsDeny.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_XFrameOptionsSameOrigin.html] +# Disabled until bug 930449 makes it stop timing out +[test_browserElement_oop_ContextmenuEvents.html] +disabled = bug 930449 +# Disabled until bug 924771 makes them stop timing out +[test_browserElement_oop_CloseFromOpener.html] +disabled = bug 924771 +[test_browserElement_oop_ExposableURI.html] +disabled = bug 924771 +[test_browserElement_oop_GetContentDimensions.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_AudioChannel.html] +tags = audiochannel +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_AudioChannel_nested.html] +tags = audiochannel +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_getWebManifest.html] +disabled = Disabling some OOP tests for WebIDL scope changes +[test_browserElement_oop_OpenWindowEmpty.html] +[test_browserElement_oop_ActiveStateChange.html] +tags = audiochannel +disabled = Disabling some OOP tests for WebIDL scope changes diff --git a/dom/browser-element/mochitest/mochitest.ini b/dom/browser-element/mochitest/mochitest.ini new file mode 100644 index 000000000..e1799f93f --- /dev/null +++ b/dom/browser-element/mochitest/mochitest.ini @@ -0,0 +1,159 @@ +[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_BrowserWindowNamespace.js + browserElement_BrowserWindowResize.js + browserElement_Close.js + browserElement_CloseFromOpener.js + browserElement_ContextmenuEvents.js + browserElement_CookiesNotThirdParty.js + browserElement_CopyPaste.js + browserElement_DataURI.js + browserElement_Download.js + browserElement_ErrorSecurity.js + browserElement_ExposableURI.js + browserElement_FirstPaint.js + browserElement_ForwardName.js + browserElement_FrameWrongURI.js + browserElement_Iconchange.js + browserElement_LoadEvents.js + browserElement_Manifestchange.js + browserElement_Metachange.js + browserElement_NextPaint.js + browserElement_OpenNamed.js + browserElement_OpenTab.js + browserElement_OpenWindow.js + browserElement_OpenWindowDifferentOrigin.js + browserElement_OpenWindowEmpty.js + browserElement_OpenWindowInFrame.js + browserElement_OpenWindowRejected.js + browserElement_Opensearch.js + browserElement_PrivateBrowsing.js + browserElement_PromptCheck.js + browserElement_PromptConfirm.js + browserElement_Proxy.js + browserElement_Reload.js + browserElement_RemoveBrowserElement.js + browserElement_ScrollEvent.js + browserElement_SecurityChange.js + browserElement_TargetBlank.js + browserElement_TargetTop.js + browserElement_Titlechange.js + browserElement_TopBarrier.js + browserElement_XFrameOptions.js + browserElement_XFrameOptionsAllowFrom.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_BrowserWindowNamespace.html + file_browserElement_CloseFromOpener.html + file_browserElement_CookiesNotThirdParty.html + file_browserElement_ForwardName.html + file_browserElement_FrameWrongURI.html + file_browserElement_LoadEvents.html + file_browserElement_Metachange.sjs + file_browserElement_NextPaint.html + file_browserElement_Open1.html + file_browserElement_Open2.html + file_browserElement_OpenNamed.html + file_browserElement_OpenNamed2.html + file_browserElement_OpenWindowDifferentOrigin.html + file_browserElement_OpenWindowEmpty.html + file_browserElement_OpenWindowInFrame.html + file_browserElement_OpenWindowRejected.html + file_browserElement_PrivateBrowsing.html + file_browserElement_SecurityChange.html + file_browserElement_TargetBlank.html + file_browserElement_TargetTop.html + file_browserElement_XFrameOptions.sjs + file_browserElement_XFrameOptionsAllowFrom.html + file_browserElement_XFrameOptionsAllowFrom.sjs + file_browserElement_XFrameOptionsDeny.html + file_browserElement_XFrameOptionsSameOrigin.html + file_bug741717.sjs + file_download_bin.sjs + file_empty.html + file_empty_script.js + file_focus.html + file_http_401_response.sjs + file_http_407_response.sjs + file_wyciwyg.html + file_audio.html + iframe_file_audio.html + file_web_manifest.html + file_web_manifest.json + file_illegal_web_manifest.html + 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] +[test_browserElement_inproc_BrowserWindowNamespace.html] +[test_browserElement_inproc_BrowserWindowResize.html] +[test_browserElement_inproc_Close.html] +[test_browserElement_inproc_CloseFromOpener.html] +[test_browserElement_inproc_ContextmenuEvents.html] +[test_browserElement_inproc_CookiesNotThirdParty.html] +[test_browserElement_inproc_CopyPaste.html] +subsuite = clipboard +skip-if = (os == "android") # Disabled on Android, see bug 1230421 +[test_browserElement_inproc_DataURI.html] +[test_browserElement_inproc_Download.html] +disabled = bug 1022281 +[test_browserElement_inproc_ExposableURI.html] +[test_browserElement_inproc_FirstPaint.html] +[test_browserElement_inproc_ForwardName.html] +[test_browserElement_inproc_FrameWrongURI.html] +[test_browserElement_inproc_Iconchange.html] +[test_browserElement_inproc_LoadEvents.html] +[test_browserElement_inproc_Manifestchange.html] +[test_browserElement_inproc_Metachange.html] +[test_browserElement_inproc_OpenNamed.html] +[test_browserElement_inproc_OpenTab.html] +disabled = won't work as Firefox desktop will intercept ctrl-click +[test_browserElement_inproc_OpenWindow.html] +[test_browserElement_inproc_OpenWindowDifferentOrigin.html] +[test_browserElement_inproc_OpenWindowInFrame.html] +[test_browserElement_inproc_OpenWindowRejected.html] +[test_browserElement_inproc_Opensearch.html] +[test_browserElement_inproc_PrivateBrowsing.html] +[test_browserElement_inproc_PromptCheck.html] +[test_browserElement_inproc_PromptConfirm.html] +[test_browserElement_inproc_Proxy.html] +[test_browserElement_inproc_RemoveBrowserElement.html] +[test_browserElement_inproc_ScrollEvent.html] +[test_browserElement_inproc_SecurityChange.html] +[test_browserElement_inproc_TargetBlank.html] +[test_browserElement_inproc_TargetTop.html] +[test_browserElement_inproc_Titlechange.html] +[test_browserElement_inproc_TopBarrier.html] +[test_browserElement_inproc_XFrameOptions.html] +[test_browserElement_inproc_XFrameOptionsAllowFrom.html] +[test_browserElement_inproc_XFrameOptionsDeny.html] +[test_browserElement_inproc_XFrameOptionsSameOrigin.html] +[test_browserElement_oop_NextPaint.html] +# Disabled due to https://bugzilla.mozilla.org/show_bug.cgi?id=774100 +disabled = temp disabling some OOP tests for WebIDL scope changes +[test_browserElement_inproc_Reload.html] +disabled = bug 774100 +[test_browserElement_inproc_OpenWindowEmpty.html] diff --git a/dom/browser-element/mochitest/noaudio.webm b/dom/browser-element/mochitest/noaudio.webm Binary files differnew file mode 100644 index 000000000..9207017fb --- /dev/null +++ b/dom/browser-element/mochitest/noaudio.webm diff --git a/dom/browser-element/mochitest/priority/chrome.ini b/dom/browser-element/mochitest/priority/chrome.ini new file mode 100644 index 000000000..e1852f6ff --- /dev/null +++ b/dom/browser-element/mochitest/priority/chrome.ini @@ -0,0 +1,19 @@ +[DEFAULT] +# Good luck running these tests on anything but desktop Linux. +run-if = os == 'linux' && buildapp == 'browser' && !e10s +support-files = + file_Audio.html + file_MultipleFrames.html + file_NestedFramesOuter.html + file_WebGLContextLost.html + silence.ogg + !/dom/browser-element/mochitest/browserElementTestHelpers.js + !/dom/browser-element/mochitest/file_empty.html + +[test_Activity.html] +[test_Audio.html] +[test_Background.html] +[test_Keyboard.html] +[test_MultipleFrames.html] +[test_NestedFrames.html] +[test_Visibility.html] diff --git a/dom/browser-element/mochitest/priority/file_Audio.html b/dom/browser-element/mochitest/priority/file_Audio.html new file mode 100644 index 000000000..97f4dc64d --- /dev/null +++ b/dom/browser-element/mochitest/priority/file_Audio.html @@ -0,0 +1,19 @@ +<html> +<body> + +<script> +addEventListener('load', function() { + setTimeout(function() { + var a = document.getElementById('audio'); + a.onplay = function() { + alert('onplay'); + }; + a.play(); + }, 0); +}); +</script> + +<audio id='audio' loop src='silence.ogg'> + +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/file_HighPriority.html b/dom/browser-element/mochitest/priority/file_HighPriority.html new file mode 100644 index 000000000..dc7197bba --- /dev/null +++ b/dom/browser-element/mochitest/priority/file_HighPriority.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<body> + +<script> +var lock = navigator.requestWakeLock('high-priority'); +alert('step0'); + +lock.unlock(); +alert('step1'); + +lock = navigator.requestWakeLock('cpu'); +alert('step2'); + +lock.unlock(); +alert('step3'); +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/file_MultipleFrames.html b/dom/browser-element/mochitest/priority/file_MultipleFrames.html new file mode 100644 index 000000000..b3b56f560 --- /dev/null +++ b/dom/browser-element/mochitest/priority/file_MultipleFrames.html @@ -0,0 +1,14 @@ +<html> +<body> +<p>file_MultipleFrames.html</p> + +<script> +addEventListener('load', function() { + setTimeout(function() { + window.open('../file_empty.html'); + }, 0); +}); +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/file_NestedFramesOuter.html b/dom/browser-element/mochitest/priority/file_NestedFramesOuter.html new file mode 100644 index 000000000..e4378935f --- /dev/null +++ b/dom/browser-element/mochitest/priority/file_NestedFramesOuter.html @@ -0,0 +1,20 @@ +<html> +<body> +<p>file_NestedFramesOuter.html</p> +<script> + +addEventListener('load', function() { + setTimeout(createIframe, 0); +}); + +function createIframe() +{ + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.src = location.hash.substr(1); + document.body.appendChild(iframe); +} + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/file_WebGLContextLost.html b/dom/browser-element/mochitest/priority/file_WebGLContextLost.html new file mode 100644 index 000000000..bd5c84f11 --- /dev/null +++ b/dom/browser-element/mochitest/priority/file_WebGLContextLost.html @@ -0,0 +1,22 @@ +<html> +<body> +file_WebGLContextLost.html +<canvas id='canvas'></canvas> + +<script> +function runTest() +{ + var canvas = document.getElementById('canvas'); + canvas.addEventListener('webglcontextlost', function() { + alert('webglcontextlost'); + }); + + var context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + context.viewport(0, 0, 10, 10); + alert('ready'); +} + +addEventListener('load', function() { setTimeout(runTest, 0) }); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/mochitest.ini b/dom/browser-element/mochitest/priority/mochitest.ini new file mode 100644 index 000000000..8118aedd7 --- /dev/null +++ b/dom/browser-element/mochitest/priority/mochitest.ini @@ -0,0 +1,19 @@ +[DEFAULT] +# Good luck running these tests on anything but desktop Linux. +run-if = os == 'linux' && buildapp == 'browser' && !e10s +support-files = + file_HighPriority.html + silence.ogg + !/dom/browser-element/mochitest/browserElementTestHelpers.js + !/dom/browser-element/mochitest/file_empty.html + +# Note: ../browserElementTestHelpers.js makes all tests in this directory OOP, +# because testing the process-priority manager without OOP frames does not make +# much sense. + +[test_Simple.html] +[test_HighPriority.html] +[test_Preallocated.html] +disabled = bug 968604, bug 987164 +[test_WebGLContextLost.html] +disabled = bug 865844 diff --git a/dom/browser-element/mochitest/priority/silence.ogg b/dom/browser-element/mochitest/priority/silence.ogg Binary files differnew file mode 100644 index 000000000..6e0b352a3 --- /dev/null +++ b/dom/browser-element/mochitest/priority/silence.ogg diff --git a/dom/browser-element/mochitest/priority/test_Activity.html b/dom/browser-element/mochitest/priority/test_Activity.html new file mode 100644 index 000000000..ae4049d96 --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_Activity.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that calling setVisible("false") on an iframe that has an open activity +causes its priority to change. +--> +<head> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + var os = SpecialPowers.Cc["@mozilla.org/observer-service;1"] + .getService(SpecialPowers.Ci.nsIObserverService); + var iframe = document.createElement("iframe"); + iframe.setAttribute("mozbrowser", true); + + iframe.src = browserElementTestHelpers.emptyPage1; + + var childID = null; + Promise.all([ + expectOnlyOneProcessCreated("FOREGROUND").then(function(chid) { + childID = chid; + }), + expectMozbrowserEvent(iframe, "loadend") + ]).then(function() { + var p = expectPriorityChange(childID, "BACKGROUND_PERCEIVABLE"); + + // We simulate opening an activity + os.notifyObservers(null, "activity-opened", childID); + + // We wait until mozbrowserloadend before calling setVisible, because + // setVisible isn't available until mozbrowser has loaded. In practice, that + // means we can call setVisible once we've gotten /any/ mozbrowser event. + iframe.setVisible(false); + return p; + }).then(function() { + var p = expectPriorityChange(childID, "BACKGROUND"); + + // Now we simulate closing an activity + os.notifyObservers(null, "activity-closed", childID); + + return p; + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +addEventListener("testready", runTest); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_Audio.html b/dom/browser-element/mochitest/priority/test_Audio.html new file mode 100644 index 000000000..d39b1c9f3 --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_Audio.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that frames playing audio get BACKGROUND_PERCEIVABLE priority. +--> +<head> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.src = 'file_Audio.html'; + + var childID = null; + Promise.all([ + expectOnlyOneProcessCreated("FOREGROUND").then(function(chid) { + childID = chid; + }), + expectMozbrowserEvent(iframe, 'loadend'), + expectMozbrowserEvent(iframe, 'showmodalprompt').then(function(e) { + is(e.detail.message, 'onplay', 'showmodalprompt message'); + }) + ]).then(function() { + // Send the child process into the background. Because it's playing audio, + // it should get priority BACKGROUND_PERCEIVABLE, not vanilla BACKGROUND. + var p = expectPriorityChange(childID, 'BACKGROUND_PERCEIVABLE'); + iframe.setVisible(false); + return p; + }).then(function() { + var p = expectPriorityChange(childID, 'FOREGROUND'); + iframe.setVisible(true); + return p; + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_Background.html b/dom/browser-element/mochitest/priority/test_Background.html new file mode 100644 index 000000000..59eb16863 --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_Background.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that calling setVisible('false') on an iframe causes its visibility to +change. +--> +<head> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + + iframe.src = browserElementTestHelpers.emptyPage1; + + var childID = null; + Promise.all([ + expectOnlyOneProcessCreated('FOREGROUND').then(function(chid) { + childID = chid; + }), + expectMozbrowserEvent(iframe, 'loadend') + ]).then(function() { + var p = expectPriorityChange(childID, 'BACKGROUND'); + + // We wait until mozbrowserloadend before calling setVisible, because + // setVisible isn't available until mozbrowser has loaded. In practice, that + // means we can call setVisible once we've gotten /any/ mozbrowser event. + iframe.setVisible(false); + return p; + }).then(function() { + var p = expectPriorityChange(childID, 'FOREGROUND'); + iframe.setVisible(true); + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_HighPriority.html b/dom/browser-element/mochitest/priority/test_HighPriority.html new file mode 100644 index 000000000..d3396d65b --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_HighPriority.html @@ -0,0 +1,133 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that frames with mozapptype=critical which hold the "high-priority" or +"cpu" wake locks get elevated process priority. +--> +<head> + <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;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + // To test bug 870480, run this test while holding the CPU and high-priority + // wake locks. Without the fix for bug 870480, we won't set the priority of + // the child process if the main process holds these wake locks and the test + // will hang. + navigator.requestWakeLock('cpu'); + navigator.requestWakeLock('high-priority'); + + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.setAttribute('mozapptype', 'critical'); + iframe.src = 'file_HighPriority.html'; + + // We expect the following to happen: + // + // - Process is created. + // - Its priority is set to FOREGROUND (when the process starts). + // - wait_alert('step0', FOREGROUND_HIGH) + // - wait_alert('step1', FOREGROUND) + // - wait_alert('step2', FOREGROUND_HIGH) + // + // Where wait_alert(M, P) means that we expect the subprocess to + // * do alert(M) and + // * be set to priority P + // in some order. If the alert occurs before the priority change, we block + // the alert until we observe the priority change. So the subprocess only + // has to do + // + // // set priority to FOREGROUND_HIGH + // alert('step0'); + // // set priority to FOREGROUND + // alert('step1'); + // + // etc. + + var childID = null; + var alertTimes = []; + + // Return a promise that's resolved once the child process calls alert() and + // we get a priority change, in some order. + // + // We check that the text of the alert is |"step" + index|. + // + // If gracePeriod is given, we check that the priority change occurred at + // least gracePeriod ms since the alert from the previous step (with a fudge + // factor to account for inaccurate timers). + function expectAlertAndPriorityChange(index, priority, /* optional */ gracePeriod) { + function checkAlertInfo(e) { + is(e.detail.message, 'step' + index, 'alert() number ' + index); + alertTimes.push(new Date()); + + // Block the alert; we'll unblock it by calling e.detail.unblock() later. + e.preventDefault(); + return Promise.resolve(e.detail.unblock); + } + + function checkGracePeriod() { + if (gracePeriod) { + var msSinceLastAlert = (new Date()) - alertTimes[index - 1]; + + // 50ms fudge factor. This test is set up so that, if nsITimers are + // accurate, we don't need any fudge factor. Unfortunately our timers + // are not accurate! There's little we can do here except fudge. + // Thankfully all we're trying to test is that we get /some/ delay; the + // exact amount of delay isn't so important. + ok(msSinceLastAlert + 50 >= gracePeriod, + msSinceLastAlert + "ms since last alert >= (" + gracePeriod + " - 50ms)"); + } + } + + return Promise.all([ + new Promise(function(resolve, reject) { + iframe.addEventListener('mozbrowsershowmodalprompt', function check(e) { + iframe.removeEventListener('mozbrowsershowmodalprompt', check); + resolve(checkAlertInfo(e)); + }); + }), + expectPriorityChange(childID, priority).then(checkGracePeriod) + ]).then(function(results) { + // checkAlertInfo returns the function to call to unblock the alert. + // It comes to us as the first element of the results array. + results[0](); + }); + } + + expectProcessCreated('FOREGROUND').then(function(chid) { + childID = chid; + }).then(function() { + return expectAlertAndPriorityChange(0, 'FOREGROUND_HIGH'); + }).then(function() { + return expectAlertAndPriorityChange(1, 'FOREGROUND', priorityChangeGracePeriod); + }).then(function() { + return expectAlertAndPriorityChange(2, 'FOREGROUND_HIGH'); + }).then(function() { + return expectAlertAndPriorityChange(3, 'FOREGROUND', priorityChangeGracePeriod); + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +const priorityChangeGracePeriod = 100; +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv( + {set: [['dom.ipc.processPriorityManager.backgroundGracePeriodMS', + priorityChangeGracePeriod], + ['dom.wakelock.enabled', true]]}, + runTest); +}); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_Keyboard.html b/dom/browser-element/mochitest/priority/test_Keyboard.html new file mode 100644 index 000000000..a36f954ba --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_Keyboard.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that frames with mozapptype=inputmethod gets the keyboard-specific +priority level when in the foreground. +--> +<head> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.setAttribute('mozapptype', 'inputmethod'); + iframe.src = browserElementTestHelpers.emptyPage1; + + var childID = null; + Promise.all([ + expectOnlyOneProcessCreated('FOREGROUND_KEYBOARD').then(function(chid) { + childID = chid; + }), + expectMozbrowserEvent(iframe, 'loadend') + ]).then(function() { + var p = expectPriorityChange(childID, 'BACKGROUND'); + + /* We wait until mozbrowserloadend before calling setVisible, because + * setVisible isn't available until mozbrowser has loaded. In practice, + * that means we can call setVisible once we've gotten /any/ mozbrowser + * event. */ + iframe.setVisible(false); + return p; + }).then(function() { + var p = expectPriorityChange(childID, 'FOREGROUND_KEYBOARD'); + iframe.setVisible(true); + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_MultipleFrames.html b/dom/browser-element/mochitest/priority/test_MultipleFrames.html new file mode 100644 index 000000000..57d9563e7 --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_MultipleFrames.html @@ -0,0 +1,58 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that when we remove one of a process's frames from the DOM, the process's +priority is recomputed. +--> +<head> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.src = 'file_MultipleFrames.html'; + + var childID = null; + var iframe2; + Promise.all([ + expectProcessCreated('FOREGROUND').then(function(chid) { + childID = chid; + }), + new Promise(function(resolve, reject) { + iframe.addEventListener('mozbrowseropenwindow', function(e) { + iframe2 = e.detail.frameElement; + var p = expectMozbrowserEvent(iframe2, 'loadend'); + document.body.appendChild(iframe2); + resolve(p); + }); + }) + ]).then(function() { + // At this point, the child process has been set to FOREGROUND, and the popup + // opened by file_MultipleFrames has finished loading. + // + // Now setVisible(false) the popup frame and remove the popup frame from the + // DOM. This should cause the process to take on BACKGROUND priority. + var p = expectPriorityChange(childID, 'BACKGROUND'); + iframe.setVisible(false); + document.body.removeChild(iframe2); + return p; + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_NestedFrames.html b/dom/browser-element/mochitest/priority/test_NestedFrames.html new file mode 100644 index 000000000..e5381bcc5 --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_NestedFrames.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test changing the visibility of an <iframe mozbrowser> changes the visibility +(and thus the priority) of any <iframe mozbrowser>s it contains. +--> +<head> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + // Set up the following hierarchy of frames: + // + // <iframe mozbrowser remote=false src='file_NestedFramesOuter.html'> + // <iframe mozbrowser remote=true src='file_empty.html'> + // + // When we change the visibility of the outer iframe, it should change the + // priority of the inner one. + + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.setAttribute('remote', false); + iframe.src = 'file_NestedFramesOuter.html#' + browserElementTestHelpers.emptyPage1; + + // Note that this is the process corresponding to the /inner/ iframe. The + // outer iframe runs in-process (because it has remote=false). + var childID = null; + Promise.all( + [expectOnlyOneProcessCreated('FOREGROUND').then(function(child) { + childID = child; + }), + expectMozbrowserEvent(iframe, 'loadend')] + ).then(function() { + // Send the outer iframe into the background. This should change the + // priority of the inner frame's process to BACKGROUND. + var p = expectPriorityChange(childID, 'BACKGROUND'); + iframe.setVisible(false); + return p; + }).then(function() { + var p = expectPriorityChange(childID, 'FOREGROUND'); + iframe.setVisible(true); + return p; + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_Preallocated.html b/dom/browser-element/mochitest/priority/test_Preallocated.html new file mode 100644 index 000000000..b2cb0335e --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_Preallocated.html @@ -0,0 +1,71 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that the preallocated process starts up with priority BACKGROUND. +--> +<head> + <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;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); +browserElementTestHelpers.enableProcessPriorityManager(); + +var preallocationEnabledPref = null; +try { + preallocationEnabledPref = SpecialPowers.getBoolPref('dom.ipc.processPrelaunch.enabled'); +} +catch(e) { + preallocationEnabledPref = null; +} + +var childID = null; + +var cleanedUp = false; +function cleanUp() +{ + if (cleanedUp) { + return; + } + + cleanedUp = true; +} + +// Even if this test times out, we still want to run cleanUp so as to set the +// pref back. +addEventListener('unload', cleanUp); + +function runTest() +{ + if (preallocationEnabledPref) { + ok(false, "dom.ipc.processPrelaunch.enabled must be " + + "false for this test to work."); + SimpleTest.finish(); + return; + } + + // Ensure that the preallocated process initially gets BACKGROUND priority. + // That's it. + expectProcessCreated('PREALLOC').then(function() { + // We need to set the pref asynchoronously or the preallocated process won't + // be shut down. + SimpleTest.executeSoon(function(){ + cleanUp(); + SimpleTest.finish(); + }); + }); +} +// Setting this pref to true should cause us to prelaunch a process. +addEventListener('testready', function() { + SpecialPowers.pushPrefEnv({'set':[["dom.ipc.processPrelaunch.enabled",true]]},runTest); +}); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_Simple.html b/dom/browser-element/mochitest/priority/test_Simple.html new file mode 100644 index 000000000..7cc801e54 --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_Simple.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +A simple test of the process priority manager. + +https://bugzilla.mozilla.org/show_bug.cgi?id=844323 + +Note: If you run this test alone (i.e. not as part of the larger mochitest +suite), you may see some IPC assertions, e.g. "Can't allocate graphics +resources." + +What appears to be happening is that we close the Firefox window before the +frame we create in this tab finishes starting up. Then the frame finishes +loading, and it tries to show itself. But it's too late to show a remote frame +at that point, so we kill the child process. + +In other words, I think these errors are nothing to worry about. +--> +<head> + <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;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); +browserElementTestHelpers.enableProcessPriorityManager(); + +var allCompleted = 0; +var allExpected = 2; +function finish() { + allCompleted++; + if (allCompleted === allExpected) { + SimpleTest.finish(); + } +} + +function runTest() { + var iframeLoaded = false; + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.src = browserElementTestHelpers.emptyPage1; + + iframe.addEventListener('mozbrowserloadend', finish); + expectProcessCreated('FOREGROUND').then(finish); + + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_Visibility.html b/dom/browser-element/mochitest/priority/test_Visibility.html new file mode 100644 index 000000000..58648b99f --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_Visibility.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that setVisible() changes a process's priority. +--> +<head> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.src = browserElementTestHelpers.emptyPage1; + + var childID = null; + Promise.all([ + expectOnlyOneProcessCreated('FOREGROUND').then(function(chid) { + childID = chid; + }), + expectMozbrowserEvent(iframe, 'loadend') + ]).then(function() { + // Mark the frame as not visible. This should cause its priority to drop + // to BACKGROUND. + var p = expectPriorityChange(childID, 'BACKGROUND'); + iframe.setVisible(false); + return p; + }).then(function() { + // Mark the frame as visible again. This should cause its priority change + // back to FOREGROUND. + var p = expectPriorityChange(childID, 'FOREGROUND'); + iframe.setVisible(true); + return p; + }).then(SimpleTest.finish); + + document.body.appendChild(iframe); +} + +addEventListener('testready', runTest); +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/priority/test_WebGLContextLost.html b/dom/browser-element/mochitest/priority/test_WebGLContextLost.html new file mode 100644 index 000000000..383506ec6 --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_WebGLContextLost.html @@ -0,0 +1,99 @@ +<!DOCTYPE HTML> +<html> +<!-- +Test that calling setVisible('false') and then sending a low-memory +notification causes a WebGL context loss event. +--> +<head> + <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;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); +browserElementTestHelpers.enableProcessPriorityManager(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', true); + iframe.src = 'file_WebGLContextLost.html'; + + // We use this to ensure that we don't call SimpleTest.finish() twice. + var finished = false; + function finishOnce() { + if (!finished) { + SimpleTest.finish(); + finished = true; + } + } + + expectMozbrowserEvent(iframe, 'error').then(function(e) { + if (finished) { + // We don't care if the frame dies after the test finishes. + return; + } + todo(false, "child process is crashing; this probably indicates that " + + "something is wrong with WebGL in child processes on your machine."); + is(e.detail.type, 'fatal'); + }).then(finishOnce); + + var childID = null; + Promise.all([ + expectOnlyOneProcessCreated('FOREGROUND').then(function(chid) { + childID = chid; + }), + expectMozbrowserEvent(iframe, 'loadend'), + expectMozbrowserEvent(iframe, 'showmodalprompt').then(function(e) { + is(e.detail.message, 'ready'); + }) + ]).then(function() { + // Fire a low-memory notification once the process goes into the background + // due to the setVisible(false) call below. + expectPriorityChange(childID, 'BACKGROUND').then(function() { + SimpleTest.executeSoon(function() { + var os = SpecialPowers.Cc["@mozilla.org/observer-service;1"] + .getService(SpecialPowers.Ci.nsIObserverService); + os.notifyObservers(null, "memory-pressure", "low-memory"); + ok(true, 'Successfully notified observers.'); + }); + }); + + // This test isn't the only possible source of a low-memory notification; the + // browser can fire one whenever it likes. So it's fine if we lose the + // WebGL context before we fire the low-memory notification ourself. + + var p = expectMozbrowserEvent(iframe, 'showmodalprompt').then(function(e) { + is(e.detail.message, 'webglcontextlost'); + }); + + iframe.setVisible(false); + return p; + }).then(finishOnce); + + document.body.appendChild(iframe); +} + +addEventListener('testready', function() { + // At the time this test was written, webgl was blocklisted inside child + // processes on desktop Linux. The issue is that we spawn a child process to + // read driver info, but we only did this on the main prrocess. Child + // processes never read the driver info themselves, nor do they get it from + // their parent, so they refuse to start up WebGL. + // + // This isn't a problem on B2G because we force WebGL on there. But it + // obviously makes this test difficult. bjacob says forcing WebGL on here + // shouldn't hurt things, and anyway this setting mirrors what we do on B2G, + // which is what we're trying to test! + SpecialPowers.pushPrefEnv({set: [["webgl.force-enabled", true]]}, + runTest); +}); + +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_NoAttr.html b/dom/browser-element/mochitest/test_browserElement_NoAttr.html new file mode 100644 index 000000000..070aee19f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_NoAttr.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=710231 +--> +<head> + <title>Test for Bug 710231</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a> + +<!-- + Test that an iframe without the |mozbrowser| attribute does not emit + mozbrowserX events. +--> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); + +function runTest() { + var iframe = document.getElementById('iframe'); + iframe.addEventListener('mozbrowserloadstart', function() { + ok(false, 'Should not send mozbrowserloadstart event.'); + }); + + iframe.addEventListener('load', function() { + ok(true, 'Got iframe load event.'); + SimpleTest.finish(); + }); + + iframe.src = browserElementTestHelpers.emptyPage1; +} + +addEventListener('load', function() { SimpleTest.executeSoon(runTest); }); + +</script> + +<iframe id='iframe'></iframe> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_NoPermission.html b/dom/browser-element/mochitest/test_browserElement_NoPermission.html new file mode 100644 index 000000000..4e1d88072 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_NoPermission.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=710231 +--> +<head> + <title>Test for Bug 710231</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a> + +<!-- + Test that an iframe with the |mozbrowser| attribute does not emit + mozbrowserX events when this page does not have the "browser" permission. +--> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); + +function runTest() { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + + iframe.addEventListener('mozbrowserloadstart', function() { + ok(false, 'Should not send mozbrowserloadstart event.'); + }); + + iframe.addEventListener('load', function() { + ok(true, 'Got iframe load event.'); + SimpleTest.finish(); + }); + + iframe.src = browserElementTestHelpers.emptyPage1; +} + +browserElementTestHelpers.setEnabledPref(true); +SpecialPowers.removePermission("browser", document); +addEventListener('testready', runTest); + +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_NoPref.html b/dom/browser-element/mochitest/test_browserElement_NoPref.html new file mode 100644 index 000000000..df69e4c43 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_NoPref.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=710231 +--> +<head> + <title>Test for Bug 710231</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a> + +<!-- + Test that an iframe with the |mozbrowser| attribute does not emit + mozbrowserX events when they're globally pref'ed off. +--> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); + +function runTest() { + + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + + iframe.addEventListener('mozbrowserloadstart', function() { + ok(false, 'Should not send mozbrowserloadstart event.'); + }); + + iframe.addEventListener('load', function() { + ok(true, 'Got iframe load event.'); + SimpleTest.finish(); + }); + + iframe.src = browserElementTestHelpers.emptyPage1; +} + +browserElementTestHelpers.setEnabledPref(false); +addEventListener('testready', runTest); + +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ActiveStateChange.html b/dom/browser-element/mochitest/test_browserElement_inproc_ActiveStateChange.html new file mode 100644 index 000000000..4a14ad7cb --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ActiveStateChange.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test ActiveStateChangeOnChangingMutedOrVolume</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_ActiveStateChange.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Alert.html b/dom/browser-element/mochitest/test_browserElement_inproc_Alert.html new file mode 100644 index 000000000..03d03135d --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Alert.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 741587</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741587">Mozilla Bug 741587</a> + +<script type="application/javascript;version=1.7" src="browserElement_Alert.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_AlertInFrame.html b/dom/browser-element/mochitest/test_browserElement_inproc_AlertInFrame.html new file mode 100644 index 000000000..d797a1a3a --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_AlertInFrame.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for iframe mozbrowser</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;version=1.7" src="browserElement_AlertInFrame.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannel.html b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannel.html new file mode 100644 index 000000000..6bba008d7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannel.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element audioChannel.</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_AudioChannel.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannelMutedByDefault.html b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannelMutedByDefault.html new file mode 100644 index 000000000..304b1b8b4 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannelMutedByDefault.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1235535 - Audio Channel Muted-By-Default.</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_AudioChannelMutedByDefault.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannelSeeking.html b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannelSeeking.html new file mode 100644 index 000000000..a7834e929 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannelSeeking.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1225425 - Do not unregister the AudioChannelAgent during seeking</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_AudioChannelSeeking.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannel_nested.html b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannel_nested.html new file mode 100644 index 000000000..2ee58002c --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_AudioChannel_nested.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element audioChannel in nested mozbrowser iframes.</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_AudioChannel_nested.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_AudioPlayback.html b/dom/browser-element/mochitest/test_browserElement_inproc_AudioPlayback.html new file mode 100644 index 000000000..364eeff68 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_AudioPlayback.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1180824 +--> +<head> + <title>Test for Bug 1180824</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1180824">Mozilla Bug 1180824</a> + +<script type="application/javascript;version=1.7" src="browserElement_AudioPlayback.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Auth.html b/dom/browser-element/mochitest/test_browserElement_inproc_Auth.html new file mode 100644 index 000000000..0dd60f8c6 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Auth.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 775464</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=775464">Mozilla Bug 775464</a> + +<script type="application/javascript;version=1.7" src="browserElement_Auth.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_BackForward.html b/dom/browser-element/mochitest/test_browserElement_inproc_BackForward.html new file mode 100644 index 000000000..d841cc3e0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_BackForward.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_BackForward.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_BadScreenshot.html b/dom/browser-element/mochitest/test_browserElement_inproc_BadScreenshot.html new file mode 100644 index 000000000..8e4b61b33 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_BadScreenshot.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 800170</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_BadScreenshot.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_BrowserWindowNamespace.html b/dom/browser-element/mochitest/test_browserElement_inproc_BrowserWindowNamespace.html new file mode 100644 index 000000000..3fafbe646 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_BrowserWindowNamespace.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 780351</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;version=1.7" src="browserElement_BrowserWindowNamespace.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_BrowserWindowResize.html b/dom/browser-element/mochitest/test_browserElement_inproc_BrowserWindowResize.html new file mode 100644 index 000000000..bcc86b872 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_BrowserWindowResize.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 891763</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;version=1.7" src="browserElement_BrowserWindowResize.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Close.html b/dom/browser-element/mochitest/test_browserElement_inproc_Close.html new file mode 100644 index 000000000..76d203f9d --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Close.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=757182 +--> +<head> + <title>Test for Bug 757182</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=757182">Mozilla Bug 757182</a> + +<script type="application/javascript;version=1.7" src="browserElement_Close.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_CloseFromOpener.html b/dom/browser-element/mochitest/test_browserElement_inproc_CloseFromOpener.html new file mode 100644 index 000000000..3c7ee4d87 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_CloseFromOpener.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=757182 +--> +<head> + <title>Test for Bug 757182</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=757182">Mozilla Bug 757182</a> + +<script type="application/javascript;version=1.7" src="browserElement_CloseFromOpener.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ContextmenuEvents.html b/dom/browser-element/mochitest/test_browserElement_inproc_ContextmenuEvents.html new file mode 100644 index 000000000..a43f7dbef --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ContextmenuEvents.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Contextmenu Events</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;version=1.7" src="browserElement_ContextmenuEvents.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_CookiesNotThirdParty.html b/dom/browser-element/mochitest/test_browserElement_inproc_CookiesNotThirdParty.html new file mode 100644 index 000000000..37ea16fb0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_CookiesNotThirdParty.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 806127</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;version=1.7" src="browserElement_CookiesNotThirdParty.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_CopyPaste.html b/dom/browser-element/mochitest/test_browserElement_inproc_CopyPaste.html new file mode 100644 index 000000000..892245d4f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_CopyPaste.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=987040 +--> +<head> + <title>Test for Bug 987040</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=987040">Mozilla Bug 987040</a> + +<script type="application/javascript;version=1.7" src="browserElement_CopyPaste.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_DOMRequestError.html b/dom/browser-element/mochitest/test_browserElement_inproc_DOMRequestError.html new file mode 100644 index 000000000..6a9e5bbba --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_DOMRequestError.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=787519 +--> +<head> + <title>Test for Bug 787519</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787519">Mozilla Bug 787519</a> + +<script type="application/javascript;version=1.7" src='browserElement_DOMRequestError.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_DataURI.html b/dom/browser-element/mochitest/test_browserElement_inproc_DataURI.html new file mode 100644 index 000000000..2ceb49cd0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_DataURI.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=720157 +--> +<head> + <title>Test for Bug 720157</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720157">Mozilla Bug 720157</a> + +<script type='application/javascript;version=1.7' src='browserElement_DataURI.js'></script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_DocumentFirstPaint.html b/dom/browser-element/mochitest/test_browserElement_inproc_DocumentFirstPaint.html new file mode 100644 index 000000000..3197adf66 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_DocumentFirstPaint.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 829486</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_DocumentFirstPaint.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Download.html b/dom/browser-element/mochitest/test_browserElement_inproc_Download.html new file mode 100644 index 000000000..c2e5e2ed3 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Download.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 983747</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;version=1.7" src="browserElement_Download.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ErrorSecurity.html b/dom/browser-element/mochitest/test_browserElement_inproc_ErrorSecurity.html new file mode 100644 index 000000000..318d29831 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ErrorSecurity.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for mozbrowser</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;version=1.7" src="browserElement_ErrorSecurity.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ExecuteScript.html b/dom/browser-element/mochitest/test_browserElement_inproc_ExecuteScript.html new file mode 100644 index 000000000..f63f31d42 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ExecuteScript.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1174733 +--> +<head> + <title>Test for Bug 1163961</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1174733">Mozilla Bug 1174733</a> + +<script type="application/javascript;version=1.7" src="browserElement_ExecuteScript.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html b/dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html new file mode 100644 index 000000000..089e5db44 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=795317 +--> +<head> + <title>Test for Bug 795317</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795317">Mozilla Bug 795317</a> + +<script type="application/javascript;version1.7" src="browserElement_ExposableURI.js"></script> + +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Find.html b/dom/browser-element/mochitest/test_browserElement_inproc_Find.html new file mode 100644 index 000000000..386bc7882 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Find.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1163961 +--> +<head> + <title>Test for Bug 1163961</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a> + +<script type="application/javascript;version=1.7" src="browserElement_Find.js"> +</script> +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_FirstPaint.html b/dom/browser-element/mochitest/test_browserElement_inproc_FirstPaint.html new file mode 100644 index 000000000..ee013860c --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_FirstPaint.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 787378</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;version=1.7" src="browserElement_FirstPaint.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ForwardName.html b/dom/browser-element/mochitest/test_browserElement_inproc_ForwardName.html new file mode 100644 index 000000000..f24691ff1 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ForwardName.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 781320</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;version=1.7" src="browserElement_ForwardName.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_FrameWrongURI.html b/dom/browser-element/mochitest/test_browserElement_inproc_FrameWrongURI.html new file mode 100644 index 000000000..f0e6e6c20 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_FrameWrongURI.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_FrameWrongURI.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_GetContentDimensions.html b/dom/browser-element/mochitest/test_browserElement_inproc_GetContentDimensions.html new file mode 100644 index 000000000..73b59800d --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_GetContentDimensions.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_GetContentDimensions.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_GetScreenshot.html b/dom/browser-element/mochitest/test_browserElement_inproc_GetScreenshot.html new file mode 100644 index 000000000..cb246fc06 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_GetScreenshot.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=753595 +--> +<head> + <title>Test for Bug 753595</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753595">Mozilla Bug 753595</a> + +<script type="application/javascript;version=1.7" src='browserElement_GetScreenshot.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_GetScreenshotDppx.html b/dom/browser-element/mochitest/test_browserElement_inproc_GetScreenshotDppx.html new file mode 100644 index 000000000..dfc10d102 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_GetScreenshotDppx.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=959066 +--> +<head> + <title>Test for Bug 959066</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=959066">Mozilla Bug 959066</a> + +<script type="application/javascript;version=1.7" src='browserElement_GetScreenshotDppx.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Iconchange.html b/dom/browser-element/mochitest/test_browserElement_inproc_Iconchange.html new file mode 100644 index 000000000..2f17287de --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Iconchange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=719461 +--> +<head> + <title>Test for Bug 719461</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=719461">Mozilla Bug 719461</a> + +<script type="application/javascript;version=1.7" src="browserElement_Iconchange.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html b/dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html new file mode 100644 index 000000000..3370ff874 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=710231 +--> +<head> + <title>Test for Bug 710231</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a> + +<script type="application/javascript;version1.7" src="browserElement_LoadEvents.js"></script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Manifestchange.html b/dom/browser-element/mochitest/test_browserElement_inproc_Manifestchange.html new file mode 100644 index 000000000..64200bd48 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Manifestchange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=982800 +--> +<head> + <title>Test for Bug 982800</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982800">Mozilla Bug 982800</a> + +<script type="application/javascript;version=1.7" src="browserElement_Manifestchange.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Metachange.html b/dom/browser-element/mochitest/test_browserElement_inproc_Metachange.html new file mode 100644 index 000000000..d799a52e4 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Metachange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=962626 +--> +<head> + <title>Test for Bug 962626</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=962626">Mozilla Bug 962626</a> + +<script type="application/javascript;version=1.7" src="browserElement_Metachange.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_NextPaint.html b/dom/browser-element/mochitest/test_browserElement_inproc_NextPaint.html new file mode 100644 index 000000000..d9250a8db --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_NextPaint.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 808231</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_NextPaint.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_NoAudioTrack.html b/dom/browser-element/mochitest/test_browserElement_inproc_NoAudioTrack.html new file mode 100644 index 000000000..77e33befa --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_NoAudioTrack.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1227051 - No audio track video shouldn't register the AudioChannelAgent</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_NoAudioTrack.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenMixedProcess.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenMixedProcess.html new file mode 100644 index 000000000..1248c1772 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenMixedProcess.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 776129</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;version=1.7" src="browserElement_OpenMixedProcess.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenNamed.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenNamed.html new file mode 100644 index 000000000..bbe12545c --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenNamed.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenNamed.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenTab.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenTab.html new file mode 100644 index 000000000..85b979bd0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenTab.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1144015 +--> +<head> + <title>Test for Bug 1144015</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1144015">Mozilla Bug 1144015</a> + +<script type="application/javascript;version=1.7" src="browserElement_OpenTab.js"> +</script> +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindow.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindow.html new file mode 100644 index 000000000..7c249792f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindow.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindow.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowDifferentOrigin.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowDifferentOrigin.html new file mode 100644 index 000000000..327ff8960 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowDifferentOrigin.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowDifferentOrigin.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowEmpty.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowEmpty.html new file mode 100644 index 000000000..03738de71 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowEmpty.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 1216937</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;version=1.7" src="browserElement_OpenWindowEmpty.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowInFrame.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowInFrame.html new file mode 100644 index 000000000..e2c02d4a9 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowInFrame.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowInFrame.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowRejected.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowRejected.html new file mode 100644 index 000000000..a96b378f6 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowRejected.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowRejected.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowRejected2.html b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowRejected2.html new file mode 100644 index 000000000..a96b378f6 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowRejected2.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowRejected.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Opensearch.html b/dom/browser-element/mochitest/test_browserElement_inproc_Opensearch.html new file mode 100644 index 000000000..23f21ed83 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Opensearch.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=883002 +--> +<head> + <title>Test for Bug 883002</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=883002">Mozilla Bug 883002</a> + +<script type="application/javascript;version=1.7" src="browserElement_Opensearch.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_PrivateBrowsing.html b/dom/browser-element/mochitest/test_browserElement_inproc_PrivateBrowsing.html new file mode 100644 index 000000000..0947fd7c7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_PrivateBrowsing.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=832700 +--> +<head> + <title>Test for Bug 832700</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=832700">Mozilla Bug 832700</a> + +<script type="application/javascript;version=1.7" src="browserElement_PrivateBrowsing.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_PromptCheck.html b/dom/browser-element/mochitest/test_browserElement_inproc_PromptCheck.html new file mode 100644 index 000000000..476c7e2c2 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_PromptCheck.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 741587</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741587">Mozilla Bug 741587</a> + +<script type="application/javascript;version=1.7" src="browserElement_PromptCheck.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_PromptConfirm.html b/dom/browser-element/mochitest/test_browserElement_inproc_PromptConfirm.html new file mode 100644 index 000000000..b29a52025 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_PromptConfirm.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 741587</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741587">Mozilla Bug 741587</a> + +<script type="application/javascript;version=1.7" src="browserElement_PromptConfirm.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Proxy.html b/dom/browser-element/mochitest/test_browserElement_inproc_Proxy.html new file mode 100644 index 000000000..05a416eee --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Proxy.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1196654 +--> +<head> + <title>Test for Bug 1196654</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196654">Mozilla Bug 1196654</a> + +<script type="application/javascript;version=1.7" src="browserElement_Proxy.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_PurgeHistory.html b/dom/browser-element/mochitest/test_browserElement_inproc_PurgeHistory.html new file mode 100644 index 000000000..1c052996c --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_PurgeHistory.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_PurgeHistory.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Reload.html b/dom/browser-element/mochitest/test_browserElement_inproc_Reload.html new file mode 100644 index 000000000..75b912b19 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Reload.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_Reload.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ReloadPostRequest.html b/dom/browser-element/mochitest/test_browserElement_inproc_ReloadPostRequest.html new file mode 100644 index 000000000..d26e7a0b5 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ReloadPostRequest.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_ReloadPostRequest.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_RemoveBrowserElement.html b/dom/browser-element/mochitest/test_browserElement_inproc_RemoveBrowserElement.html new file mode 100644 index 000000000..8ccbe09a7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_RemoveBrowserElement.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=787517 +--> +<head> + <title>Test for Bug 787517</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787517">Mozilla Bug 787517</a> + +<script type="application/javascript;version=1.7" src="browserElement_RemoveBrowserElement.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ScrollEvent.html b/dom/browser-element/mochitest/test_browserElement_inproc_ScrollEvent.html new file mode 100644 index 000000000..e87792243 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ScrollEvent.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=770847 +--> +<head> + <title>Test for Bug 770847</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=770847">Mozilla Bug 770847</a> + +<script type="application/javascript;version=1.7" src="browserElement_ScrollEvent.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html b/dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html new file mode 100644 index 000000000..ceaa6a40e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_SecurityChange.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_SendEvent.html b/dom/browser-element/mochitest/test_browserElement_inproc_SendEvent.html new file mode 100644 index 000000000..5eee91ed7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_SendEvent.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=774809 +--> +<head> + <title>Test for Bug 774809</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=774809">Mozilla Bug 774809</a> + +<script type="application/javascript;version=1.7" src="browserElement_SendEvent.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_SetInputMethodActive.html b/dom/browser-element/mochitest/test_browserElement_inproc_SetInputMethodActive.html new file mode 100644 index 000000000..957bf82fc --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_SetInputMethodActive.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 905573</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_SetInputMethodActive.js"> +</script> +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_SetVisible.html b/dom/browser-element/mochitest/test_browserElement_inproc_SetVisible.html new file mode 100644 index 000000000..6241d4b1f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_SetVisible.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=702880 +--> + <head> + <title>Test for Bug 702880</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753595">Mozilla Bug 702880</a> + +<script type="application/javascript;version=1.7" src='browserElement_SetVisible.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_SetVisibleFrames.html b/dom/browser-element/mochitest/test_browserElement_inproc_SetVisibleFrames.html new file mode 100644 index 000000000..8ae182285 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_SetVisibleFrames.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 762939</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_SetVisibleFrames.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_SetVisibleFrames2.html b/dom/browser-element/mochitest/test_browserElement_inproc_SetVisibleFrames2.html new file mode 100644 index 000000000..17d161a95 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_SetVisibleFrames2.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 762939</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_SetVisibleFrames2.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Stop.html b/dom/browser-element/mochitest/test_browserElement_inproc_Stop.html new file mode 100644 index 000000000..42c32da7e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Stop.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_Stop.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_TargetBlank.html b/dom/browser-element/mochitest/test_browserElement_inproc_TargetBlank.html new file mode 100644 index 000000000..916ed312b --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_TargetBlank.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for mozbrowser</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;version=1.7" src="browserElement_TargetBlank.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_TargetTop.html b/dom/browser-element/mochitest/test_browserElement_inproc_TargetTop.html new file mode 100644 index 000000000..6c99f1c21 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_TargetTop.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 771273</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;version=1.7" src="browserElement_TargetTop.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_ThemeColor.html b/dom/browser-element/mochitest/test_browserElement_inproc_ThemeColor.html new file mode 100644 index 000000000..4075ce58d --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_ThemeColor.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1013913 +--> +<head> + <title>Test for Bug 1013913</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013913">Mozilla Bug 1013913</a> + +<script type="application/javascript;version=1.7" src="browserElement_ThemeColor.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Titlechange.html b/dom/browser-element/mochitest/test_browserElement_inproc_Titlechange.html new file mode 100644 index 000000000..1fdde48c1 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Titlechange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=720157 +--> +<head> + <title>Test for Bug 720157</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720157">Mozilla Bug 720157</a> + +<script type="application/javascript;version=1.7" src='browserElement_Titlechange.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_TopBarrier.html b/dom/browser-element/mochitest/test_browserElement_inproc_TopBarrier.html new file mode 100644 index 000000000..c77a7a9ec --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_TopBarrier.html @@ -0,0 +1,21 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=725796 +--> +<head> + <title>Test for Bug 725796</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725796">Mozilla Bug 725796</a> + +<script type="application/javascript;version=1.7" src="browserElement_TopBarrier.js"> +</script> + +</body> +</html> + + diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_Viewmode.html b/dom/browser-element/mochitest/test_browserElement_inproc_Viewmode.html new file mode 100644 index 000000000..286dd3989 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_Viewmode.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1162844 +--> +<head> + <title>Test for Bug 1162844</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162844">Mozilla Bug 1162844</a> + +<script type="application/javascript;version=1.7" src="browserElement_Viewmode.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_VisibilityChange.html b/dom/browser-element/mochitest/test_browserElement_inproc_VisibilityChange.html new file mode 100644 index 000000000..ce4251a42 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_VisibilityChange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=868816 +--> +<head> + <title>Test for Bug 868816</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=868816">Mozilla Bug 868816</a> + +<script type="application/javascript;version=1.7" src='browserElement_VisibilityChange.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptions.html b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptions.html new file mode 100644 index 000000000..36479ee06 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptions.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 770239</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;version=1.7" src="browserElement_XFrameOptions.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsAllowFrom.html b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsAllowFrom.html new file mode 100644 index 000000000..801c7879f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsAllowFrom.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 690168</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;version=1.7" src="browserElement_XFrameOptionsAllowFrom.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsDeny.html b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsDeny.html new file mode 100644 index 000000000..edd91dbd7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsDeny.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 770239</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;version=1.7" src="browserElement_XFrameOptionsDeny.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsSameOrigin.html b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsSameOrigin.html new file mode 100644 index 000000000..e0ecbabc4 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_XFrameOptionsSameOrigin.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 770239</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;version=1.7" src="browserElement_XFrameOptionsSameOrigin.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html b/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html new file mode 100644 index 000000000..1252de5e5 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 1169633</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.8" + src="async.js"> +</script> +<script type="application/javascript;version=1.8" + src="browserElement_getWebManifest.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ActiveStateChange.html b/dom/browser-element/mochitest/test_browserElement_oop_ActiveStateChange.html new file mode 100644 index 000000000..4a14ad7cb --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ActiveStateChange.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test ActiveStateChangeOnChangingMutedOrVolume</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.7" src="browserElement_ActiveStateChange.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Alert.html b/dom/browser-element/mochitest/test_browserElement_oop_Alert.html new file mode 100644 index 000000000..03d03135d --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Alert.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 741587</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741587">Mozilla Bug 741587</a> + +<script type="application/javascript;version=1.7" src="browserElement_Alert.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_AlertInFrame.html b/dom/browser-element/mochitest/test_browserElement_oop_AlertInFrame.html new file mode 100644 index 000000000..d797a1a3a --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_AlertInFrame.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for iframe mozbrowser</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;version=1.7" src="browserElement_AlertInFrame.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_AudioChannel.html b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannel.html new file mode 100644 index 000000000..34909e904 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannel.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element audioChannel.</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;version=1.7" src="browserElement_AudioChannel.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_AudioChannelMutedByDefault.html b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannelMutedByDefault.html new file mode 100644 index 000000000..60bead59f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannelMutedByDefault.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1235535 - Audio Channel Muted-By-Default.</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;version=1.7" src="browserElement_AudioChannelMutedByDefault.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_AudioChannelSeeking.html b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannelSeeking.html new file mode 100644 index 000000000..54c3a1fb4 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannelSeeking.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1225425 - Do not unregister the AudioChannelAgent during seeking</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;version=1.7" src="browserElement_AudioChannelSeeking.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_AudioChannel_nested.html b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannel_nested.html new file mode 100644 index 000000000..d189a7ca4 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_AudioChannel_nested.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element audioChannel.</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;version=1.7" src="browserElement_AudioChannel_nested.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_AudioPlayback.html b/dom/browser-element/mochitest/test_browserElement_oop_AudioPlayback.html new file mode 100644 index 000000000..bb3a1c2d6 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_AudioPlayback.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1180824 +--> +<head> + <title>Test for Bug 1180824</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1180824">Mozilla Bug 1180824</a> + +<script type="application/javascript;version=1.7" src="browserElement_AudioPlayback.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Auth.html b/dom/browser-element/mochitest/test_browserElement_oop_Auth.html new file mode 100644 index 000000000..0dd60f8c6 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Auth.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 775464</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=775464">Mozilla Bug 775464</a> + +<script type="application/javascript;version=1.7" src="browserElement_Auth.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_BackForward.html b/dom/browser-element/mochitest/test_browserElement_oop_BackForward.html new file mode 100644 index 000000000..e5d753b5e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_BackForward.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_BackForward.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_BadScreenshot.html b/dom/browser-element/mochitest/test_browserElement_oop_BadScreenshot.html new file mode 100644 index 000000000..5713b512e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_BadScreenshot.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 800170</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;version=1.7" src="browserElement_BadScreenshot.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_BrowserWindowResize.html b/dom/browser-element/mochitest/test_browserElement_oop_BrowserWindowResize.html new file mode 100644 index 000000000..bcc86b872 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_BrowserWindowResize.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 891763</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;version=1.7" src="browserElement_BrowserWindowResize.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Close.html b/dom/browser-element/mochitest/test_browserElement_oop_Close.html new file mode 100644 index 000000000..76d203f9d --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Close.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=757182 +--> +<head> + <title>Test for Bug 757182</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=757182">Mozilla Bug 757182</a> + +<script type="application/javascript;version=1.7" src="browserElement_Close.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_CloseFromOpener.html b/dom/browser-element/mochitest/test_browserElement_oop_CloseFromOpener.html new file mode 100644 index 000000000..3c7ee4d87 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_CloseFromOpener.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=757182 +--> +<head> + <title>Test for Bug 757182</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=757182">Mozilla Bug 757182</a> + +<script type="application/javascript;version=1.7" src="browserElement_CloseFromOpener.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ContextmenuEvents.html b/dom/browser-element/mochitest/test_browserElement_oop_ContextmenuEvents.html new file mode 100644 index 000000000..a43f7dbef --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ContextmenuEvents.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Contextmenu Events</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;version=1.7" src="browserElement_ContextmenuEvents.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_CookiesNotThirdParty.html b/dom/browser-element/mochitest/test_browserElement_oop_CookiesNotThirdParty.html new file mode 100644 index 000000000..37ea16fb0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_CookiesNotThirdParty.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 806127</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;version=1.7" src="browserElement_CookiesNotThirdParty.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_CopyPaste.html b/dom/browser-element/mochitest/test_browserElement_oop_CopyPaste.html new file mode 100644 index 000000000..892245d4f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_CopyPaste.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=987040 +--> +<head> + <title>Test for Bug 987040</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=987040">Mozilla Bug 987040</a> + +<script type="application/javascript;version=1.7" src="browserElement_CopyPaste.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_DOMRequestError.html b/dom/browser-element/mochitest/test_browserElement_oop_DOMRequestError.html new file mode 100644 index 000000000..48d404cc3 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_DOMRequestError.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=787519 +--> +<head> + <title>Test for Bug 787519</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787519">Mozilla Bug 787519</a> + +<script type="application/javascript;version=1.7" src='browserElement_DOMRequestError.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_DataURI.html b/dom/browser-element/mochitest/test_browserElement_oop_DataURI.html new file mode 100644 index 000000000..2ceb49cd0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_DataURI.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=720157 +--> +<head> + <title>Test for Bug 720157</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720157">Mozilla Bug 720157</a> + +<script type='application/javascript;version=1.7' src='browserElement_DataURI.js'></script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_DocumentFirstPaint.html b/dom/browser-element/mochitest/test_browserElement_oop_DocumentFirstPaint.html new file mode 100644 index 000000000..6667a76eb --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_DocumentFirstPaint.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 829486</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;version=1.7" src="browserElement_DocumentFirstPaint.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Download.html b/dom/browser-element/mochitest/test_browserElement_oop_Download.html new file mode 100644 index 000000000..c2e5e2ed3 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Download.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 983747</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;version=1.7" src="browserElement_Download.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ErrorSecurity.html b/dom/browser-element/mochitest/test_browserElement_oop_ErrorSecurity.html new file mode 100644 index 000000000..318d29831 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ErrorSecurity.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for mozbrowser</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;version=1.7" src="browserElement_ErrorSecurity.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ExecuteScript.html b/dom/browser-element/mochitest/test_browserElement_oop_ExecuteScript.html new file mode 100644 index 000000000..e3bbabfa0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ExecuteScript.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1174733 +--> +<head> + <title>Test for Bug 1163961</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1174733">Mozilla Bug 1174733</a> + +<script type="application/javascript;version=1.7" src="browserElement_ExecuteScript.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html b/dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html new file mode 100644 index 000000000..089e5db44 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=795317 +--> +<head> + <title>Test for Bug 795317</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795317">Mozilla Bug 795317</a> + +<script type="application/javascript;version1.7" src="browserElement_ExposableURI.js"></script> + +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Find.html b/dom/browser-element/mochitest/test_browserElement_oop_Find.html new file mode 100644 index 000000000..e0333a6bb --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Find.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1163961 +--> +<head> + <title>Test for Bug 1163961</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a> + +<script type="application/javascript;version=1.7" src="browserElement_Find.js"> +</script> +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_oop_FirstPaint.html b/dom/browser-element/mochitest/test_browserElement_oop_FirstPaint.html new file mode 100644 index 000000000..ee013860c --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_FirstPaint.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 787378</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;version=1.7" src="browserElement_FirstPaint.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ForwardName.html b/dom/browser-element/mochitest/test_browserElement_oop_ForwardName.html new file mode 100644 index 000000000..f24691ff1 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ForwardName.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 781320</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;version=1.7" src="browserElement_ForwardName.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_FrameWrongURI.html b/dom/browser-element/mochitest/test_browserElement_oop_FrameWrongURI.html new file mode 100644 index 000000000..f0e6e6c20 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_FrameWrongURI.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_FrameWrongURI.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_GetContentDimensions.html b/dom/browser-element/mochitest/test_browserElement_oop_GetContentDimensions.html new file mode 100644 index 000000000..067615c1b --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_GetContentDimensions.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_GetContentDimensions.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_GetScreenshot.html b/dom/browser-element/mochitest/test_browserElement_oop_GetScreenshot.html new file mode 100644 index 000000000..81d3e1993 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_GetScreenshot.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=753595 +--> +<head> + <title>Test for Bug 753595</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753595">Mozilla Bug 753595</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=878003">Mozilla Bug 878003</a> + +<script type="application/javascript;version=1.7" src='browserElement_GetScreenshot.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_GetScreenshotDppx.html b/dom/browser-element/mochitest/test_browserElement_oop_GetScreenshotDppx.html new file mode 100644 index 000000000..9d30fc541 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_GetScreenshotDppx.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=959066 +--> +<head> + <title>Test for Bug 959066</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=959066">Mozilla Bug 959066</a> + +<script type="application/javascript;version=1.7" src='browserElement_GetScreenshotDppx.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Iconchange.html b/dom/browser-element/mochitest/test_browserElement_oop_Iconchange.html new file mode 100644 index 000000000..2f17287de --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Iconchange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=719461 +--> +<head> + <title>Test for Bug 719461</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=719461">Mozilla Bug 719461</a> + +<script type="application/javascript;version=1.7" src="browserElement_Iconchange.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html b/dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html new file mode 100644 index 000000000..c6daf805e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=710231 +--> +<head> + <title>Test for Bug 710231</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a> + +<script type="application/javascript;version1.7" src="browserElement_LoadEvents.js"></script> + +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Manifestchange.html b/dom/browser-element/mochitest/test_browserElement_oop_Manifestchange.html new file mode 100644 index 000000000..64200bd48 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Manifestchange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=982800 +--> +<head> + <title>Test for Bug 982800</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982800">Mozilla Bug 982800</a> + +<script type="application/javascript;version=1.7" src="browserElement_Manifestchange.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Metachange.html b/dom/browser-element/mochitest/test_browserElement_oop_Metachange.html new file mode 100644 index 000000000..d799a52e4 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Metachange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=962626 +--> +<head> + <title>Test for Bug 962626</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=962626">Mozilla Bug 962626</a> + +<script type="application/javascript;version=1.7" src="browserElement_Metachange.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_NextPaint.html b/dom/browser-element/mochitest/test_browserElement_oop_NextPaint.html new file mode 100644 index 000000000..8144819f2 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_NextPaint.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 808231</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;version=1.7" src="browserElement_NextPaint.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_NoAudioTrack.html b/dom/browser-element/mochitest/test_browserElement_oop_NoAudioTrack.html new file mode 100644 index 000000000..90782bc63 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_NoAudioTrack.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1227051 - No audio track video shouldn't register the AudioChannelAgent</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;version=1.7" src="browserElement_NoAudioTrack.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenMixedProcess.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenMixedProcess.html new file mode 100644 index 000000000..cefe06c3e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenMixedProcess.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 776129</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;version=1.7" src="browserElement_OpenMixedProcess.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenNamed.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenNamed.html new file mode 100644 index 000000000..bbe12545c --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenNamed.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenNamed.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenTab.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenTab.html new file mode 100644 index 000000000..85b979bd0 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenTab.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1144015 +--> +<head> + <title>Test for Bug 1144015</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1144015">Mozilla Bug 1144015</a> + +<script type="application/javascript;version=1.7" src="browserElement_OpenTab.js"> +</script> +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenWindow.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindow.html new file mode 100644 index 000000000..7c249792f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindow.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindow.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowDifferentOrigin.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowDifferentOrigin.html new file mode 100644 index 000000000..327ff8960 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowDifferentOrigin.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowDifferentOrigin.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowEmpty.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowEmpty.html new file mode 100644 index 000000000..03738de71 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowEmpty.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 1216937</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;version=1.7" src="browserElement_OpenWindowEmpty.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowInFrame.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowInFrame.html new file mode 100644 index 000000000..e2c02d4a9 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowInFrame.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowInFrame.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected.html new file mode 100644 index 000000000..a96b378f6 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowRejected.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected2.html b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected2.html new file mode 100644 index 000000000..a96b378f6 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected2.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_OpenWindowRejected.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Opensearch.html b/dom/browser-element/mochitest/test_browserElement_oop_Opensearch.html new file mode 100644 index 000000000..23f21ed83 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Opensearch.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=883002 +--> +<head> + <title>Test for Bug 883002</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=883002">Mozilla Bug 883002</a> + +<script type="application/javascript;version=1.7" src="browserElement_Opensearch.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_PrivateBrowsing.html b/dom/browser-element/mochitest/test_browserElement_oop_PrivateBrowsing.html new file mode 100644 index 000000000..0947fd7c7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_PrivateBrowsing.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=832700 +--> +<head> + <title>Test for Bug 832700</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=832700">Mozilla Bug 832700</a> + +<script type="application/javascript;version=1.7" src="browserElement_PrivateBrowsing.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_PromptCheck.html b/dom/browser-element/mochitest/test_browserElement_oop_PromptCheck.html new file mode 100644 index 000000000..476c7e2c2 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_PromptCheck.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 741587</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741587">Mozilla Bug 741587</a> + +<script type="application/javascript;version=1.7" src="browserElement_PromptCheck.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_PromptConfirm.html b/dom/browser-element/mochitest/test_browserElement_oop_PromptConfirm.html new file mode 100644 index 000000000..b29a52025 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_PromptConfirm.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741587 +--> +<head> + <title>Test for Bug 741587</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741587">Mozilla Bug 741587</a> + +<script type="application/javascript;version=1.7" src="browserElement_PromptConfirm.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Proxy.html b/dom/browser-element/mochitest/test_browserElement_oop_Proxy.html new file mode 100644 index 000000000..05a416eee --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Proxy.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1196654 +--> +<head> + <title>Test for Bug 1196654</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196654">Mozilla Bug 1196654</a> + +<script type="application/javascript;version=1.7" src="browserElement_Proxy.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_PurgeHistory.html b/dom/browser-element/mochitest/test_browserElement_oop_PurgeHistory.html new file mode 100644 index 000000000..cf606fd80 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_PurgeHistory.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_PurgeHistory.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Reload.html b/dom/browser-element/mochitest/test_browserElement_oop_Reload.html new file mode 100644 index 000000000..75b912b19 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Reload.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_Reload.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ReloadPostRequest.html b/dom/browser-element/mochitest/test_browserElement_oop_ReloadPostRequest.html new file mode 100644 index 000000000..d26e7a0b5 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ReloadPostRequest.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_ReloadPostRequest.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_RemoveBrowserElement.html b/dom/browser-element/mochitest/test_browserElement_oop_RemoveBrowserElement.html new file mode 100644 index 000000000..8ccbe09a7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_RemoveBrowserElement.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=787517 +--> +<head> + <title>Test for Bug 787517</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787517">Mozilla Bug 787517</a> + +<script type="application/javascript;version=1.7" src="browserElement_RemoveBrowserElement.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ScrollEvent.html b/dom/browser-element/mochitest/test_browserElement_oop_ScrollEvent.html new file mode 100644 index 000000000..e87792243 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ScrollEvent.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=770847 +--> +<head> + <title>Test for Bug 770847</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=770847">Mozilla Bug 770847</a> + +<script type="application/javascript;version=1.7" src="browserElement_ScrollEvent.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html b/dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html new file mode 100644 index 000000000..ceaa6a40e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_SecurityChange.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_SendEvent.html b/dom/browser-element/mochitest/test_browserElement_oop_SendEvent.html new file mode 100644 index 000000000..38d16a9da --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_SendEvent.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=774809 +--> +<head> + <title>Test for Bug 774809</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=774809">Mozilla Bug 774809</a> + +<script type="application/javascript;version=1.7" src="browserElement_SendEvent.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_SetInputMethodActive.html b/dom/browser-element/mochitest/test_browserElement_oop_SetInputMethodActive.html new file mode 100644 index 000000000..5d4b45bc8 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_SetInputMethodActive.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 905573</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;version=1.7" src="browserElement_SetInputMethodActive.js"> +</script> +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_oop_SetVisible.html b/dom/browser-element/mochitest/test_browserElement_oop_SetVisible.html new file mode 100644 index 000000000..a2220d1b3 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_SetVisible.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=702880 +--> + <head> + <title>Test for Bug 702880</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753595">Mozilla Bug 702880</a> + +<script type="application/javascript;version=1.7" src='browserElement_SetVisible.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_SetVisibleFrames.html b/dom/browser-element/mochitest/test_browserElement_oop_SetVisibleFrames.html new file mode 100644 index 000000000..b6477c870 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_SetVisibleFrames.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 762939</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;version=1.7" src="browserElement_SetVisibleFrames.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_SetVisibleFrames2.html b/dom/browser-element/mochitest/test_browserElement_oop_SetVisibleFrames2.html new file mode 100644 index 000000000..108080f50 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_SetVisibleFrames2.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 762939</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;version=1.7" src="browserElement_SetVisibleFrames2.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Stop.html b/dom/browser-element/mochitest/test_browserElement_oop_Stop.html new file mode 100644 index 000000000..3425944e8 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Stop.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test of browser element.</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;version=1.7" src="browserElement_Stop.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_TargetBlank.html b/dom/browser-element/mochitest/test_browserElement_oop_TargetBlank.html new file mode 100644 index 000000000..916ed312b --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_TargetBlank.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for mozbrowser</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;version=1.7" src="browserElement_TargetBlank.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_TargetTop.html b/dom/browser-element/mochitest/test_browserElement_oop_TargetTop.html new file mode 100644 index 000000000..6c99f1c21 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_TargetTop.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 771273</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;version=1.7" src="browserElement_TargetTop.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_ThemeColor.html b/dom/browser-element/mochitest/test_browserElement_oop_ThemeColor.html new file mode 100644 index 000000000..4075ce58d --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_ThemeColor.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1013913 +--> +<head> + <title>Test for Bug 1013913</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013913">Mozilla Bug 1013913</a> + +<script type="application/javascript;version=1.7" src="browserElement_ThemeColor.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Titlechange.html b/dom/browser-element/mochitest/test_browserElement_oop_Titlechange.html new file mode 100644 index 000000000..1fdde48c1 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Titlechange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=720157 +--> +<head> + <title>Test for Bug 720157</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720157">Mozilla Bug 720157</a> + +<script type="application/javascript;version=1.7" src='browserElement_Titlechange.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_TopBarrier.html b/dom/browser-element/mochitest/test_browserElement_oop_TopBarrier.html new file mode 100644 index 000000000..8756b4455 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_TopBarrier.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=725796 +--> +<head> + <title>Test for Bug 725796</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725796">Mozilla Bug 725796</a> + +<script type="application/javascript;version=1.7" src="browserElement_TopBarrier.js"> +</script> + +</body> +</html> + diff --git a/dom/browser-element/mochitest/test_browserElement_oop_Viewmode.html b/dom/browser-element/mochitest/test_browserElement_oop_Viewmode.html new file mode 100644 index 000000000..286dd3989 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_Viewmode.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1162844 +--> +<head> + <title>Test for Bug 1162844</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162844">Mozilla Bug 1162844</a> + +<script type="application/javascript;version=1.7" src="browserElement_Viewmode.js"> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_VisibilityChange.html b/dom/browser-element/mochitest/test_browserElement_oop_VisibilityChange.html new file mode 100644 index 000000000..546882c1c --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_VisibilityChange.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=868816 +--> +<head> + <title>Test for Bug 868816</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> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=868816">Mozilla Bug 868816</a> + +<script type="application/javascript;version=1.7" src='browserElement_VisibilityChange.js'> +</script> + +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptions.html b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptions.html new file mode 100644 index 000000000..36479ee06 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptions.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 770239</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;version=1.7" src="browserElement_XFrameOptions.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsAllowFrom.html b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsAllowFrom.html new file mode 100644 index 000000000..801c7879f --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsAllowFrom.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 690168</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;version=1.7" src="browserElement_XFrameOptionsAllowFrom.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsDeny.html b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsDeny.html new file mode 100644 index 000000000..edd91dbd7 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsDeny.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 770239</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;version=1.7" src="browserElement_XFrameOptionsDeny.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsSameOrigin.html b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsSameOrigin.html new file mode 100644 index 000000000..e0ecbabc4 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_XFrameOptionsSameOrigin.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 770239</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;version=1.7" src="browserElement_XFrameOptionsSameOrigin.js"> +</script> +</body> +</html>
\ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html b/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html new file mode 100644 index 000000000..4ee13d924 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 1169633</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/dom/browser-element/mochitest/browserElementTestHelpers.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<script type="application/javascript;version=1.8" + src="async.js"></script> +<script type="application/javascript;version=1.8" + src="browserElement_getWebManifest.js"> +</script> +</body> +</html> diff --git a/dom/browser-element/moz.build b/dom/browser-element/moz.build new file mode 100644 index 000000000..0b00a2e06 --- /dev/null +++ b/dom/browser-element/moz.build @@ -0,0 +1,60 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +EXPORTS.mozilla += [ + 'BrowserElementParent.h', +] + +EXPORTS.mozilla.dom += [ + 'BrowserElementAudioChannel.h', +] + +SOURCES += [ + 'BrowserElementAudioChannel.cpp', + 'BrowserElementParent.cpp', +] + +XPIDL_SOURCES += [ + 'nsIBrowserElementAPI.idl', +] + +XPIDL_MODULE = 'browser-element' + +EXTRA_COMPONENTS += [ + 'BrowserElementParent.js', + 'BrowserElementParent.manifest', + 'BrowserElementProxy.js', + 'BrowserElementProxy.manifest', +] + +EXTRA_JS_MODULES += [ + 'BrowserElementPromptService.jsm', +] + +LOCAL_INCLUDES += [ + '/dom/html', +] + +include('/ipc/chromium/chromium-config.mozbuild') + +FINAL_LIBRARY = 'xul' + +LOCAL_INCLUDES += [ + '/dom/', + '/dom/base', + '/dom/ipc', +] + +MOCHITEST_MANIFESTS += [ + 'mochitest/mochitest-oop.ini', + 'mochitest/mochitest.ini', + 'mochitest/priority/mochitest.ini', +] + +MOCHITEST_CHROME_MANIFESTS += [ + 'mochitest/chrome.ini', + 'mochitest/priority/chrome.ini', +] diff --git a/dom/browser-element/nsIBrowserElementAPI.idl b/dom/browser-element/nsIBrowserElementAPI.idl new file mode 100644 index 000000000..0833d53b0 --- /dev/null +++ b/dom/browser-element/nsIBrowserElementAPI.idl @@ -0,0 +1,112 @@ +/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "nsISupports.idl" + +interface nsIDOMDOMRequest; +interface nsIFrameLoader; + +[scriptable, function, uuid(00d0e19d-bd67-491f-8e85-b9905224d3bb)] +interface nsIBrowserElementNextPaintListener : nsISupports +{ + void recvNextPaint(); +}; + +%{C++ +#define BROWSER_ELEMENT_API_CONTRACTID "@mozilla.org/dom/browser-element-api;1" +#define BROWSER_ELEMENT_API_CID \ + { 0x651db7e3, 0x1734, 0x4536, \ + { 0xb1, 0x5a, 0x5b, 0x3a, 0xe6, 0x44, 0x13, 0x4c } } +%} + +/** + * Interface to the BrowserElementParent implementation. All methods + * but setFrameLoader throw when the remote process is dead. + */ +[scriptable, uuid(57758c10-6036-11e5-a837-0800200c9a66)] +interface nsIBrowserElementAPI : nsISupports +{ + const long FIND_CASE_SENSITIVE = 0; + const long FIND_CASE_INSENSITIVE = 1; + + const long FIND_FORWARD = 0; + const long FIND_BACKWARD = 1; + + /** + * Notify frame scripts that support the API to destroy. + */ + void destroyFrameScripts(); + + void setFrameLoader(in nsIFrameLoader frameLoader); + + void setVisible(in boolean visible); + nsIDOMDOMRequest getVisible(); + void setActive(in boolean active); + boolean getActive(); + + void sendMouseEvent(in DOMString type, + in uint32_t x, + in uint32_t y, + in uint32_t button, + in uint32_t clickCount, + in uint32_t mifiers); + void sendTouchEvent(in DOMString aType, + [const, array, size_is(count)] in uint32_t aIdentifiers, + [const, array, size_is(count)] in int32_t aXs, + [const, array, size_is(count)] in int32_t aYs, + [const, array, size_is(count)] in uint32_t aRxs, + [const, array, size_is(count)] in uint32_t aRys, + [const, array, size_is(count)] in float aRotationAngles, + [const, array, size_is(count)] in float aForces, + in uint32_t count, + in long aModifiers); + void goBack(); + void goForward(); + void reload(in boolean hardReload); + void stop(); + nsIDOMDOMRequest download(in DOMString url, + [optional] in jsval options); + nsIDOMDOMRequest purgeHistory(); + nsIDOMDOMRequest getScreenshot(in uint32_t width, + in uint32_t height, + [optional] in DOMString mimeType); + void zoom(in float zoom); + nsIDOMDOMRequest getCanGoBack(); + nsIDOMDOMRequest getCanGoForward(); + nsIDOMDOMRequest getContentDimensions(); + + void findAll(in DOMString searchString, in long caseSensitivity); + void findNext(in long direction); + void clearMatch(); + + void mute(); + void unmute(); + nsIDOMDOMRequest getMuted(); + + void setVolume(in float volume); + nsIDOMDOMRequest getVolume(); + + void addNextPaintListener(in nsIBrowserElementNextPaintListener listener); + void removeNextPaintListener(in nsIBrowserElementNextPaintListener listener); + + nsIDOMDOMRequest setInputMethodActive(in boolean isActive); + + nsIDOMDOMRequest getAudioChannelVolume(in uint32_t audioChannel); + nsIDOMDOMRequest setAudioChannelVolume(in uint32_t audioChannel, in float volume); + + nsIDOMDOMRequest getAudioChannelMuted(in uint32_t audioChannel); + nsIDOMDOMRequest setAudioChannelMuted(in uint32_t audioChannel, in bool muted); + + nsIDOMDOMRequest isAudioChannelActive(in uint32_t audioChannel); + + nsIDOMDOMRequest executeScript(in DOMString script, in jsval options); + + /** + * Returns an object that represents a Web Manifest: + * http://w3c.github.io/manifest/ + */ + nsIDOMDOMRequest getWebManifest(); +}; |