import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1212148 - Outline DialogValueHolder::Get() and create the variant directly. r=bz (1f3eb24a70)
- Bug 1210591, part 1 - Use nsVariantCC in various places. r=smaug (960ec7f9d3)
- Bug 1210591, part 2 - Cycle collect DataTransfer::mItems. r=smaug (3bc922fd42)
- Bug 931283, part 1 - Rename nsVariant to nsVariantBase. r=froydnj (1ba409004e)
- Bug 931283, part 2 - Split out nsVariant into a subclass. r=froydnj (6fc4012db0)
- Bug 931283, part 3 - Implement a cycle collected version of nsVariant. r=froydnj (9dd0e97d28)
- Bug 1208815 - Use the legacy opt-out in GetMozSourceNode to avoid crashes. r=bholley (b8aaa945fd)
- Bug 1217614 - Remove nsIDOMDataTransfer::mozGetDataAt and refactor associated code. r=bz (6a5a403776)
- Bug 1197002 - Use channel->Open2() in editor/libeditor/nsHTMLDataTransfer.cpp (r=sicking) (4995576e25)
- Bug 1169268 - Don't crash when pasting files. r=ndeakin (b52b5e9971)
- Bug 1156062 part 1b - Convert some callers of nsEditor::SplitNodeDeep; r=ehsan (c0ecbdf8ec)
- Bug 1156062 part 1c - Convert remaining callers of nsEditor::SplitNodeDeep; r=ehsan (e9cb446bef)
- Bug 1156062 part 1d - Clean up nsEditor::SplitNodeDeep; r=ehsan (d8513a605c)
- Bug 1156062 part 2 - Make GetBlockNodeParent and GetEnclosingTable return regular pointers; r=ehsan (8e80c4c53c)
- Bug 1156062 part 3 - New helper nsHTMLEditor::GetBlock; r=ehsan (9466c926f3)
- Bug 1145395 - Call nsINode::Length directly in nsHTMLEditor::CreateDOMFragmentFromPaste; r=ehsan (5b9d9b208c)
- Bug 1152229 Define FnLock as a KeyboardEvent.code value r=smaug (0f0ba16ba2)
- Bug 1192774 - Rename nsOuterWindowProxy::GetWindow to GetOuterWindow and add an assertion; r=khuey (5bbad7f98a)
- Bug 920734 - Part 1: Implement window.orientation and window.onorientationchange. r=baku (3f350de924)
- Bug 920734 - Part 2: Update tests to avoid using orientation as variable name. r=seth (a5c98bcc6f)
- Bug 1216072 - Pass aCallerIsChrome in more places. r=bz Bug 1215398 - Hoist the IsCallerChrome call in CanMoveResizeWindows to the script-only entry points. r=bz (3ff7d3d1a2)
- Bug 1107443. Make WindowProxy throw if you attempt to explicitly define a non-configurable property. r=peterv (d4659731fe)
- Bug 1196317 - Optimize CallbackObject::mCreationStack out from cycle collection graph when possible, r=mccr8 (6221298ec7)
- Bug 1184058 - AudioChannelAgent should be muted when used without a proper window object. r=alwu (3bc66c7727)
- Bug 1196361 - Remove the media.useAudioChannelService pref; r=baku (ba976d4402)
- Bug 1190040 - Part 2: Teach the audio channel service how to not notify audio-playback, and do that when a media element has no audio track; r=padenot (b163cbd6e2)
- Bug 1180940 - Changed return type of AudioDestinationNode::CreateAudioChannelAgent method to return errors, if any methods that it calls fail. Added code to handle the return value in AudioContext::Init(), and its callers. r=baku (03671277dc)
- Bug 1183304 - Unregister the actor when unlinked by CC. r=ehsan (ad0a3a7050)
- Bug 1191814 - WebSpeech synthesis API and AudioChannelService, r=eeejay (2140326485)
- Bug 1043165 - Part 1: Add TelephonyCall.disconnectedReason (webidl). r=hsinyi (a08a2e3b19)
- Bug 1043165 - Part 2: Add TelephonyCall.disconnectedReason (dom). r=hsinyi (1403f942fd)
- Bug 1043165 - Part 3: Add TelephonyCall.disconnectedReason (ril). r=hsinyi (cdb3991ed0)
- Bug 1043165 - Part 4: Update test cases. r=hsinyi (aa3f784b07)
- Bug 1131047 - Part 1: Obsolete some events (WebIDL). r=hsinyi (64e098a773)
- Bug 1131047 - Part 2: Obsolete some events (DOM). r=aknow (75caf5fa03)
- Bug 1161403 - Part 1: Deprecate internal states. r=aknow (dfd955bf8b)
- Bug 1161403 - Part 2: A new testcase. r=aknow (4798f3ec44)
- Bug 1129882 - create agent in telephony object. r=baku, r=hsinyi (1d7e7e44a4)
- Bug 1129882 - add mozInterrupt in telephony object. r=baku (f52465229b)
- Bug 1211511 - AudioChannelAgent::NotifyStartedPlaying and NotifyStoppedPlaying should use the same level of playback notification, r=roc (a73b0fda70)
- Bug 1187204 - AudioChannelService must exist before calling IsAudioChannelMutedByDefault(), r=alwu (665d082d4f)
- Bug 1089526 - Correct function name. r=baku (0706ced01f)
- Bug 1183925 - Part 1: Clean up the SpeakerManagerService shutdown; r=baku (7aefa655d5)
- Bug 1223734 - AudioChannelService should not be re-initialized after the XPCOM shutdown, r=smaug (1e35895d8d)
- Bug 1223734 - Add crashtest. r=baku (cfb753dcf2)
- Bug 1151992 - Use call state to decide the usages of output device. r=baku (37ea21895f)
- Bug 1215684 - Shut down AudioChannelService in the child process. r=mccr8 (389b137630)
- Bug 1183033 - Don't mute the system channel type. r=baku (da88f69119)
- Bug 1218396 - By default window-less AudioChannelAgents should be muted, r=alwu (3a74b6e8e0)
- Bug 1222902 - Create log system for the AudioChannel. r=baku. (4734efd27b)
- var-let (9849b3f3a9)
- Bug 1138354 - Add proxy authencation info for 'mozbrowserusernameandpasswordrequired' event. r=mayhemer (e1717f0113)
- Bug 1195801 - part 2: Tests for getStructuredData. r=kanru (221d9b4fa8)
- Bug 1169633 - [Browser API] getWebManifest(). r=kanru, r=bholley (904c043d16)
- Bug 1206581 - Implement notifyChannel() on AudioChannel API. r=kanru, r=baku. (42554161e7)
- Bug 1196654 - navigator.mozBrowserElementProxy for access Browser API methods from the embedded, r=kanru, sr=sicking (878b701d4b)
- Bug 1214133 - Preload ExtensionContent.jsm to get rid of the overhead. r=fabrice (50f6584735)
- Bug 1212321 - Stop painting on app launch. r=fabrice (a4cadc9577)
- Bug 1203068 - Add system type into kMozAudioChannelAttributeTable. r=baku (c908fef580)
- Bug 1208353 - Fix -Wshadow warnings in dom/audiochannel. r=padenot (85193d75a2)
- Bug 1184970 - Remove unused struct in AudioChannelService, r=ehsan (f0511a942b)
- Bug 1214491 - Rejigger entry points for nsGlobalWindow::Close. r=bz (6eccbffe1f)
- Bug 1212360. Split up the MozStorageChanged event into separate events for sessionstorage and localstorage. r=khuey (ff0047fe22)
- Bug 1162013. Process the Promise queue between adjacent setTimeout callback invocations when we're going through the callback list without returning to the event loop. r=smaug (f4966fa41e)
- Bug 1214491 - Remove CanCallerAccess check for XPIDL version of nsGlobalWindow::AddEventListener. r=bz (5bb993e1ea)
- Bug 1181176 - Pass along x and y position for context menus on Graphene. r=fabrice (652b528a92)
- Bug 1211481 - Expose screenX and screenY to context menu events. r=fabrice (e9679e9d6c)
- Bug 952456 - Part 2: Support copy image in BrowserElement. r=kchen (f91eb8ae95)
- Bug 952456 - Part 3: Enable test_copyimage.html on gonk/cocoa r=fabrice (be0d20fd99)
- Bug 1121463 - Support copy link on context menu. r=kanru (a981b7e05c)
- Backout c7c68c4389d6 (bug 1125713) for gaia app startup regression r=me (ed1d13993f)
- Bug 1178484 - Part 2: Regenerate gecko's in-tree parser. r=hsivone (42d5b50cf1)
- Bug 1164123 - Add support for a theme-group meta to make theme-color"themable". r=fabrice (40757cf461)
- Bug 1178484 - Part 4: Fire metachange event when a <meta> tag has Open Graph data. r=kanru (111cf1c43f)
- Bug 1178484 - Part 5: Test for metachange event when Open Graph property is loaded. r=kanru (0b464de5de)
- Bug 1156615 - (Browser API) ctrl/cmd/middle-click doesn't work if <a> element has children. r=kchen (673a7031f9)
- Bug 1210265 - Add a pref toggle for copying/pasting only plain text on B2G. r=timdream (4fbbad858e)
- Bug 1198522 - Add a flag to make sure customized menu is added. r=timdream, r=kanru (81e611997d)
- Bug 1168658 - Enable tracking protection in b2g r=francois (fc04c160ae)
- Bug 1189494 - Pass tracking information to BrowserElement's mozbrowsersecuritychange event. r=fabrice (bb24e94178)
- Bug 1170644 - Fix forced reflow in BrowserElementChildPreload. r=bz (73078e79fa)
- Bug 1178069 - Check devices capability before enable use of vp8 hardware acceleration using android.media.MediaCodecList and android.media.MediaCodecInfo r=jrmuizel (883351b87c)
- Bug 1164036 - Add an xpcshell test for graphics blocklist versioning. r=kats (c846c5b142)
- Bug 1183725 - Windows 10 not recognized in downloadable blocklist. r=bas (6a07f03ea3)
- Bug 1191404 - Update the comments to avoid confusion about what happens with blocklisting when the OS is unknown. No code change. r=milan (40bec16ce6)
- Bug 1215892 - Fix clang's -Wimplicit-fallthrough warnings in gfx. r=BenWa (83d160740c)
- var/const crashreporter (c9e5ccbb70)
- Bug 1225233 - Make MovableCellHasher a public interface, usable by embedders; r=jonco (603b00a836)
- Bug 1214508: SharedStubs - Part 1: Move the getprop stubs in to shared stub files, r=jandem (7cddae3b9e)
- Bug 1214508: SharedStubs - Part 2: Adjust the getprop stubs to report which engine they use, r=jandem (03ae066cad)
- Bug 1214508: SharedStubs - Part 3: Enable the getprop stubs in ionmonkey, r=jandem (e002db87c2)
- Bug 1214508: SharedStubs - Part 4: Make sure the frame pushed are set correctly for ion vmcalls, r=jandem (6238ed03c4)
- Bug 1214508: SharedStubs - Part 5: Fix ion vmcalls in shared stub, r=jandem (5a914ccfe6)
- Bug 1214508: SharedStubs - Part 6: Move the monitor stubs in to shared stub files, r=jandem (6f03cfaa1f)
- Bug 1214508: SharedStubs - Part 7: Adjust the getprop stubs to report which engine they use, r=jandem (e3849fde89)
- Bug 1214508: SharedStubs - Part 8: Dont sync for the decompiler in ion, r=jandem (7fe1a01bca)
- Bug 1214508: SharedStubs - Fix bustage in arm64, r=bustage on CLOSED TREE (0b60ba5974)
- Bug 1214508: SharedStubs - fix bustage, r=bustage (968a63544d)
- Bug 1212624 - Make WeakMapBase be a LinkedListElement, r=Waldo (744bb6eb8d)
- Bug 1223519 - Remove unused rekeying logic from WeakMap; r=sfink (3a4fe3b5df)
- Bug 1219288 - Ensure module environment object is not extensible and contains only non-configurable properties r=shu (0b9ac212b9)
This commit is contained in:
2023-01-05 23:57:13 +08:00
parent 9938fac30a
commit 136569692c
235 changed files with 9225 additions and 6033 deletions
+41 -2
View File
@@ -347,6 +347,47 @@ pref("dom.w3c_touch_events.enabled", 1);
pref("dom.w3c_touch_events.safetyX", 0); // escape borders in units of 1/240"
pref("dom.w3c_touch_events.safetyY", 120); // escape borders in units of 1/240"
#ifdef MOZ_SAFE_BROWSING
pref("browser.safebrowsing.enabled", true);
// Prevent loading of pages identified as malware
pref("browser.safebrowsing.malware.enabled", true);
pref("browser.safebrowsing.downloads.enabled", true);
pref("browser.safebrowsing.downloads.remote.enabled", true);
pref("browser.safebrowsing.downloads.remote.timeout_ms", 10000);
pref("browser.safebrowsing.debug", false);
pref("browser.safebrowsing.provider.google.lists", "goog-badbinurl-shavar,goog-downloadwhite-digest256,goog-phish-shavar,goog-malware-shavar,goog-unwanted-shavar");
pref("browser.safebrowsing.provider.google.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
pref("browser.safebrowsing.provider.google.gethashURL", "https://safebrowsing.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
pref("browser.safebrowsing.provider.google.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
pref("browser.safebrowsing.provider.google.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
pref("browser.safebrowsing.reportPhishMistakeURL", "https://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%&url=");
pref("browser.safebrowsing.reportPhishURL", "https://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%&url=");
pref("browser.safebrowsing.reportMalwareMistakeURL", "https://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%&url=");
pref("browser.safebrowsing.id", "Firefox");
// Tables for application reputation.
pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar");
// The number of random entries to send with a gethash request.
pref("urlclassifier.gethashnoise", 4);
// Gethash timeout for Safebrowsing.
pref("urlclassifier.gethash.timeout_ms", 5000);
// If an urlclassifier table has not been updated in this number of seconds,
// a gethash request will be forced to check that the result is still in
// the database.
pref("urlclassifier.max-complete-age", 2700);
// Tracking protection
pref("privacy.trackingprotection.enabled", false);
pref("privacy.trackingprotection.pbmode.enabled", true);
#endif
// True if this is the first time we are showing about:firstrun
pref("browser.firstrun.show.uidiscovery", true);
pref("browser.firstrun.show.localepicker", true);
@@ -850,8 +891,6 @@ pref("general.useragent.updates.retry", 86400); // 1 day
// Device ID can be composed of letter, numbers, hyphen ("-") and dot (".")
pref("general.useragent.device_id", "");
// Make <audio> and <video> talk to the AudioChannelService.
pref("media.useAudioChannelService", true);
// Add Mozilla AudioChannel APIs.
pref("media.useAudioChannelAPI", true);
+2
View File
@@ -399,6 +399,8 @@
@RESPATH@/components/ConsoleAPIStorage.js
@RESPATH@/components/BrowserElementParent.manifest
@RESPATH@/components/BrowserElementParent.js
@RESPATH@/components/BrowserElementProxy.manifest
@RESPATH@/components/BrowserElementProxy.js
@RESPATH@/components/ContactManager.js
@RESPATH@/components/ContactManager.manifest
@RESPATH@/components/PhoneNumberService.js
+2
View File
@@ -384,6 +384,8 @@
@RESPATH@/components/ConsoleAPIStorage.js
@RESPATH@/components/BrowserElementParent.manifest
@RESPATH@/components/BrowserElementParent.js
@RESPATH@/components/BrowserElementProxy.manifest
@RESPATH@/components/BrowserElementProxy.js
@RESPATH@/components/FeedProcessor.manifest
@RESPATH@/components/FeedProcessor.js
@RESPATH@/components/PackagedAppUtils.js
+4 -3
View File
@@ -7,13 +7,14 @@ import subprocess
def get_all_toplevel_filenames():
'''Get a list of all the files in the (Mercurial or Git) repository.'''
failed_cmds = []
try:
cmd = ['hg', 'manifest', '-q']
all_filenames = subprocess.check_output(cmd, universal_newlines=True,
stderr=subprocess.PIPE).split('\n')
return all_filenames
except:
pass
failed_cmds.append(cmd)
try:
# Get the relative path to the top-level directory.
@@ -25,6 +26,6 @@ def get_all_toplevel_filenames():
stderr=subprocess.PIPE).split('\n')
return all_filenames
except:
pass
failed_cmds.append(cmd)
raise Exception('failed to run any of the repo manifest commands', cmds)
raise Exception('failed to run any of the repo manifest commands', failed_cmds)
+5
View File
@@ -131,6 +131,11 @@ this.PermissionsTable = { geolocation: {
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
"browser:embedded-system-app": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
bluetooth: {
app: DENY_ACTION,
privileged: DENY_ACTION,
+8 -2
View File
@@ -573,8 +573,6 @@ WebappsApplication.prototype = {
launch: function(aStartPoint) {
let request = this.createRequest();
this.addMessageListeners(["Webapps:Launch:Return:OK",
"Webapps:Launch:Return:KO"]);
cpmm.sendAsyncMessage("Webapps:Launch", { origin: this.origin,
manifestURL: this.manifestURL,
startPoint: aStartPoint || "",
@@ -582,6 +580,14 @@ WebappsApplication.prototype = {
topId: this._topId,
timestamp: Date.now(),
requestID: this.getRequestId(request) });
let manifestURL = AppsUtils.getAppManifestURLFromWindow(this._window);
if (manifestURL != this.manifestURL) {
Services.obs.notifyObservers(null, "will-launch-app", null);
}
this.addMessageListeners(["Webapps:Launch:Return:OK",
"Webapps:Launch:Return:KO"]);
return request;
},
+55 -7
View File
@@ -12,7 +12,18 @@
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION(AudioChannelAgent, mWindow, mCallback)
NS_IMPL_CYCLE_COLLECTION_CLASS(AudioChannelAgent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioChannelAgent)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioChannelAgent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioChannelAgent)
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgent)
@@ -26,10 +37,17 @@ AudioChannelAgent::AudioChannelAgent()
: mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
, mInnerWindowID(0)
, mIsRegToService(false)
, mNotifyPlayback(false)
{
}
AudioChannelAgent::~AudioChannelAgent()
{
Shutdown();
}
void
AudioChannelAgent::Shutdown()
{
if (mIsRegToService) {
NotifyStoppedPlaying();
@@ -77,7 +95,7 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
"Enum of channel on nsIAudioChannelAgent.idl should be the same with AudioChannelBinding.h");
if (mAudioChannelType != AUDIO_AGENT_CHANNEL_ERROR ||
aChannelType > AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION ||
aChannelType > AUDIO_AGENT_CHANNEL_SYSTEM ||
aChannelType < AUDIO_AGENT_CHANNEL_NORMAL) {
return NS_ERROR_FAILURE;
}
@@ -112,39 +130,63 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
mCallback = aCallback;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, InitInternal, this = %p, type = %d, "
"owner = %p, hasCallback = %d\n", this, mAudioChannelType,
mWindow.get(), (!!mCallback || !!mWeakCallback)));
return NS_OK;
}
NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(float *aVolume,
NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(uint32_t aNotifyPlayback,
float *aVolume,
bool* aMuted)
{
MOZ_ASSERT(aVolume);
MOZ_ASSERT(aMuted);
// Window-less AudioChannelAgents are muted by default.
if (!mWindow) {
*aVolume = 0;
*aMuted = true;
return NS_OK;
}
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
service == nullptr || mIsRegToService) {
return NS_ERROR_FAILURE;
}
service->RegisterAudioChannelAgent(this,
service->RegisterAudioChannelAgent(this, aNotifyPlayback,
static_cast<AudioChannel>(mAudioChannelType));
service->GetState(mWindow, mAudioChannelType, aVolume, aMuted);
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, NotifyStartedPlaying, this = %p, mute = %d, "
"volume = %f\n", this, *aMuted, *aVolume));
mNotifyPlayback = aNotifyPlayback;
mIsRegToService = true;
return NS_OK;
}
NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying(void)
NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying()
{
if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
!mIsRegToService) {
return NS_ERROR_FAILURE;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, NotifyStoppedPlaying, this = %p\n", this));
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->UnregisterAudioChannelAgent(this);
if (service) {
service->UnregisterAudioChannelAgent(this, mNotifyPlayback);
}
mIsRegToService = false;
return NS_OK;
}
@@ -171,7 +213,13 @@ AudioChannelAgent::WindowVolumeChanged()
bool muted = false;
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->GetState(mWindow, mAudioChannelType, &volume, &muted);
if (service) {
service->GetState(mWindow, mAudioChannelType, &volume, &muted);
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, WindowVolumeChanged, this = %p, mute = %d, "
"volume = %f\n", this, muted, volume));
callback->WindowVolumeChanged(volume, muted);
}
+3
View File
@@ -54,6 +54,8 @@ private:
nsIAudioChannelAgentCallback* aCallback,
bool aUseWeakRef);
void Shutdown();
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsIAudioChannelAgentCallback> mCallback;
@@ -62,6 +64,7 @@ private:
int32_t mAudioChannelType;
uint64_t mInnerWindowID;
bool mIsRegToService;
bool mNotifyPlayback;
};
} // namespace dom
+81 -35
View File
@@ -40,6 +40,7 @@ namespace {
// If true, any new AudioChannelAgent will be muted when created.
bool sAudioChannelMutedByDefault = false;
bool sXPCOMShuttingDown = false;
class NotifyChannelActiveRunnable final : public nsRunnable
{
@@ -78,6 +79,11 @@ public:
mActive
? MOZ_UTF16("active")
: MOZ_UTF16("inactive"));
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("NotifyChannelActiveRunnable, type = %d, active = %d\n",
mAudioChannel, mActive));
return NS_OK;
}
@@ -156,32 +162,54 @@ static const nsAttrValue::EnumTable kMozAudioChannelAttributeTable[] = {
{ "telephony", (int16_t)AudioChannel::Telephony },
{ "ringer", (int16_t)AudioChannel::Ringer },
{ "publicnotification", (int16_t)AudioChannel::Publicnotification },
{ "system", (int16_t)AudioChannel::System },
{ nullptr }
};
/* static */ already_AddRefed<AudioChannelService>
AudioChannelService::GetOrCreate()
/* static */ void
AudioChannelService::CreateServiceIfNeeded()
{
MOZ_ASSERT(NS_IsMainThread());
if (!gAudioChannelService) {
gAudioChannelService = new AudioChannelService();
}
}
/* static */ already_AddRefed<AudioChannelService>
AudioChannelService::GetOrCreate()
{
if (sXPCOMShuttingDown) {
return nullptr;
}
CreateServiceIfNeeded();
RefPtr<AudioChannelService> service = gAudioChannelService.get();
return service.forget();
}
void
/* static */ PRLogModuleInfo*
AudioChannelService::GetAudioChannelLog()
{
static PRLogModuleInfo *gAudioChannelLog;
if (!gAudioChannelLog) {
gAudioChannelLog = PR_NewLogModule("AudioChannel");
}
return gAudioChannelLog;
}
/* static */ void
AudioChannelService::Shutdown()
{
if (gAudioChannelService) {
if (IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(gAudioChannelService, "xpcom-shutdown");
obs->RemoveObserver(gAudioChannelService, "outer-window-destroyed");
if (IsParentProcess()) {
obs->RemoveObserver(gAudioChannelService, "ipc:content-shutdown");
obs->RemoveObserver(gAudioChannelService, "xpcom-shutdown");
obs->RemoveObserver(gAudioChannelService, "outer-window-destroyed");
#ifdef MOZ_WIDGET_GONK
// To monitor the volume settings based on audio channel.
obs->RemoveObserver(gAudioChannelService, "mozsettings-changed");
@@ -189,6 +217,12 @@ AudioChannelService::Shutdown()
}
}
gAudioChannelService->mWindows.Clear();
gAudioChannelService->mPlayingChildren.Clear();
#ifdef MOZ_WIDGET_GONK
gAudioChannelService->mSpeakerManager.Clear();
#endif
gAudioChannelService = nullptr;
}
}
@@ -208,12 +242,13 @@ AudioChannelService::AudioChannelService()
, mContentOrNormalChannel(false)
, mAnyChannel(false)
{
if (IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(this, "xpcom-shutdown", false);
obs->AddObserver(this, "outer-window-destroyed", false);
if (IsParentProcess()) {
obs->AddObserver(this, "ipc:content-shutdown", false);
obs->AddObserver(this, "xpcom-shutdown", false);
obs->AddObserver(this, "outer-window-destroyed", false);
#ifdef MOZ_WIDGET_GONK
// To monitor the volume settings based on audio channel.
obs->AddObserver(this, "mozsettings-changed", false);
@@ -231,6 +266,7 @@ AudioChannelService::~AudioChannelService()
void
AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback,
AudioChannel aChannel)
{
uint64_t windowID = aAgent->WindowID();
@@ -251,7 +287,8 @@ AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
}
// If this is the first agent for this window, we must notify the observers.
if (winData->mAgents.Length() == 1) {
if (aNotifyPlayback == nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY &&
winData->mAgents.Length() == 1) {
RefPtr<MediaPlaybackRunnable> runnable =
new MediaPlaybackRunnable(aAgent->Window(), true /* active */);
NS_DispatchToCurrentThread(runnable);
@@ -261,7 +298,8 @@ AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
}
void
AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback)
{
AudioChannelWindow* winData = GetWindowData(aAgent->WindowID());
if (!winData) {
@@ -293,7 +331,8 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
#endif
// If this is the last agent for this window, we must notify the observers.
if (winData->mAgents.IsEmpty()) {
if (aNotifyPlayback == nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY &&
winData->mAgents.IsEmpty()) {
RefPtr<MediaPlaybackRunnable> runnable =
new MediaPlaybackRunnable(aAgent->Window(), false /* active */);
NS_DispatchToCurrentThread(runnable);
@@ -310,13 +349,16 @@ AudioChannelService::GetState(nsPIDOMWindow* aWindow, uint32_t aAudioChannel,
MOZ_ASSERT(aVolume && aMuted);
MOZ_ASSERT(aAudioChannel < NUMBER_OF_AUDIO_CHANNELS);
*aVolume = 1.0;
*aMuted = false;
if (!aWindow || !aWindow->IsOuterWindow()) {
*aVolume = 0.0;
*aMuted = true;
return;
}
*aVolume = 1.0;
*aMuted = false;
AudioChannelWindow* winData = nullptr;
nsCOMPtr<nsPIDOMWindow> window = aWindow;
@@ -346,9 +388,9 @@ AudioChannelService::GetState(nsPIDOMWindow* aWindow, uint32_t aAudioChannel,
bool
AudioChannelService::TelephonyChannelIsActive()
{
nsTObserverArray<nsAutoPtr<AudioChannelWindow>>::ForwardIterator iter(mWindows);
while (iter.HasMore()) {
AudioChannelWindow* next = iter.GetNext();
nsTObserverArray<nsAutoPtr<AudioChannelWindow>>::ForwardIterator windowsIter(mWindows);
while (windowsIter.HasMore()) {
AudioChannelWindow* next = windowsIter.GetNext();
if (next->mChannels[(uint32_t)AudioChannel::Telephony].mNumberOfAgents != 0 &&
!next->mChannels[(uint32_t)AudioChannel::Telephony].mMuted) {
return true;
@@ -357,9 +399,9 @@ AudioChannelService::TelephonyChannelIsActive()
if (IsParentProcess()) {
nsTObserverArray<nsAutoPtr<AudioChannelChildStatus>>::ForwardIterator
iter(mPlayingChildren);
while (iter.HasMore()) {
AudioChannelChildStatus* child = iter.GetNext();
childrenIter(mPlayingChildren);
while (childrenIter.HasMore()) {
AudioChannelChildStatus* child = childrenIter.GetNext();
if (child->mActiveTelephonyChannel) {
return true;
}
@@ -452,7 +494,7 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown")) {
mWindows.Clear();
sXPCOMShuttingDown = true;
Shutdown();
} else if (!strcmp(aTopic, "outer-window-destroyed")) {
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
@@ -518,16 +560,6 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
struct RefreshAgentsVolumeData
{
explicit RefreshAgentsVolumeData(nsPIDOMWindow* aWindow)
: mWindow(aWindow)
{}
nsPIDOMWindow* mWindow;
nsTArray<RefPtr<AudioChannelAgent>> mAgents;
};
void
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
{
@@ -713,6 +745,10 @@ AudioChannelService::SetAudioChannelVolume(nsPIDOMWindow* aWindow,
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aWindow->IsOuterWindow());
MOZ_LOG(GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelService, SetAudioChannelVolume, window = %p, type = %d, "
"volume = %d\n", aWindow, aAudioChannel, aVolume));
AudioChannelWindow* winData = GetOrCreateWindowData(aWindow);
winData->mChannels[(uint32_t)aAudioChannel].mVolume = aVolume;
RefreshAgentsVolume(aWindow);
@@ -767,6 +803,15 @@ AudioChannelService::SetAudioChannelMuted(nsPIDOMWindow* aWindow,
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aWindow->IsOuterWindow());
MOZ_LOG(GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelService, SetAudioChannelMuted, window = %p, type = %d, "
"mute = %d\n", aWindow, aAudioChannel, aMuted));
if (aAudioChannel == AudioChannel::System) {
// Workaround for bug1183033, system channel type can always playback.
return;
}
AudioChannelWindow* winData = GetOrCreateWindowData(aWindow);
winData->mChannels[(uint32_t)aAudioChannel].mMuted = aMuted;
RefreshAgentsVolume(aWindow);
@@ -923,5 +968,6 @@ AudioChannelService::ChildStatusReceived(uint64_t aChildID,
/* static */ bool
AudioChannelService::IsAudioChannelMutedByDefault()
{
CreateServiceIfNeeded();
return sAudioChannelMutedByDefault;
}
+14 -3
View File
@@ -19,6 +19,7 @@
class nsIRunnable;
class nsPIDOMWindow;
struct PRLogModuleInfo;
namespace mozilla {
namespace dom {
@@ -45,17 +46,22 @@ public:
static bool IsAudioChannelMutedByDefault();
static PRLogModuleInfo* GetAudioChannelLog();
/**
* Any audio channel agent that starts playing should register itself to
* this service, sharing the AudioChannel.
*/
void RegisterAudioChannelAgent(AudioChannelAgent* aAgent, AudioChannel aChannel);
void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback,
AudioChannel aChannel);
/**
* Any audio channel agent that stops playing should unregister itself to
* this service.
*/
void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback);
/**
* Return the state to indicate this audioChannel for his window should keep
@@ -139,6 +145,8 @@ private:
AudioChannelService();
~AudioChannelService();
static void CreateServiceIfNeeded();
/**
* Shutdown the singleton.
*/
@@ -170,7 +178,10 @@ private:
{
explicit AudioChannelWindow(uint64_t aWindowID)
: mWindowID(aWindowID)
{}
{
// Workaround for bug1183033, system channel type can always playback.
mChannels[(int16_t)AudioChannel::System].mMuted = false;
}
uint64_t mWindowID;
AudioChannelConfig mChannels[NUMBER_OF_AUDIO_CHANNELS];
+17
View File
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function boom() {
var audio = document.createElement('audio');
audio.loop = true;
audio.play();
document.implementation.createDocument("", "", null).adoptNode(audio);
}
</script>
</head>
<body onload="boom();"></body>
</html>
@@ -0,0 +1 @@
load 1223734.html
+3
View File
@@ -24,3 +24,6 @@ UNIFIED_SOURCES += [
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
+8 -2
View File
@@ -34,7 +34,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
* 1. Changes to the playable status of this channel.
*/
[uuid(ee39a34b-a5c7-4b30-b1ac-cd64ceedef67)]
[uuid(18222148-1b32-463d-b050-b741f43a07ba)]
interface nsIAudioChannelAgent : nsISupports
{
const long AUDIO_AGENT_CHANNEL_NORMAL = 0;
@@ -52,6 +52,9 @@ interface nsIAudioChannelAgent : nsISupports
const long AUDIO_AGENT_STATE_MUTED = 1;
const long AUDIO_AGENT_STATE_FADED = 2;
const long AUDIO_AGENT_DONT_NOTIFY = 0;
const long AUDIO_AGENT_NOTIFY = 1;
/**
* Before init() is called, this returns AUDIO_AGENT_CHANNEL_ERROR.
*/
@@ -98,6 +101,9 @@ interface nsIAudioChannelAgent : nsISupports
* Note: Gecko component SHOULD call this function first then start to
* play audio stream only when return value is true.
*
* @param notifyPlaying
* Whether to send audio-playback notifications, one of AUDIO_CHANNEL_NOTIFY
* or AUDIO_CHANNEL_DONT_NOTIFY.
*
* @return
* normal state: the agent has registered with audio channel service and
@@ -107,7 +113,7 @@ interface nsIAudioChannelAgent : nsISupports
* faded state: the agent has registered with audio channel service the
* component should start playback as well as reducing the volume.
*/
void notifyStartedPlaying(out float volume, out bool muted);
void notifyStartedPlaying(in unsigned long notifyPlayback, out float volume, out bool muted);
/**
* Notify the agent we no longer want to play.
+55
View File
@@ -0,0 +1,55 @@
/* -*- 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 "WindowOrientationObserver.h"
#include "nsGlobalWindow.h"
#include "mozilla/Hal.h"
/**
* This class is used by nsGlobalWindow to implement window.orientation
* and window.onorientationchange. This class is defined in its own file
* because Hal.h pulls in windows.h and can't be included from
* nsGlobalWindow.cpp
*/
WindowOrientationObserver::WindowOrientationObserver(
nsGlobalWindow* aGlobalWindow)
: mWindow(aGlobalWindow)
{
MOZ_ASSERT(aGlobalWindow && aGlobalWindow->IsInnerWindow());
hal::RegisterScreenConfigurationObserver(this);
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
mAngle = config.angle();
}
WindowOrientationObserver::~WindowOrientationObserver()
{
hal::UnregisterScreenConfigurationObserver(this);
}
void
WindowOrientationObserver::Notify(
const mozilla::hal::ScreenConfiguration& aConfiguration)
{
uint16_t currentAngle = aConfiguration.angle();
if (mAngle != currentAngle && mWindow->IsCurrentInnerWindow()) {
mAngle = currentAngle;
mWindow->GetOuterWindow()->DispatchCustomEvent(NS_LITERAL_STRING("orientationchange"));
}
}
/* static */ int16_t
WindowOrientationObserver::OrientationAngle()
{
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
int16_t angle = static_cast<int16_t>(config.angle());
// config.angle() returns 0, 90, 180 or 270.
// window.orientation returns -90, 0, 90 or 180.
return angle <= 180 ? angle : angle - 360;
}
+35
View File
@@ -0,0 +1,35 @@
/* -*- 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_dom_WindowOrientationObserver_h
#define mozilla_dom_WindowOrientationObserver_h
#include "mozilla/HalScreenConfiguration.h"
class nsGlobalWindow;
namespace mozilla {
namespace dom {
class WindowOrientationObserver final :
public mozilla::hal::ScreenConfigurationObserver
{
public:
explicit WindowOrientationObserver(nsGlobalWindow* aGlobalWindow);
~WindowOrientationObserver();
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override;
static int16_t OrientationAngle();
private:
// Weak pointer, instance is owned by mWindow.
nsGlobalWindow* MOZ_NON_OWNING_REF mWindow;
uint16_t mAngle;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_WindowOrientationObserver_h
+2
View File
@@ -212,6 +212,7 @@ EXPORTS.mozilla.dom += [
'URL.h',
'URLSearchParams.h',
'WebSocket.h',
'WindowOrientationObserver.h',
]
UNIFIED_SOURCES += [
@@ -360,6 +361,7 @@ UNIFIED_SOURCES += [
'URLSearchParams.cpp',
'WebSocket.cpp',
'WindowNamedPropertiesHandler.cpp',
'WindowOrientationObserver.cpp',
]
if CONFIG['MOZ_WEBRTC']:
+3 -3
View File
@@ -727,7 +727,7 @@ DragDataProducer::AddString(DataTransfer* aDataTransfer,
const nsAString& aData,
nsIPrincipal* aPrincipal)
{
RefPtr<nsVariant> variant = new nsVariant();
RefPtr<nsVariantCC> variant = new nsVariantCC();
variant->SetAsAString(aData);
aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal);
}
@@ -783,7 +783,7 @@ DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
// a new flavor so as not to confuse anyone who is really registered
// for image/gif or image/jpg.
if (mImage) {
RefPtr<nsVariant> variant = new nsVariant();
RefPtr<nsVariantCC> variant = new nsVariantCC();
variant->SetAsISupports(mImage);
aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kNativeImageMime),
variant, 0, principal);
@@ -795,7 +795,7 @@ DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
nsCOMPtr<nsIFlavorDataProvider> dataProvider =
new nsContentAreaDragDropDataProvider();
if (dataProvider) {
RefPtr<nsVariant> variant = new nsVariant();
RefPtr<nsVariantCC> variant = new nsVariantCC();
variant->SetAsISupports(dataProvider);
aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kFilePromiseMime),
variant, 0, principal);
+80 -2
View File
@@ -7357,6 +7357,7 @@ nsContentUtils::CallOnAllRemoteChildren(nsIDOMWindow* aWindow,
void
nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables,
nsTArray<IPCDataTransfer>& aIPC,
bool aInSyncMessage,
mozilla::dom::nsIContentChild* aChild,
mozilla::dom::nsIContentParent* aParent)
{
@@ -7369,14 +7370,71 @@ nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables
nsCOMPtr<nsISupports> genericItem;
aTransferables->GetElementAt(i, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> transferable(do_QueryInterface(genericItem));
TransferableToIPCTransferable(transferable, dt, aChild, aParent);
TransferableToIPCTransferable(transferable, dt, aInSyncMessage, aChild, aParent);
}
}
}
nsresult
nsContentUtils::SlurpFileToString(nsIFile* aFile, nsACString& aString)
{
aString.Truncate();
nsCOMPtr<nsIURI> fileURI;
nsresult rv = NS_NewFileURI(getter_AddRefs(fileURI), aFile);
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
fileURI,
nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
nsIContentPolicy::TYPE_OTHER);
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIInputStream> stream;
rv = channel->Open2(getter_AddRefs(stream));
if (NS_FAILED(rv)) {
return rv;
}
rv = NS_ConsumeStream(stream, UINT32_MAX, aString);
if (NS_FAILED(rv)) {
return rv;
}
rv = stream->Close();
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
bool
nsContentUtils::IsFileImage(nsIFile* aFile, nsACString& aType)
{
nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1");
if (!mime) {
return false;
}
nsresult rv = mime->GetTypeFromFile(aFile, aType);
if (NS_FAILED(rv)) {
return false;
}
return StringBeginsWith(aType, NS_LITERAL_CSTRING("image/"));
}
void
nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
IPCDataTransfer* aIPCDataTransfer,
bool aInSyncMessage,
mozilla::dom::nsIContentChild* aChild,
mozilla::dom::nsIContentParent* aParent)
{
@@ -7450,7 +7508,7 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
int32_t stride;
mozilla::UniquePtr<char[]> surfaceData =
nsContentUtils::GetSurfaceData(dataSurface, &length, &stride);
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = nsCString(flavorStr);
item->data() = nsCString(surfaceData.get(), length);
@@ -7470,6 +7528,22 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
nsCOMPtr<BlobImpl> blobImpl;
nsCOMPtr<nsIFile> file = do_QueryInterface(data);
if (file) {
// If we can send this over as a blob, do so. Otherwise, we're
// responding to a sync message and the child can't process the blob
// constructor before processing our response, which would crash. In
// that case, hope that the caller is nsClipboardProxy::GetData,
// called from editor and send over images as raw data.
if (aInSyncMessage) {
nsAutoCString type;
if (IsFileImage(file, type)) {
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = type;
SlurpFileToString(file, item->data());
}
continue;
}
blobImpl = new BlobImplFile(file, false);
ErrorResult rv;
// Ensure that file data is cached no that the content process
@@ -7478,6 +7552,10 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
blobImpl->GetLastModified(rv);
blobImpl->LookupAndCacheIsDirectory();
} else {
if (aInSyncMessage) {
// Can't do anything.
continue;
}
blobImpl = do_QueryInterface(data);
}
if (blobImpl) {
+17
View File
@@ -2444,13 +2444,30 @@ public:
CallOnRemoteChildFunction aCallback,
void* aArg);
/**
* Given an nsIFile, attempts to read it into aString.
*
* Note: Use sparingly! This causes main-thread I/O, which causes jank and all
* other bad things.
*/
static nsresult SlurpFileToString(nsIFile* aFile, nsACString& aString);
/**
* Returns true if the mime service thinks this file contains an image.
*
* The content type is returned in aType.
*/
static bool IsFileImage(nsIFile* aFile, nsACString& aType);
static void TransferablesToIPCTransferables(nsISupportsArray* aTransferables,
nsTArray<mozilla::dom::IPCDataTransfer>& aIPC,
bool aInSyncMessage,
mozilla::dom::nsIContentChild* aChild,
mozilla::dom::nsIContentParent* aParent);
static void TransferableToIPCTransferable(nsITransferable* aTransferable,
mozilla::dom::IPCDataTransfer* aIPCDataTransfer,
bool aInSyncMessage,
mozilla::dom::nsIContentChild* aChild,
mozilla::dom::nsIContentParent* aParent);
+1
View File
@@ -840,6 +840,7 @@ GK_ATOM(onobsolete, "onobsolete")
GK_ATOM(ononline, "ononline")
GK_ATOM(onoffline, "onoffline")
GK_ATOM(onopen, "onopen")
GK_ATOM(onorientationchange, "onorientationchange")
GK_ATOM(onotastatuschange, "onotastatuschange")
GK_ATOM(onoverflow, "onoverflow")
GK_ATOM(onoverflowchanged, "onoverflowchanged")
+185 -94
View File
@@ -20,6 +20,9 @@
#include "mozilla/dom/DOMStorage.h"
#include "mozilla/dom/StorageEvent.h"
#include "mozilla/dom/StorageEventBinding.h"
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
#include "mozilla/dom/WindowOrientationObserver.h"
#endif
#include "nsDOMOfflineResourceList.h"
#include "nsError.h"
#include "nsIIdleService.h"
@@ -42,6 +45,7 @@
#include "WindowNamedPropertiesHandler.h"
#include "nsFrameSelection.h"
#include "nsNetUtil.h"
#include "nsVariant.h"
// Helper Classes
#include "nsJSUtils.h"
@@ -561,6 +565,27 @@ nsTimeout::HasRefCntOne()
return mRefCnt.get() == 1;
}
static already_AddRefed<nsIVariant>
CreateVoidVariant()
{
RefPtr<nsVariantCC> writable = new nsVariantCC();
writable->SetAsVoid();
return writable.forget();
}
nsresult
DialogValueHolder::Get(nsIPrincipal* aSubject, nsIVariant** aResult)
{
nsCOMPtr<nsIVariant> result;
if (aSubject->SubsumesConsideringDomain(mOrigin)) {
result = mValue;
} else {
result = CreateVoidVariant();
}
result.forget(aResult);
return NS_OK;
}
namespace mozilla {
namespace dom {
extern uint64_t
@@ -677,10 +702,12 @@ public:
static const nsOuterWindowProxy singleton;
protected:
static nsGlobalWindow* GetWindow(JSObject *proxy)
static nsGlobalWindow* GetOuterWindow(JSObject *proxy)
{
return nsGlobalWindow::FromSupports(
nsGlobalWindow* outerWindow = nsGlobalWindow::FromSupports(
static_cast<nsISupports*>(js::GetProxyExtra(proxy, 0).toPrivate()));
MOZ_ASSERT_IF(outerWindow, outerWindow->IsOuterWindow());
return outerWindow;
}
// False return value means we threw an exception. True return value
@@ -720,15 +747,15 @@ nsOuterWindowProxy::className(JSContext *cx, JS::Handle<JSObject*> proxy) const
void
nsOuterWindowProxy::finalize(JSFreeOp *fop, JSObject *proxy) const
{
nsGlobalWindow* global = GetWindow(proxy);
if (global) {
global->ClearWrapper();
nsGlobalWindow* outerWindow = GetOuterWindow(proxy);
if (outerWindow) {
outerWindow->ClearWrapper();
// Ideally we would use OnFinalize here, but it's possible that
// EnsureScriptEnvironment will later be called on the window, and we don't
// want to create a new script object in that case. Therefore, we need to
// write a non-null value that will reliably crash when dereferenced.
global->PoisonOuterWindowProxy(proxy);
outerWindow->PoisonOuterWindowProxy(proxy);
}
}
@@ -770,6 +797,9 @@ nsOuterWindowProxy::getOwnPropertyDescriptor(JSContext* cx,
}
// else fall through to js::Wrapper
// When we change this to always claim the property is configurable (bug
// 1178639), update the comments in nsOuterWindowProxy::defineProperty
// accordingly.
return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
}
@@ -788,14 +818,29 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
return result.failCantDefineWindowElement();
}
#ifndef RELEASE_BUILD // To be turned on in bug 1178638.
// For now, allow chrome code to define non-configurable properties
// on windows, until we sort out what exactly the addon SDK is
// doing. In the meantime, this still allows us to test web compat
// behavior.
if (false && !desc.configurable() && !nsContentUtils::IsCallerChrome()) {
if (desc.hasConfigurable() && !desc.configurable() &&
!nsContentUtils::IsCallerChrome()) {
return ThrowErrorMessage(cx, MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW);
}
// Note that if hasConfigurable() is false we do NOT want to
// setConfigurable(true). That would make this code:
//
// var x;
// window.x = 5;
//
// fail, because the JS engine ends up converting the assignment into a define
// with !hasConfigurable(), but the var actually declared a non-configurable
// property on our underlying Window object, so the set would fail if we
// forced setConfigurable(true) here. What we want to do instead is change
// getOwnPropertyDescriptor to always claim configurable. See bug 1178639.
#endif
return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
}
@@ -976,7 +1021,7 @@ nsOuterWindowProxy::GetSubframeWindow(JSContext *cx,
return nullptr;
}
nsGlobalWindow* win = GetWindow(proxy);
nsGlobalWindow* win = GetOuterWindow(proxy);
MOZ_ASSERT(win->IsOuterWindow());
return win->IndexedGetterOuter(index);
}
@@ -985,7 +1030,7 @@ bool
nsOuterWindowProxy::AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
JS::AutoIdVector &props) const
{
uint32_t length = GetWindow(proxy)->Length();
uint32_t length = GetOuterWindow(proxy)->Length();
MOZ_ASSERT(int32_t(length) >= 0);
if (!props.reserve(props.length() + length)) {
return false;
@@ -1014,9 +1059,9 @@ nsOuterWindowProxy::unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
void
nsOuterWindowProxy::ObjectMoved(JSObject *obj, const JSObject *old)
{
nsGlobalWindow* global = GetWindow(obj);
if (global) {
global->UpdateWrapper(obj, old);
nsGlobalWindow* outerWindow = GetOuterWindow(obj);
if (outerWindow) {
outerWindow->UpdateWrapper(obj, old);
}
}
@@ -1483,6 +1528,10 @@ nsGlobalWindow::CleanUp()
mSpeechSynthesis = nullptr;
#endif
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
mOrientationChangeObserver = nullptr;
#endif
ClearControllers();
mOpener = nullptr; // Forces Release
@@ -1597,6 +1646,10 @@ nsGlobalWindow::FreeInnerObjects(bool aForDocumentOpen)
mScreen = nullptr;
}
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
mOrientationChangeObserver = nullptr;
#endif
if (mDoc) {
// Remember the document's principal and URI.
mDocumentPrincipal = mDoc->NodePrincipal();
@@ -1923,10 +1976,7 @@ nsGlobalWindow::UnmarkGrayTimers()
if (timeout->mScriptHandler) {
Function* f = timeout->mScriptHandler->GetCallback();
if (f) {
// Callable() already does xpc_UnmarkGrayObject.
DebugOnly<JS::Handle<JSObject*> > o = f->Callable();
MOZ_ASSERT(!JS::ObjectIsMarkedGray(o.value),
"Should have been unmarked");
f->MarkForCC();
}
}
}
@@ -3713,7 +3763,9 @@ void
nsPIDOMWindow::RefreshMediaElements()
{
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->RefreshAgentsVolume(GetOuterWindow());
if (service) {
service->RefreshAgentsVolume(GetOuterWindow());
}
}
bool
@@ -3731,7 +3783,9 @@ nsPIDOMWindow::SetAudioCapture(bool aCapture)
mAudioCaptured = aCapture;
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
if (service) {
service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
}
return NS_OK;
}
@@ -4880,7 +4934,7 @@ nsGlobalWindow::GetInnerWidth(int32_t* aInnerWidth)
}
void
nsGlobalWindow::SetInnerWidthOuter(int32_t aInnerWidth, ErrorResult& aError)
nsGlobalWindow::SetInnerWidthOuter(int32_t aInnerWidth, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -4889,7 +4943,7 @@ nsGlobalWindow::SetInnerWidthOuter(int32_t aInnerWidth, ErrorResult& aError)
return;
}
CheckSecurityWidthAndHeight(&aInnerWidth, nullptr);
CheckSecurityWidthAndHeight(&aInnerWidth, nullptr, aCallerIsChrome);
RefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
@@ -4918,7 +4972,7 @@ nsGlobalWindow::SetInnerWidthOuter(int32_t aInnerWidth, ErrorResult& aError)
void
nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SetInnerWidthOuter, (aInnerWidth, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(SetInnerWidthOuter, (aInnerWidth, aError, nsContentUtils::IsCallerChrome()), aError, );
}
void
@@ -4981,7 +5035,7 @@ nsGlobalWindow::GetInnerHeight(int32_t* aInnerHeight)
}
void
nsGlobalWindow::SetInnerHeightOuter(int32_t aInnerHeight, ErrorResult& aError)
nsGlobalWindow::SetInnerHeightOuter(int32_t aInnerHeight, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -5000,7 +5054,7 @@ nsGlobalWindow::SetInnerHeightOuter(int32_t aInnerHeight, ErrorResult& aError)
nsRect shellArea = presContext->GetVisibleArea();
nscoord height = aInnerHeight;
nscoord width = shellArea.width;
CheckSecurityWidthAndHeight(nullptr, &height);
CheckSecurityWidthAndHeight(nullptr, &height, aCallerIsChrome);
SetCSSViewportWidthAndHeight(width,
nsPresContext::CSSPixelsToAppUnits(height));
return;
@@ -5011,14 +5065,14 @@ nsGlobalWindow::SetInnerHeightOuter(int32_t aInnerHeight, ErrorResult& aError)
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
docShellAsWin->GetSize(&width, &height);
CheckSecurityWidthAndHeight(nullptr, &aInnerHeight);
CheckSecurityWidthAndHeight(nullptr, &aInnerHeight, aCallerIsChrome);
aError = SetDocShellWidthAndHeight(width, CSSToDevIntPixels(aInnerHeight));
}
void
nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SetInnerHeightOuter, (aInnerHeight, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(SetInnerHeightOuter, (aInnerHeight, aError, nsContentUtils::IsCallerChrome()), aError, );
}
void
@@ -5144,7 +5198,7 @@ nsGlobalWindow::GetOuterHeight(int32_t* aOuterHeight)
void
nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
ErrorResult& aError)
ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_ASSERT(IsOuterWindow());
@@ -5155,7 +5209,8 @@ nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
}
CheckSecurityWidthAndHeight(aIsWidth ? &aLengthCSSPixels : nullptr,
aIsWidth ? nullptr : &aLengthCSSPixels);
aIsWidth ? nullptr : &aLengthCSSPixels,
aCallerIsChrome);
int32_t width, height;
aError = treeOwnerAsWin->GetSize(&width, &height);
@@ -5173,17 +5228,17 @@ nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
}
void
nsGlobalWindow::SetOuterWidthOuter(int32_t aOuterWidth, ErrorResult& aError)
nsGlobalWindow::SetOuterWidthOuter(int32_t aOuterWidth, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
SetOuterSize(aOuterWidth, true, aError);
SetOuterSize(aOuterWidth, true, aError, aCallerIsChrome);
}
void
nsGlobalWindow::SetOuterWidth(int32_t aOuterWidth, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SetOuterWidthOuter, (aOuterWidth, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(SetOuterWidthOuter, (aOuterWidth, aError, nsContentUtils::IsCallerChrome()), aError, );
}
void
@@ -5210,17 +5265,17 @@ nsGlobalWindow::SetOuterWidth(int32_t aOuterWidth)
}
void
nsGlobalWindow::SetOuterHeightOuter(int32_t aOuterHeight, ErrorResult& aError)
nsGlobalWindow::SetOuterHeightOuter(int32_t aOuterHeight, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
SetOuterSize(aOuterHeight, false, aError);
SetOuterSize(aOuterHeight, false, aError, aCallerIsChrome);
}
void
nsGlobalWindow::SetOuterHeight(int32_t aOuterHeight, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SetOuterHeightOuter, (aOuterHeight, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(SetOuterHeightOuter, (aOuterHeight, aError, nsContentUtils::IsCallerChrome()), aError, );
}
void
@@ -5563,7 +5618,7 @@ nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
}
void
nsGlobalWindow::SetScreenXOuter(int32_t aScreenX, ErrorResult& aError)
nsGlobalWindow::SetScreenXOuter(int32_t aScreenX, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -5579,7 +5634,7 @@ nsGlobalWindow::SetScreenXOuter(int32_t aScreenX, ErrorResult& aError)
return;
}
CheckSecurityLeftAndTop(&aScreenX, nullptr);
CheckSecurityLeftAndTop(&aScreenX, nullptr, aCallerIsChrome);
x = CSSToDevIntPixels(aScreenX);
aError = treeOwnerAsWin->SetPosition(x, y);
@@ -5588,7 +5643,7 @@ nsGlobalWindow::SetScreenXOuter(int32_t aScreenX, ErrorResult& aError)
void
nsGlobalWindow::SetScreenX(int32_t aScreenX, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SetScreenXOuter, (aScreenX, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(SetScreenXOuter, (aScreenX, aError, nsContentUtils::IsCallerChrome()), aError, );
}
void
@@ -5649,7 +5704,7 @@ nsGlobalWindow::GetScreenY(JSContext* aCx,
}
void
nsGlobalWindow::SetScreenYOuter(int32_t aScreenY, ErrorResult& aError)
nsGlobalWindow::SetScreenYOuter(int32_t aScreenY, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -5665,7 +5720,7 @@ nsGlobalWindow::SetScreenYOuter(int32_t aScreenY, ErrorResult& aError)
return;
}
CheckSecurityLeftAndTop(nullptr, &aScreenY);
CheckSecurityLeftAndTop(nullptr, &aScreenY, aCallerIsChrome);
y = CSSToDevIntPixels(aScreenY);
aError = treeOwnerAsWin->SetPosition(x, y);
@@ -5674,7 +5729,7 @@ nsGlobalWindow::SetScreenYOuter(int32_t aScreenY, ErrorResult& aError)
void
nsGlobalWindow::SetScreenY(int32_t aScreenY, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SetScreenYOuter, (aScreenY, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(SetScreenYOuter, (aScreenY, aError, nsContentUtils::IsCallerChrome()), aError, );
}
void
@@ -5703,12 +5758,12 @@ nsGlobalWindow::SetScreenY(int32_t aScreenY)
// NOTE: Arguments to this function should have values scaled to
// CSS pixels, not device pixels.
void
nsGlobalWindow::CheckSecurityWidthAndHeight(int32_t* aWidth, int32_t* aHeight)
nsGlobalWindow::CheckSecurityWidthAndHeight(int32_t* aWidth, int32_t* aHeight, bool aCallerIsChrome)
{
MOZ_ASSERT(IsOuterWindow());
#ifdef MOZ_XUL
if (!nsContentUtils::IsCallerChrome()) {
if (!aCallerIsChrome) {
// if attempting to resize the window, hide any open popups
nsContentUtils::HidePopupsInDocument(mDoc);
}
@@ -5767,7 +5822,7 @@ nsGlobalWindow::SetCSSViewportWidthAndHeight(nscoord aInnerWidth, nscoord aInner
// NOTE: Arguments to this function should have values scaled to
// CSS pixels, not device pixels.
void
nsGlobalWindow::CheckSecurityLeftAndTop(int32_t* aLeft, int32_t* aTop)
nsGlobalWindow::CheckSecurityLeftAndTop(int32_t* aLeft, int32_t* aTop, bool aCallerIsChrome)
{
MOZ_ASSERT(IsOuterWindow());
@@ -5775,7 +5830,7 @@ nsGlobalWindow::CheckSecurityLeftAndTop(int32_t* aLeft, int32_t* aTop)
// Check security state for use in determing window dimensions
if (!nsContentUtils::IsCallerChrome()) {
if (!aCallerIsChrome) {
#ifdef MOZ_XUL
// if attempting to move the window, hide any open popups
nsContentUtils::HidePopupsInDocument(mDoc);
@@ -6536,12 +6591,12 @@ nsGlobalWindow::MakeScriptDialogTitle(nsAString &aOutTitle)
}
bool
nsGlobalWindow::CanMoveResizeWindows()
nsGlobalWindow::CanMoveResizeWindows(bool aCallerIsChrome)
{
MOZ_ASSERT(IsOuterWindow());
// When called from chrome, we can avoid the following checks.
if (!nsContentUtils::IsCallerChrome()) {
if (!aCallerIsChrome) {
// Don't allow scripts to move or resize windows that were not opened by a
// script.
if (!mHadOriginalOpener) {
@@ -7256,7 +7311,7 @@ nsGlobalWindow::Print()
}
void
nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos, ErrorResult& aError)
nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
/*
@@ -7264,7 +7319,7 @@ nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos, ErrorResult& aError)
* prevent window.moveTo() by exiting early
*/
if (!CanMoveResizeWindows() || IsFrame()) {
if (!CanMoveResizeWindows(aCallerIsChrome) || IsFrame()) {
return;
}
@@ -7276,7 +7331,7 @@ nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos, ErrorResult& aError)
// Mild abuse of a "size" object so we don't need more helper functions.
nsIntSize cssPos(aXPos, aYPos);
CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height);
CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height, aCallerIsChrome);
nsIntSize devPos = CSSToDevIntPixels(cssPos);
@@ -7286,7 +7341,7 @@ nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos, ErrorResult& aError)
void
nsGlobalWindow::MoveTo(int32_t aXPos, int32_t aYPos, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(MoveToOuter, (aXPos, aYPos, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(MoveToOuter, (aXPos, aYPos, aError, nsContentUtils::IsCallerChrome()), aError, );
}
NS_IMETHODIMP
@@ -7301,7 +7356,7 @@ nsGlobalWindow::MoveTo(int32_t aXPos, int32_t aYPos)
}
void
nsGlobalWindow::MoveByOuter(int32_t aXDif, int32_t aYDif, ErrorResult& aError)
nsGlobalWindow::MoveByOuter(int32_t aXDif, int32_t aYDif, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -7310,7 +7365,7 @@ nsGlobalWindow::MoveByOuter(int32_t aXDif, int32_t aYDif, ErrorResult& aError)
* prevent window.moveBy() by exiting early
*/
if (!CanMoveResizeWindows() || IsFrame()) {
if (!CanMoveResizeWindows(aCallerIsChrome) || IsFrame()) {
return;
}
@@ -7336,7 +7391,7 @@ nsGlobalWindow::MoveByOuter(int32_t aXDif, int32_t aYDif, ErrorResult& aError)
cssPos.width += aXDif;
cssPos.height += aYDif;
CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height);
CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height, aCallerIsChrome);
nsIntSize newDevPos(CSSToDevIntPixels(cssPos));
@@ -7346,22 +7401,22 @@ nsGlobalWindow::MoveByOuter(int32_t aXDif, int32_t aYDif, ErrorResult& aError)
void
nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(MoveByOuter, (aXDif, aYDif, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(MoveByOuter, (aXDif, aYDif, aError, nsContentUtils::IsCallerChrome()), aError, );
}
NS_IMETHODIMP
nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif)
{
FORWARD_TO_INNER(MoveBy, (aXDif, aYDif), NS_ERROR_UNEXPECTED);
FORWARD_TO_OUTER(MoveBy, (aXDif, aYDif), NS_ERROR_UNEXPECTED);
ErrorResult rv;
MoveBy(aXDif, aYDif, rv);
MoveByOuter(aXDif, aYDif, rv, /* aCallerIsChrome = */ true);
return rv.StealNSResult();
}
void
nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aError)
nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -7383,7 +7438,7 @@ nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aErr
* prevent window.resizeTo() by exiting early
*/
if (!CanMoveResizeWindows() || IsFrame()) {
if (!CanMoveResizeWindows(aCallerIsChrome) || IsFrame()) {
return;
}
@@ -7394,7 +7449,7 @@ nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aErr
}
nsIntSize cssSize(aWidth, aHeight);
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height);
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerIsChrome);
nsIntSize devSz(CSSToDevIntPixels(cssSize));
@@ -7404,7 +7459,7 @@ nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aErr
void
nsGlobalWindow::ResizeTo(int32_t aWidth, int32_t aHeight, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(ResizeToOuter, (aWidth, aHeight, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(ResizeToOuter, (aWidth, aHeight, aError, nsContentUtils::IsCallerChrome()), aError, );
}
NS_IMETHODIMP
@@ -7420,7 +7475,7 @@ nsGlobalWindow::ResizeTo(int32_t aWidth, int32_t aHeight)
void
nsGlobalWindow::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
ErrorResult& aError)
ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -7449,7 +7504,7 @@ nsGlobalWindow::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
* prevent window.resizeBy() by exiting early
*/
if (!CanMoveResizeWindows() || IsFrame()) {
if (!CanMoveResizeWindows(aCallerIsChrome) || IsFrame()) {
return;
}
@@ -7474,7 +7529,7 @@ nsGlobalWindow::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
cssSize.width += aWidthDif;
cssSize.height += aHeightDif;
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height);
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerIsChrome);
nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
@@ -7485,7 +7540,7 @@ void
nsGlobalWindow::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(ResizeByOuter, (aWidthDif, aHeightDif, aError), aError, );
FORWARD_TO_OUTER_OR_THROW(ResizeByOuter, (aWidthDif, aHeightDif, aError, nsContentUtils::IsCallerChrome()), aError, );
}
NS_IMETHODIMP
@@ -7500,7 +7555,7 @@ nsGlobalWindow::ResizeBy(int32_t aWidthDif, int32_t aHeightDif)
}
void
nsGlobalWindow::SizeToContentOuter(ErrorResult& aError)
nsGlobalWindow::SizeToContentOuter(ErrorResult& aError, bool aCallerIsChrome)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -7513,7 +7568,7 @@ nsGlobalWindow::SizeToContentOuter(ErrorResult& aError)
* prevent window.sizeToContent() by exiting early
*/
if (!CanMoveResizeWindows() || IsFrame()) {
if (!CanMoveResizeWindows(aCallerIsChrome) || IsFrame()) {
return;
}
@@ -7541,7 +7596,7 @@ nsGlobalWindow::SizeToContentOuter(ErrorResult& aError)
}
nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height);
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerIsChrome);
nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
@@ -7552,7 +7607,7 @@ nsGlobalWindow::SizeToContentOuter(ErrorResult& aError)
void
nsGlobalWindow::SizeToContent(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aError), aError, );
FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aError, nsContentUtils::IsCallerChrome()), aError, );
}
NS_IMETHODIMP
@@ -8448,7 +8503,7 @@ nsGlobalWindow::CanClose()
}
void
nsGlobalWindow::CloseOuter()
nsGlobalWindow::CloseOuter(bool aTrustedCaller)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@@ -8480,7 +8535,7 @@ nsGlobalWindow::CloseOuter()
mDoc->GetURL(url);
if (!mDocShell->GetIsApp() &&
!StringBeginsWith(url, NS_LITERAL_STRING("about:neterror")) &&
!mHadOriginalOpener && !nsContentUtils::IsCallerChrome()) {
!mHadOriginalOpener && !aTrustedCaller) {
bool allowClose = mAllowScriptsToClose ||
Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
if (!allowClose) {
@@ -8524,18 +8579,15 @@ nsGlobalWindow::CloseOuter()
void
nsGlobalWindow::Close(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(CloseOuter, (), aError, );
FORWARD_TO_OUTER_OR_THROW(CloseOuter, (nsContentUtils::IsCallerChrome()), aError, );
}
NS_IMETHODIMP
nsGlobalWindow::Close()
{
FORWARD_TO_INNER(Close, (), NS_ERROR_UNEXPECTED);
ErrorResult rv;
Close(rv);
return rv.StealNSResult();
FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
CloseOuter(/* aTrustedCaller = */ true);
return NS_OK;
}
void
@@ -9659,11 +9711,6 @@ nsGlobalWindow::AddEventListener(const nsAString& aType,
"aWantsUntrusted to false or make the aWantsUntrusted "
"explicit by making optional_argc non-zero.");
if (IsOuterWindow() && mInnerWindow &&
!nsContentUtils::CanCallerAccess(mInnerWindow)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!aWantsUntrusted &&
(aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
aWantsUntrusted = true;
@@ -11497,6 +11544,8 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
nsCOMPtr<nsIDOMStorage> istorage = changingStorage.get();
bool fireMozStorageChanged = false;
nsAutoString eventType;
eventType.AssignLiteral("storage");
principal = GetPrincipal();
if (!principal) {
return NS_OK;
@@ -11532,6 +11581,9 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
}
fireMozStorageChanged = mSessionStorage == changingStorage;
if (fireMozStorageChanged) {
eventType.AssignLiteral("MozSessionStorageChanged");
}
break;
}
@@ -11549,6 +11601,9 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
fireMozStorageChanged = mLocalStorage == changingStorage;
if (fireMozStorageChanged) {
eventType.AssignLiteral("MozLocalStorageChanged");
};
break;
}
default:
@@ -11558,11 +11613,8 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
// Clone the storage event included in the observer notification. We want
// to dispatch clones rather than the original event.
ErrorResult error;
RefPtr<StorageEvent> newEvent =
CloneStorageEvent(fireMozStorageChanged ?
NS_LITERAL_STRING("MozStorageChanged") :
NS_LITERAL_STRING("storage"),
event, error);
RefPtr<StorageEvent> newEvent = CloneStorageEvent(eventType,
event, error);
if (error.Failed()) {
return error.StealNSResult();
}
@@ -12376,6 +12428,12 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
// point anyway, and the script context should have already reported
// the script error in the usual way - so we just drop it.
// Since we might be processing more timeouts, go ahead and flush the promise
// queue now before we do that. We need to do that while we're still in our
// "running JS is safe" state (e.g. mRunningTimeout is set, timeout->mRunning
// is false).
Promise::PerformMicroTaskCheckpoint();
if (trackNestingLevel) {
sNestingLevel = nestingLevel;
}
@@ -12385,6 +12443,7 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
mRunningTimeout = last_running_timeout;
timeout->mRunning = false;
return timeout->mCleared;
}
@@ -12504,14 +12563,17 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
deadline = now;
}
// The timeout list is kept in deadline order. Discover the latest
// timeout whose deadline has expired. On some platforms, native
// timeout events fire "early", so we need to test the timer as well
// as the deadline.
// The timeout list is kept in deadline order. Discover the latest timeout
// whose deadline has expired. On some platforms, native timeout events fire
// "early", but we handled that above by setting deadline to aTimeout->mWhen
// if the timer fired early. So we can stop walking if we get to timeouts
// whose mWhen is greater than deadline, since once that happens we know
// nothing past that point is expired.
last_expired_timeout = nullptr;
for (nsTimeout *timeout = mTimeouts.getFirst(); timeout; timeout = timeout->getNext()) {
if (((timeout == aTimeout) || (timeout->mWhen <= deadline)) &&
(timeout->mFiringDepth == 0)) {
for (nsTimeout *timeout = mTimeouts.getFirst();
timeout && timeout->mWhen <= deadline;
timeout = timeout->getNext()) {
if (timeout->mFiringDepth == 0) {
// Mark any timeouts that are on the list to be fired with the
// firing depth so that we can reentrantly run timeouts
timeout->mFiringDepth = firingDepth;
@@ -13319,6 +13381,27 @@ nsGlobalWindow::DisableDeviceSensor(uint32_t aType)
}
}
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
void
nsGlobalWindow::EnableOrientationChangeListener()
{
MOZ_ASSERT(IsInnerWindow());
if (!mOrientationChangeObserver) {
mOrientationChangeObserver =
new WindowOrientationObserver(this);
}
}
void
nsGlobalWindow::DisableOrientationChangeListener()
{
MOZ_ASSERT(IsInnerWindow());
mOrientationChangeObserver = nullptr;
}
#endif
void
nsGlobalWindow::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
{
@@ -14150,6 +14233,14 @@ nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
}
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
int16_t
nsGlobalWindow::Orientation() const
{
return WindowOrientationObserver::OrientationAngle();
}
#endif
NS_IMETHODIMP
nsGlobalWindow::GetConsole(JSContext* aCx,
JS::MutableHandle<JS::Value> aConsole)
@@ -14385,7 +14476,7 @@ nsGlobalWindow::SetReplaceableWindowCoord(JSContext* aCx,
* just treat this the way we would an IDL replaceable property.
*/
nsGlobalWindow* outer = GetOuterWindowInternal();
if (!outer || !outer->CanMoveResizeWindows() || outer->IsFrame()) {
if (!outer || !outer->CanMoveResizeWindows(nsContentUtils::IsCallerChrome()) || outer->IsFrame()) {
RedefineProperty(aCx, aPropName, aValue, aError);
return;
}
+29 -36
View File
@@ -118,6 +118,9 @@ class RequestOrUSVString;
class Selection;
class SpeechSynthesis;
class WakeLock;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
class WindowOrientationObserver;
#endif
namespace cache {
class CacheStorage;
} // namespace cache
@@ -241,15 +244,6 @@ struct IdleObserverHolder
}
};
static inline already_AddRefed<nsIVariant>
CreateVoidVariant()
{
nsCOMPtr<nsIWritableVariant> writable =
do_CreateInstance(NS_VARIANT_CONTRACTID);
writable->SetAsVoid();
return writable.forget();
}
// Helper class to manage modal dialog arguments and all their quirks.
//
// Given our clunky embedding APIs, modal dialog arguments need to be passed
@@ -271,17 +265,7 @@ public:
DialogValueHolder(nsIPrincipal* aSubject, nsIVariant* aValue)
: mOrigin(aSubject)
, mValue(aValue) {}
nsresult Get(nsIPrincipal* aSubject, nsIVariant** aResult)
{
nsCOMPtr<nsIVariant> result;
if (aSubject->SubsumesConsideringDomain(mOrigin)) {
result = mValue;
} else {
result = CreateVoidVariant();
}
result.forget(aResult);
return NS_OK;
}
nsresult Get(nsIPrincipal* aSubject, nsIVariant** aResult);
void Get(JSContext* aCx, JS::Handle<JSObject*> aScope, nsIPrincipal* aSubject,
JS::MutableHandle<JS::Value> aResult, mozilla::ErrorResult& aError)
{
@@ -658,6 +642,11 @@ public:
virtual void EnableDeviceSensor(uint32_t aType) override;
virtual void DisableDeviceSensor(uint32_t aType) override;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
virtual void EnableOrientationChangeListener() override;
virtual void DisableOrientationChangeListener() override;
#endif
virtual void EnableTimeChangeNotifications() override;
virtual void DisableTimeChangeNotifications() override;
@@ -856,7 +845,7 @@ public:
void GetStatus(nsAString& aStatus, mozilla::ErrorResult& aError);
void SetStatusOuter(const nsAString& aStatus);
void SetStatus(const nsAString& aStatus, mozilla::ErrorResult& aError);
void CloseOuter();
void CloseOuter(bool aTrustedCaller);
void Close(mozilla::ErrorResult& aError);
bool GetClosedOuter();
bool GetClosed(mozilla::ErrorResult& aError);
@@ -980,14 +969,14 @@ public:
already_AddRefed<mozilla::dom::MediaQueryList> MatchMedia(const nsAString& aQuery,
mozilla::ErrorResult& aError);
nsScreen* GetScreen(mozilla::ErrorResult& aError);
void MoveToOuter(int32_t aXPos, int32_t aYPos, mozilla::ErrorResult& aError);
void MoveToOuter(int32_t aXPos, int32_t aYPos, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void MoveTo(int32_t aXPos, int32_t aYPos, mozilla::ErrorResult& aError);
void MoveByOuter(int32_t aXDif, int32_t aYDif, mozilla::ErrorResult& aError);
void MoveByOuter(int32_t aXDif, int32_t aYDif, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void MoveBy(int32_t aXDif, int32_t aYDif, mozilla::ErrorResult& aError);
void ResizeToOuter(int32_t aWidth, int32_t aHeight, mozilla::ErrorResult& aError);
void ResizeToOuter(int32_t aWidth, int32_t aHeight, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void ResizeTo(int32_t aWidth, int32_t aHeight,
mozilla::ErrorResult& aError);
void ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif, mozilla::ErrorResult& aError);
void ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
mozilla::ErrorResult& aError);
void Scroll(double aXScroll, double aYScroll);
@@ -1049,7 +1038,7 @@ public:
GetDefaultComputedStyle(mozilla::dom::Element& aElt,
const nsAString& aPseudoElt,
mozilla::ErrorResult& aError);
void SizeToContentOuter(mozilla::ErrorResult& aError);
void SizeToContentOuter(mozilla::ErrorResult& aError, bool aCallerIsChrome);
void SizeToContent(mozilla::ErrorResult& aError);
mozilla::dom::Crypto* GetCrypto(mozilla::ErrorResult& aError);
nsIControllers* GetControllersOuter(mozilla::ErrorResult& aError);
@@ -1209,27 +1198,27 @@ protected:
// And the implementations of WindowCoordGetter/WindowCoordSetter.
int32_t GetInnerWidthOuter(mozilla::ErrorResult& aError);
int32_t GetInnerWidth(mozilla::ErrorResult& aError);
void SetInnerWidthOuter(int32_t aInnerWidth, mozilla::ErrorResult& aError);
void SetInnerWidthOuter(int32_t aInnerWidth, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError);
int32_t GetInnerHeightOuter(mozilla::ErrorResult& aError);
int32_t GetInnerHeight(mozilla::ErrorResult& aError);
void SetInnerHeightOuter(int32_t aInnerHeight, mozilla::ErrorResult& aError);
void SetInnerHeightOuter(int32_t aInnerHeight, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void SetInnerHeight(int32_t aInnerHeight, mozilla::ErrorResult& aError);
int32_t GetScreenXOuter(mozilla::ErrorResult& aError);
int32_t GetScreenX(mozilla::ErrorResult& aError);
void SetScreenXOuter(int32_t aScreenX, mozilla::ErrorResult& aError);
void SetScreenXOuter(int32_t aScreenX, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void SetScreenX(int32_t aScreenX, mozilla::ErrorResult& aError);
int32_t GetScreenYOuter(mozilla::ErrorResult& aError);
int32_t GetScreenY(mozilla::ErrorResult& aError);
void SetScreenYOuter(int32_t aScreenY, mozilla::ErrorResult& aError);
void SetScreenYOuter(int32_t aScreenY, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void SetScreenY(int32_t aScreenY, mozilla::ErrorResult& aError);
int32_t GetOuterWidthOuter(mozilla::ErrorResult& aError);
int32_t GetOuterWidth(mozilla::ErrorResult& aError);
void SetOuterWidthOuter(int32_t aOuterWidth, mozilla::ErrorResult& aError);
void SetOuterWidthOuter(int32_t aOuterWidth, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void SetOuterWidth(int32_t aOuterWidth, mozilla::ErrorResult& aError);
int32_t GetOuterHeightOuter(mozilla::ErrorResult& aError);
int32_t GetOuterHeight(mozilla::ErrorResult& aError);
void SetOuterHeightOuter(int32_t aOuterHeight, mozilla::ErrorResult& aError);
void SetOuterHeightOuter(int32_t aOuterHeight, mozilla::ErrorResult& aError, bool aCallerIsChrome);
void SetOuterHeight(int32_t aOuterHeight, mozilla::ErrorResult& aError);
// Array of idle observers that are notified of idle events.
@@ -1463,8 +1452,8 @@ public:
// Outer windows only.
void EnsureReflowFlushAndPaint();
void CheckSecurityWidthAndHeight(int32_t* width, int32_t* height);
void CheckSecurityLeftAndTop(int32_t* left, int32_t* top);
void CheckSecurityWidthAndHeight(int32_t* width, int32_t* height, bool aCallerIsChrome);
void CheckSecurityLeftAndTop(int32_t* left, int32_t* top, bool aCallerIsChrome);
// Outer windows only.
// Arguments to this function should have values in app units
@@ -1477,7 +1466,7 @@ public:
static void MakeScriptDialogTitle(nsAString &aOutTitle);
// Outer windows only.
bool CanMoveResizeWindows();
bool CanMoveResizeWindows(bool aCallerIsChrome);
// If aDoFlush is true, we'll flush our own layout; otherwise we'll try to
// just flush our parent and only flush ourselves if we think we need to.
@@ -1490,7 +1479,7 @@ public:
nsresult GetInnerSize(mozilla::CSSIntSize& aSize);
nsIntSize GetOuterSize(mozilla::ErrorResult& aError);
void SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
mozilla::ErrorResult& aError);
mozilla::ErrorResult& aError, bool aCallerIsChrome);
nsRect GetInnerScreenRect();
void ScrollTo(const mozilla::CSSIntPoint& aScroll,
@@ -1826,6 +1815,10 @@ protected:
nsTArray<uint32_t> mEnabledSensors;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
nsAutoPtr<mozilla::dom::WindowOrientationObserver> mOrientationChangeObserver;
#endif
#ifdef MOZ_WEBSPEECH
// mSpeechSynthesis is only used on inner windows.
RefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;
+5
View File
@@ -630,6 +630,11 @@ public:
*/
virtual void DisableDeviceSensor(uint32_t aType) = 0;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
virtual void EnableOrientationChangeListener() = 0;
virtual void DisableOrientationChangeListener() = 0;
#endif
virtual void EnableTimeChangeNotifications() = 0;
virtual void DisableTimeChangeNotifications() = 0;
+3 -1
View File
@@ -358,6 +358,8 @@ skip-if = buildapp == 'mulet'
[test_window_extensible.html]
[test_window_indexing.html]
[test_window_named_frame_enumeration.html]
[test_window_orientation.html]
skip-if = toolkit != 'gonk'
[test_writable-replaceable.html]
[test_navigatorPrefOverride.html]
[test_EventSource_redirects.html]
@@ -710,7 +712,7 @@ support-files = referrerHelper.js
[test_classList.html]
# This test fails on the Mac for some reason
[test_copyimage.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows' || e10s #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || (toolkit != 'cocoa' && toolkit != 'gonk' && toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows') || e10s #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_copypaste.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 904183 # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
[test_copypaste.xhtml]
@@ -29,11 +29,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
.getService(SpecialPowers.Ci.nsIObserverService);
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "media-playback", false);
ok(true, "Observer set");
+1 -1
View File
@@ -99,7 +99,7 @@ function runTest() {
iframe.src = "data:text/html,page";
}
SpecialPowers.pushPrefEnv({ "set": [["media.useAudioChannelService", true]]}, runTest);
onload = runTest;
SimpleTest.waitForExplicitFinish();
</script>
+6 -2
View File
@@ -47,8 +47,7 @@ function hasExpectedFlavors() {
cb.kGlobalClipboard);
}
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function nextTest() {
function nextTest() {
var div = document.querySelector("#content>div");
if (!div) {
SimpleTest.finish();
@@ -69,6 +68,11 @@ SimpleTest.waitForFocus(function nextTest() {
ok(false, "failed to copy the expected content to the clipboard");
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
SpecialPowers.pushPrefEnv({"set": [["clipboard.plainTextOnly", false]]}, nextTest);
});
</script>
+52 -21
View File
@@ -1,6 +1,8 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=518249
https://bugzilla.mozilla.org/show_bug.cgi?id=952456
-->
<head>
<title>Test for copy image</title>
@@ -9,6 +11,7 @@
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=518249">Mozilla Bug 518249</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=952456">Mozilla Bug 952456</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
@@ -16,39 +19,67 @@
<script class="testbody" type="text/javascript">
function testCopyImage () {
// selection of the node
var Ci = SpecialPowers.Ci;
var Cc = SpecialPowers.Cc;
var clipboard = SpecialPowers.Services.clipboard;
function getClipboardData(mime) {
var transferable = Cc['@mozilla.org/widget/transferable;1']
.createInstance(Ci.nsITransferable);
var loadingContext = SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsILoadContext);
transferable.init(loadingContext);
transferable.addDataFlavor(mime);
clipboard.getData(transferable, 1);
var data = SpecialPowers.createBlankObject();
transferable.getTransferData(mime, data, {});
return data;
}
function testClipboardValue(mime, expected) {
var data = SpecialPowers.wrap(getClipboardData(mime));
var str = data.value == null ? data.value :
data.value.QueryInterface(Ci.nsISupportsString).data;
is(str, expected, "clipboard has correct [" + mime + "] content")
}
//--------- Prepare data and copy it.
// Select the node.
var node = document.getElementById('logo');
// Set node and copy image.
var webnav = SpecialPowers.wrap(window)
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
var docShell = webnav.QueryInterface(SpecialPowers.Ci.nsIDocShell);
docShell.chromeEventHandler.ownerDocument.popupNode = node;
// let's copy the node
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
var docShell = webnav.QueryInterface(Ci.nsIDocShell);
var documentViewer = docShell.contentViewer
.QueryInterface(SpecialPowers.Ci.nsIContentViewerEdit);
.QueryInterface(Ci.nsIContentViewerEdit);
documentViewer.setCommandNode(node);
documentViewer.copyImage(documentViewer.COPY_IMAGE_ALL);
//--------- now check the content of the clipboard
var clipboard = SpecialPowers.Cc["@mozilla.org/widget/clipboard;1"]
.getService(SpecialPowers.Ci.nsIClipboard);
// does the clipboard contain text/unicode data ?
//--------- Let's check the content of the clipboard now.
// Does the clipboard contain text/unicode data ?
ok(clipboard.hasDataMatchingFlavors(["text/unicode"], 1, clipboard.kGlobalClipboard), "clipboard contains unicode text");
// does the clipboard contain text/html data ?
// Does the clipboard contain text/html data ?
ok(clipboard.hasDataMatchingFlavors(["text/html"], 1, clipboard.kGlobalClipboard), "clipboard contains html text");
// does the clipboard contain image data ?
// Does the clipboard contain image data ?
ok(clipboard.hasDataMatchingFlavors(["image/png"], 1, clipboard.kGlobalClipboard), "clipboard contains image");
// Is the text/uncodie data correct ?
testClipboardValue('text/unicode', 'about:logo');
// Is the text/html data correct ?
testClipboardValue('text/html', '<img id="logo" src="about:logo">');
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(testCopyImage);
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["clipboard.plainTextOnly", false]]}, testCopyImage);
});
</script>
</pre>
@@ -38,10 +38,6 @@ video.onplay = video.onpause = function() {
};
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "media-playback", false);
ok(true, "Observer set");
@@ -34,10 +34,6 @@ var audio = new Audio();
audio.loop = true;
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "media-playback", false);
ok(true, "Observer set");
@@ -34,10 +34,6 @@ var audio = new Audio();
audio.loop = true;
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "media-playback", false);
ok(true, "Observer set");
@@ -34,10 +34,6 @@ var audio = new Audio();
audio.loop = true;
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "media-playback", false);
ok(true, "Observer set");
@@ -62,11 +62,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
.getService(SpecialPowers.Ci.nsIObserverService);
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "media-playback", false);
ok(true, "Observer set");
+3 -1
View File
@@ -31,7 +31,9 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");
runTest();
},
function() {
@@ -29,11 +29,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
.getService(SpecialPowers.Ci.nsIObserverService);
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "media-playback", false);
ok(true, "Observer set");
@@ -12,7 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443
/** Test for Bug 1107443 **/
try {
Object.defineProperty(window, "nosuchprop", { value: 5 });
Object.defineProperty(window, "nosuchprop", { value: 5, configurable: false });
throw "didn't throw";
} catch (e) {
is(e instanceof TypeError, true,
@@ -22,9 +22,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443
'Window should not have property after an attempt to define it failed');
}
Object.defineProperty(window, "nosuchprop", { value: 7, configurable: true });
Object.defineProperty(window, "nosuchprop", { value: 6 });
var desc = Object.getOwnPropertyDescriptor(window, "nosuchprop");
is(typeof(desc), "object", "Should have a property now");
todo_is(desc.configurable, true, "Property should be configurable");
is(desc.writable, false, "Property should be readonly");
is(desc.value, 6, "Property should have the right value");
Object.defineProperty(window, "nosuchprop2", { value: 7, configurable: true });
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop2");
is(typeof(desc), "object", "Should have a property now");
is(desc.configurable, true, "Property should be configurable");
is(desc.writable, false, "Property should be readonly");
is(desc.value, 7, "Property should have the right value");
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for window.orientation</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="orientationcommon.js"></script>
<div id="log"></div>
<script>
async_test(function(t) {
var originalOrientation = screen.orientation.type;
var alternateOrientation = originalOrientation == "portrait-primary" ?
"landscape-primary" : "portrait-primary";
var originalWindowOrientation = window.orientation;
window.onorientationchange = function() {
t.step(function() { assert_not_equals(window.orientation, originalWindowOrientation); });
var p2 = specialPowersUnlock();
p2.then(function() {
t.done();
}).catch(t.step_func(function(err) {
assert_unreached("Error unlocking orientation: " + err);
t.done();
}));
}
var p1 = specialPowersLock(alternateOrientation);
p1.catch(t.step_func(function(err) {
assert_unreached("Error locking orientation: " + err);
t.done();
}));
}, "Test window.orientation and orientationchange.");
</script>
+10
View File
@@ -83,6 +83,16 @@ public:
return result;
}
void MarkForCC()
{
if (mCallback) {
JS::ExposeObjectToActiveJS(mCallback);
}
if (mCreationStack) {
JS::ExposeObjectToActiveJS(mCreationStack);
}
}
/*
* This getter does not change the color of the JSObject meaning that the
* object returned is not guaranteed to be kept alive past the next CC.
@@ -7,15 +7,21 @@
#include "mozilla/Services.h"
#include "mozilla/dom/BrowserElementAudioChannelBinding.h"
#include "mozilla/dom/DOMRequest.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/ToJSValue.h"
#include "AudioChannelService.h"
#include "nsIBrowserElementAPI.h"
#include "nsIDocShell.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDOMRequest.h"
#include "nsIObserverService.h"
#include "nsISupportsPrimitives.h"
#include "nsISystemMessagesInternal.h"
#include "nsITabParent.h"
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h"
namespace {
@@ -50,28 +56,36 @@ BrowserElementAudioChannel::Create(nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel,
const nsAString& aManifestURL,
ErrorResult& aRv)
{
RefPtr<BrowserElementAudioChannel> ac =
new BrowserElementAudioChannel(aWindow, aFrameLoader, aAPI, aAudioChannel);
new BrowserElementAudioChannel(aWindow, aFrameLoader, aAPI,
aAudioChannel, aManifestURL);
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(
nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel)
nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel,
const nsAString& aManifestURL)
: DOMEventTargetHelper(aWindow)
, mFrameLoader(aFrameLoader)
, mBrowserElementAPI(aAPI)
, mAudioChannel(aAudioChannel)
, mManifestURL(aManifestURL)
, mState(eStateUnknown)
{
MOZ_ASSERT(NS_IsMainThread());
@@ -189,7 +203,9 @@ public:
NS_IMETHODIMP Run() override
{
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
if (!service) {
return NS_OK;
}
AutoJSAPI jsapi;
if (!jsapi.Init(mParentWindow)) {
@@ -302,6 +318,43 @@ protected:
}
};
class RespondSuccessHandler final : public PromiseNativeHandler
{
public:
NS_DECL_ISUPPORTS
explicit RespondSuccessHandler(DOMRequest* aRequest)
: mDomRequest(aRequest)
{};
virtual void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
virtual void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
private:
~RespondSuccessHandler() {};
RefPtr<DOMRequest> mDomRequest;
};
NS_IMPL_ISUPPORTS0(RespondSuccessHandler);
void
RespondSuccessHandler::ResolvedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
JS::Rooted<JS::Value> value(aCx);
mDomRequest->FireSuccess(value);
}
void
RespondSuccessHandler::RejectedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
mDomRequest->FireError(NS_ERROR_FAILURE);
}
} // anonymous namespace
already_AddRefed<dom::DOMRequest>
@@ -349,9 +402,9 @@ BrowserElementAudioChannel::SetVolume(float aVolume, ErrorResult& aRv)
}
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
service->SetAudioChannelVolume(mFrameWindow, mAudioChannel, aVolume);
if (service) {
service->SetAudioChannelVolume(mFrameWindow, mAudioChannel, aVolume);
}
RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner());
nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(),
@@ -408,9 +461,9 @@ BrowserElementAudioChannel::SetMuted(bool aMuted, ErrorResult& aRv)
}
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
service->SetAudioChannelMuted(mFrameWindow, mAudioChannel, aMuted);
if (service) {
service->SetAudioChannelMuted(mFrameWindow, mAudioChannel, aMuted);
}
RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner());
nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(),
@@ -459,6 +512,62 @@ BrowserElementAudioChannel::IsActive(ErrorResult& aRv)
return domRequest.forget();
}
already_AddRefed<dom::DOMRequest>
BrowserElementAudioChannel::NotifyChannel(const nsAString& aEvent,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess());
if (!mFrameWindow) {
nsCOMPtr<nsIDOMDOMRequest> request;
aRv = mBrowserElementAPI->NotifyChannel(aEvent, mManifestURL,
(uint32_t)mAudioChannel,
getter_AddRefs(request));
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return request.forget().downcast<DOMRequest>();
}
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
do_GetService("@mozilla.org/system-message-internal;1");
MOZ_ASSERT(systemMessenger);
AutoJSAPI jsAPI;
if (!jsAPI.Init(GetOwner())) {
return nullptr;
}
JS::Rooted<JS::Value> value(jsAPI.cx());
value.setInt32((uint32_t)mAudioChannel);
nsCOMPtr<nsIURI> manifestURI;
nsresult rv = NS_NewURI(getter_AddRefs(manifestURI), mManifestURL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
// Since the pageURI of the app has been registered to the system messager,
// when the app was installed. The system messager can only use the manifest
// to send the message to correct page.
nsCOMPtr<nsISupports> promise;
rv = systemMessenger->SendMessage(aEvent, value, nullptr, manifestURI,
JS::UndefinedHandleValue,
getter_AddRefs(promise));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
RefPtr<Promise> promiseIns = static_cast<Promise*>(promise.get());
RefPtr<DOMRequest> request = new DOMRequest(GetOwner());
RefPtr<RespondSuccessHandler> handler = new RespondSuccessHandler(request);
promiseIns->AppendNativeHandler(handler);
return request.forget();
}
NS_IMETHODIMP
BrowserElementAudioChannel::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
@@ -505,6 +614,10 @@ BrowserElementAudioChannel::Observe(nsISupports* aSubject, const char* aTopic,
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"));
@@ -40,6 +40,7 @@ public:
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel,
const nsAString& aManifestURL,
ErrorResult& aRv);
// WebIDL methods
@@ -57,13 +58,17 @@ public:
already_AddRefed<dom::DOMRequest> IsActive(ErrorResult& aRv);
already_AddRefed<dom::DOMRequest> NotifyChannel(const nsAString& aEvent,
ErrorResult& aRv);
IMPL_EVENT_HANDLER(activestatechanged);
private:
BrowserElementAudioChannel(nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel);
AudioChannel aAudioChannel,
const nsAString& aManifestURL);
~BrowserElementAudioChannel();
@@ -76,6 +81,7 @@ private:
nsCOMPtr<nsITabParent> mTabParent;
nsCOMPtr<nsPIDOMWindow> mFrameWindow;
AudioChannel mAudioChannel;
nsString mManifestURL;
enum {
eStateActive,
+267 -70
View File
@@ -8,18 +8,28 @@ dump("######################## BrowserElementChildPreload.js loaded\n");
var BrowserElementIsReady = false;
let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
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/Microformats.js");
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");
let kLongestReturnedString = 128;
var kLongestReturnedString = 128;
const Timer = Components.Constructor("@mozilla.org/timer;1",
"nsITimer",
"initWithCallback");
function debug(msg) {
//dump("BrowserElementChildPreload - " + msg + "\n");
@@ -53,19 +63,23 @@ function sendSyncMsg(msg, data) {
return sendSyncMessage('browser-element-api:call', data);
}
let CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
var CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
const OBSERVED_EVENTS = [
'fullscreen-origin-change',
'ask-parent-to-exit-fullscreen',
'ask-parent-to-rollback-fullscreen',
'xpcom-shutdown',
'activity-done'
'activity-done',
'invalid-widget',
'will-launch-app'
];
const COMMAND_MAP = {
'cut': 'cmd_cut',
'copy': 'cmd_copyAndCollapseToEnd',
'copyImage': 'cmd_copyImage',
'copyLink': 'cmd_copyLink',
'paste': 'cmd_paste',
'selectall': 'cmd_selectAll'
};
@@ -83,6 +97,38 @@ const COMMAND_MAP = {
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 = {};
@@ -102,6 +148,8 @@ function BrowserElementChild() {
this._pendingSetInputMethodActive = [];
this._selectionStateChangedTarget = null;
this.forwarder = new BrowserElementProxyForwarder();
this._init();
};
@@ -119,8 +167,7 @@ BrowserElementChild.prototype = {
.addProgressListener(this._progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_SECURITY |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
Ci.nsIWebProgress.NOTIFY_PROGRESS);
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
docShell.QueryInterface(Ci.nsIWebNavigation)
.sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
@@ -238,7 +285,8 @@ BrowserElementChild.prototype = {
"get-audio-channel-muted": this._recvGetAudioChannelMuted,
"set-audio-channel-muted": this._recvSetAudioChannelMuted,
"get-is-audio-channel-active": this._recvIsAudioChannelActive,
"get-structured-data": this._recvGetStructuredData
"get-structured-data": this._recvGetStructuredData,
"get-web-manifest": this._recvGetWebManifest,
}
addMessageListener("browser-element-api:call", function(aMessage) {
@@ -271,12 +319,18 @@ BrowserElementChild.prototype = {
OBSERVED_EVENTS.forEach((aTopic) => {
Services.obs.addObserver(this, aTopic, false);
});
this.forwarder.init();
},
_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' && (!content || subject != content.document))
if (topic !== 'activity-done' &&
topic !== 'audio-playback' &&
topic !== 'will-launch-app' &&
(!content || subject !== content.document)) {
return;
if (topic == 'activity-done' && docShell !== subject)
return;
@@ -296,9 +350,34 @@ BrowserElementChild.prototype = {
case 'xpcom-shutdown':
this._shuttingDown = true;
break;
case 'invalid-widget':
sendAsyncMsg('error', { type: 'invalid-widget' });
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;
},
/**
* Called when our TabChildGlobal starts to die. This is not called when the
* page inside |content| unloads.
@@ -308,6 +387,9 @@ BrowserElementChild.prototype = {
OBSERVED_EVENTS.forEach((aTopic) => {
Services.obs.removeObserver(this, aTopic);
});
this.forwarder.uninit();
this.forwarder = null;
},
_tryGetInnerWindowID: function(win) {
@@ -542,32 +624,42 @@ BrowserElementChild.prototype = {
return;
}
if (!e.target.name) {
var name = e.target.name;
var property = e.target.getAttributeNS(null, "property");
if (!name && !property) {
return;
}
debug('Got metaChanged: (' + e.target.name + ') ' + e.target.content);
debug('Got metaChanged: (' + (name || property) + ') ' +
e.target.content);
let handlers = {
'viewmode': this._viewmodeChangedHandler,
'theme-color': this._themeColorChangedHandler,
'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;
}
let handler = handlers[e.target.name];
if (handler) {
handler(e.type, e.target);
handler(name, e.type, e.target);
}
},
_applicationNameChangedHandler: function(eventType, 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: 'application-name',
let meta = { name: name,
content: target.content };
let lang;
@@ -608,13 +700,25 @@ BrowserElementChild.prototype = {
},
_ClickHandler: function(e) {
let elem = e.target;
if (elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) {
// Open in a new tab if middle click or ctrl/cmd-click.
if ((Services.appinfo.OS == 'Darwin' && e.metaKey) ||
(Services.appinfo.OS != 'Darwin' && e.ctrlKey) ||
e.button == 1) {
sendAsyncMsg('opentab', {url: elem.href});
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});
}
}
},
@@ -710,19 +814,9 @@ BrowserElementChild.prototype = {
sendAsyncMsg('selectionstatechanged', detail);
},
_viewmodeChangedHandler: function(eventType, target) {
_genericMetaHandler: function(name, eventType, target) {
let meta = {
name: 'viewmode',
content: target.content,
type: eventType.replace('DOMMeta', '').toLowerCase()
};
sendAsyncMsg('metachange', meta);
},
_themeColorChangedHandler: function(eventType, target) {
let meta = {
name: 'theme-color',
name: name,
content: target.content,
type: eventType.replace('DOMMeta', '').toLowerCase()
};
@@ -826,6 +920,18 @@ BrowserElementChild.prototype = {
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);
@@ -839,16 +945,31 @@ BrowserElementChild.prototype = {
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) {
var menu = e.target.ownerDocument.getElementById(ctxMenuId);
if (menu) {
menuData.contextmenu = this._buildMenuObj(menu, '');
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.
//
@@ -863,7 +984,7 @@ BrowserElementChild.prototype = {
},
_getSystemCtxMenuData: function(elem) {
let documentURI =
let documentURI =
docShell.QueryInterface(Ci.nsIWebNavigation).currentURI.spec;
if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
@@ -1054,10 +1175,9 @@ BrowserElementChild.prototype = {
},
_mozScrollAreaChanged: function(e) {
let dimensions = this._getContentDimensions();
sendAsyncMsg('scrollareachanged', {
width: dimensions.width,
height: dimensions.height
width: e.width,
height: e.height
});
},
@@ -1162,31 +1282,58 @@ BrowserElementChild.prototype = {
_recvFireCtxCallback: function(data) {
debug("Received fireCtxCallback message: (" + data.json.menuitem + ")");
// We silently ignore if the embedder uses an incorrect id in the callback
if (data.json.menuitem in this._ctxHandlers) {
if (data.json.menuitem == 'copy-image') {
// Set command
data.json.command = 'copyImage';
this._recvDoCommand(data);
} else if (data.json.menuitem == 'copy-link') {
// Set command
data.json.command = 'copyLink';
this._recvDoCommand(data);
} 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) {
var menuObj = {type: 'menu', items: []};
this._maybeCopyAttribute(menu, menuObj, 'label');
_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 + '_'));
} 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);
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;
},
@@ -1222,6 +1369,11 @@ BrowserElementChild.prototype = {
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();
}
}
},
@@ -1377,7 +1529,26 @@ BrowserElementChild.prototype = {
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) {
try {
@@ -1908,33 +2079,59 @@ BrowserElementChild.prototype = {
return;
}
var stateDesc;
var securityStateDesc;
if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
stateDesc = 'secure';
securityStateDesc = 'secure';
}
else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
stateDesc = 'broken';
securityStateDesc = 'broken';
}
else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
stateDesc = 'insecure';
securityStateDesc = 'insecure';
}
else {
debug("Unexpected securitychange state!");
stateDesc = '???';
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: stateDesc, extendedValidation: isEV });
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) {
sendAsyncMsg('loadprogresschanged', { curTotalProgress: curTotalProgress,
maxTotalProgress: maxTotalProgress });
},
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
},
// Expose the message manager for WebApps and others.
+210 -8
View File
@@ -23,6 +23,10 @@ XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function () {
return DOMApplicationRegistry;
});
XPCOMUtils.defineLazyServiceGetter(this, "systemMessenger",
"@mozilla.org/system-message-internal;1",
"nsISystemMessagesInternal");
function debug(msg) {
//dump("BrowserElementParent - " + msg + "\n");
}
@@ -76,6 +80,177 @@ function defineDOMRequestMethod(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", "selectionstatechanged", "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 'setNFCFocus':
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;
@@ -89,6 +264,8 @@ function BrowserElementParent() {
Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true);
Services.obs.addObserver(this, 'ask-children-to-execute-copypaste-command', /* ownsWeak = */ true);
this.proxyCallHandler = new BrowserElementParentProxyCallHandler();
}
BrowserElementParent.prototype = {
@@ -131,6 +308,9 @@ BrowserElementParent.prototype = {
BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this);
this._setupMessageListener();
this._registerAppManifest();
this.proxyCallHandler.init(
this._frameElement, this._frameLoader.messageManager);
},
_runPendingAPICall: function() {
@@ -189,7 +369,6 @@ BrowserElementParent.prototype = {
"hello": this._recvHello,
"loadstart": this._fireProfiledEventFromMsg,
"loadend": this._fireProfiledEventFromMsg,
"loadprogresschanged": this._fireEventFromMsg,
"close": this._fireEventFromMsg,
"error": this._fireEventFromMsg,
"firstpaint": this._fireProfiledEventFromMsg,
@@ -218,7 +397,8 @@ BrowserElementParent.prototype = {
"got-audio-channel-muted": this._gotDOMRequestResult,
"got-set-audio-channel-muted": this._gotDOMRequestResult,
"got-is-audio-channel-active": this._gotDOMRequestResult,
"got-structured-data": this._gotDOMRequestResult
"got-structured-data": this._gotDOMRequestResult,
"got-web-manifest": this._gotDOMRequestResult,
};
let mmSecuritySensitiveCalls = {
@@ -290,7 +470,8 @@ BrowserElementParent.prototype = {
/* username and password */
let detail = {
host: authDetail.host,
realm: authDetail.realm
realm: authDetail.realm,
isProxy: authDetail.isProxy
};
evt = this._createEvent('usernameandpasswordrequired', detail,
@@ -741,7 +922,7 @@ BrowserElementParent.prototype = {
if (!this._isAlive()) {
return null;
}
let uri = Services.io.newURI(_url, null, null);
let url = uri.QueryInterface(Ci.nsIURL);
@@ -831,7 +1012,7 @@ BrowserElementParent.prototype = {
Ci.nsIRequestObserver])
};
// If we have a URI we'll use it to get the triggering principal to use,
// If we have a URI we'll use it to get the triggering principal to use,
// if not available a null principal is acceptable.
let referrer = null;
let principal = null;
@@ -854,9 +1035,9 @@ BrowserElementParent.prototype = {
debug('Using principal? ' + !!principal);
let channel =
let channel =
Services.io.newChannelFromURI2(url,
null, // No document.
null, // No document.
principal, // Loading principal
principal, // Triggering principal
Ci.nsILoadInfo.SEC_NORMAL,
@@ -877,7 +1058,7 @@ BrowserElementParent.prototype = {
channel.loadFlags |= flags;
if (channel instanceof Ci.nsIHttpChannel) {
debug('Setting HTTP referrer = ' + (referrer && referrer.spec));
debug('Setting HTTP referrer = ' + (referrer && referrer.spec));
channel.referrer = referrer;
if (channel instanceof Ci.nsIHttpChannelInternal) {
channel.forceAllowThirdPartyCookie = true;
@@ -1036,8 +1217,29 @@ BrowserElementParent.prototype = {
{audioChannel: aAudioChannel});
},
notifyChannel: function(aEvent, aManifest, aAudioChannel) {
var self = this;
var req = Services.DOMRequest.createRequest(self._window);
// Since the pageURI of the app has been registered to the system messager,
// when the app was installed. The system messager can only use the manifest
// to send the message to correct page.
let manifestURL = Services.io.newURI(aManifest, null, null);
systemMessenger.sendMessage(aEvent, aAudioChannel, null, manifestURL)
.then(function() {
Services.DOMRequest.fireSuccess(req,
Cu.cloneInto(true, self._window));
}, function() {
debug("Error : NotifyChannel fail.");
Services.DOMRequest.fireErrorAsync(req,
Cu.cloneInto("NotifyChannel fail.", self._window));
});
return req;
},
getStructuredData: defineDOMRequestMethod('get-structured-data'),
getWebManifest: defineDOMRequestMethod('get-web-manifest'),
/**
* Called when the visibility of the window which owns this iframe changes.
*/
@@ -383,17 +383,46 @@ BrowserElementAuthPrompt.prototype = {
host: hostname,
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 = this._getFormattedHostname(channel.URI);
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.
let realm = authInfo.realm;
realm = authInfo.realm;
if (!realm)
realm = hostname;
+220
View File
@@ -0,0 +1,220 @@
/* 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'),
setNFCFocus: defineNoReturnMethod('setNFCFocus'),
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]);
@@ -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}
+78
View File
@@ -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));
@@ -57,6 +57,10 @@ const browserElementTestHelpers = {
);
},
setClipboardPlainTextOnlyPref: function(value) {
this._setPref('clipboard.plainTextOnly', value);
},
setEnabledPref: function(value) {
this._setPref('dom.mozBrowserFramesEnabled', value);
},
@@ -9,8 +9,6 @@ SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
SpecialPowers.setBoolPref("media.useAudioChannelService", true);
function noaudio() {
var iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
@@ -66,11 +66,12 @@ function testHttpAuth(e) {
iframe.removeEventListener("mozbrowsertitlechange", onTitleChange);
iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail);
is(e.detail, 'http auth success', 'expect authentication to succeed');
SimpleTest.executeSoon(testAuthJarNoInterfere);
SimpleTest.executeSoon(testProxyAuth);
});
is(e.detail.realm, 'http_realm', 'expected realm matches');
is(e.detail.host, 'http://test', 'expected host matches');
is(e.detail.isProxy, false, 'expected isProxy is false');
e.preventDefault();
SimpleTest.executeSoon(function() {
@@ -78,6 +79,74 @@ function testHttpAuth(e) {
});
}
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.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 ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
var pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"]
.getService();
var systemPrincipal = SpecialPowers.Services.scriptSecurityManager
.getSystemPrincipal();
var channel = ioService.newChannel2(testingSJS,
null,
null,
null,
systemPrincipal,
null,
SpecialPowers.Ci.nsILoadInfo.SEC_NORMAL,
SpecialPowers.Ci.nsIContentPolicy.TYPE_OTHER);
pps.asyncResolve(channel, 0, resolveCallback);
}
function testAuthJarNoInterfere(e) {
var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1']
.getService(SpecialPowers.Ci.nsIHttpAuthManager);
@@ -2,10 +2,11 @@
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.setClipboardPlainTextOnlyPref(false);
browserElementTestHelpers.addPermission();
let audioUrl = 'http://mochi.test:8888/tests/dom/browser-element/mochitest/audio.ogg';
let videoUrl = 'http://mochi.test:8888/tests/dom/browser-element/mochitest/short-video.ogv';
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() {
@@ -24,7 +25,12 @@ function checkEmptyContextMenu() {
function checkInnerContextMenu() {
sendContextMenuTo('#inner-link', function onContextMenu(detail) {
is(detail.systemTargets.length, 1, 'Includes anchor data');
is(detail.contextmenu.items.length, 2, 'Inner clicks trigger correct menu');
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');
@@ -47,9 +53,19 @@ function checkNestedContextMenu() {
var innerMenu = detail.contextmenu.items.filter(function(x) {
return x.type === 'menu';
});
is(detail.systemTargets.length, 2, 'Includes anchor and img data');
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();
});
}
@@ -131,6 +147,9 @@ function checkImageContextMenu() {
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);
@@ -265,7 +284,7 @@ function createIframe(callback) {
'</menu>' +
'<menu type="context" id="menu2" label="secondmenu">' +
'<menuitem label="outer" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
'<menu>' +
'<menu label="submenu">' +
'<menuitem label="inner 1"></menuitem>' +
'<menuitem label="inner 2" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
'</menu>' +
@@ -13,8 +13,7 @@ function runTest() {
// Load emptypage1 into the iframe, wait for that to finish loading, then
// call runTest2.
//
// This should trigger loadstart, locationchange, loadprogresschanged and
// loadend events.
// This should trigger loadstart, locationchange, and loadend events.
var seenLoadEnd = false;
var seenLoadStart = false;
@@ -75,7 +74,6 @@ function runTest2() {
var seenLoadStart = false;
var seenLoadEnd = false;
var seenLocationChange = false;
var seenLoadProgressChanged = false;
// Add this event listener to the document; the events should bubble.
document.addEventListener('mozbrowserloadstart', function(e) {
@@ -105,14 +103,6 @@ function runTest2() {
is(e.detail.backgroundColor, 'transparent', 'Expected background color reported')
});
iframe.addEventListener('mozbrowserloadprogresschanged', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
seenLoadProgressChanged = true;
ok(seenLoadStart, 'Load end after load start.');
ok(seenLocationChange, 'Load end after location change.');
ok(!seenLoadEnd, 'Load end after load progress.');
});
iframe.src = browserElementTestHelpers.emptyPage2;
function waitForAllCallbacks() {
@@ -24,6 +24,10 @@ 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');
@@ -131,6 +135,26 @@ function runTest() {
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 {
@@ -0,0 +1,118 @@
"use strict";
SimpleTest.waitForExplicitFinish();
const { classes: Cc, interfaces: Ci } = Components;
const systemMessenger = Cc["@mozilla.org/system-message-internal;1"]
.getService(Ci.nsISystemMessagesInternal);
const ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var tests = [false /* INPROC */, true /* OOP */];
var rootURI = "http://test/chrome/dom/browser-element/mochitest/";
var manifestURI = rootURI + "manifest.webapp";
var srcURI = rootURI + "file_browserElement_NotifyChannel.html";
var generator = runTests();
var app = null;
addLoadEvent(() => {
SpecialPowers.pushPermissions(
[{ "type": "webapps-manage", "allow": 1, "context": document },
{ "type": "browser", "allow": 1, "context": document },
{ "type": "embed-apps", "allow": 1, "context": document }],
function() {
SpecialPowers.pushPrefEnv(
{'set': [["dom.mozBrowserFramesEnabled", true],
["dom.sysmsg.enabled", true]]},
() => { generator.next(); })
});
});
function error(message) {
ok(false, message);
SimpleTest.finish();
}
function continueTest() {
try {
generator.next();
} catch (e if e instanceof StopIteration) {
error("Stop test because of exception!");
}
}
function registerPage(aEvent) {
systemMessenger.registerPage(aEvent,
ioService.newURI(srcURI, null, null),
ioService.newURI(manifestURI, null, null));
}
function runTest(aEnable) {
var request = navigator.mozApps.install(manifestURI, {});
request.onerror = () => {
error("Install app failed!");
};
request.onsuccess = () => {
app = request.result;
ok(app, "App is installed. remote = " + aEnable);
is(app.manifestURL, manifestURI, "App manifest url is correct.");
var iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', true);
iframe.setAttribute('remote', aEnable);
iframe.setAttribute('mozapp', manifestURI);
iframe.src = srcURI;
document.body.appendChild(iframe);
iframe.addEventListener('mozbrowserloadend', () => {
var channels = iframe.allowedAudioChannels;
is(channels.length, 1, "1 audio channel by default");
var ac = channels[0];
ok(ac instanceof BrowserElementAudioChannel, "Correct class");
ok("notifyChannel" in ac, "ac.notifyChannel exists");
var message = "audiochannel-interruption-begin";
registerPage(message);
ac.notifyChannel(message);
iframe.addEventListener("mozbrowsershowmodalprompt", function (e) {
is(e.detail.message, message,
"App got audiochannel-interruption-begin.");
if (app) {
request = navigator.mozApps.mgmt.uninstall(app);
app = null;
request.onerror = () => {
error("Uninstall app failed!");
};
request.onsuccess = () => {
is(request.result, manifestURI, "App uninstalled.");
runNextTest();
}
}
});
});
};
}
function runNextTest() {
if (tests.length) {
var isEnabledOOP = tests.shift();
runTest(isEnabledOOP);
} else {
SimpleTest.finish();
}
}
function runTests() {
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.autoConfirmAppInstall(continueTest);
yield undefined;
SpecialPowers.autoConfirmAppUninstall(continueTest);
yield undefined;
runNextTest();
yield undefined;
}
@@ -51,7 +51,7 @@ function runTest() {
iframe.sendMouseEvent('mouseup', x, y, 1, 1, 0);
}
let onMiddleClick= e => {
let onMiddleClick = e => {
is(e.detail.url, 'http://example.com/', 'URL matches');
iframe.removeEventListener('mozbrowseropentab', onMiddleClick);
SimpleTest.finish();
@@ -63,7 +63,7 @@ function runTest() {
});
iframe.src = 'data:text/html,<body style="margin:0"><a href="http://example.com">click here</a></body>';
iframe.src = 'data:text/html,<body style="margin:0"><a href="http://example.com"><span>click here</span></a></body>';
}
addEventListener('testready', runTest);
@@ -0,0 +1,161 @@
/* 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,
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
isInBrowserElement: true
}
},{
type: 'browser',
allow: true,
context: {
url: frameUrl,
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
isInBrowserElement: 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);
@@ -9,6 +9,9 @@ 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');
@@ -23,21 +26,37 @@ function runTest() {
var count = 0;
iframe.addEventListener('mozbrowserloadend', function(e) {
count++;
var nextURL;
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();
}
});
@@ -46,4 +65,18 @@ function runTest() {
document.body.appendChild(iframe);
}
addEventListener('testready', runTest);
addEventListener('testready', function() {
SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
SpecialPowers.pushPrefEnv({"set" : [
["privacy.trackingprotection.enabled", true],
["privacy.trackingprotection.pbmode.enabled", false],
["browser.safebrowsing.enabled", false],
["browser.safebrowsing.malware.enabled", false],
]}, () => {
SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
UrlClassifierTestUtils.addTestTrackers().then(() => {
runTest();
});
});
});
@@ -43,6 +43,20 @@ function runTest() {
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);";
@@ -50,7 +64,7 @@ function runTest() {
break;
}
case 2: {
case 3: {
is(detail.name, 'theme-color', 'name matches');
is(detail.content, 'green', 'content matches');
is(detail.type, 'removed', 'type matches');
@@ -0,0 +1,111 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*globals async, is, SimpleTest, browserElementTestHelpers*/
// Bug 119580 - getStructuredData tests
'use strict';
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
const EMPTY_URL = 'file_empty.html';
const MICRODATA_URL = 'file_microdata.html';
const MICRODATA_ITEMREF_URL = 'file_microdata_itemref.html';
const MICRODATA_BAD_ITEMREF_URL = 'file_microdata_bad_itemref.html';
const MICROFORMATS_URL = 'file_microformats.html';
var test1 = async(function* () {
var structuredData = yield requestStructuredData(EMPTY_URL);
is(structuredData.items && structuredData.items.length, 0,
'There should be 0 items.');
});
var test2 = async(function* () {
var structuredData = yield requestStructuredData(MICRODATA_URL);
is(structuredData.items && structuredData.items.length, 2,
'There should be two items.');
is(structuredData.items[0].type[0], 'http://schema.org/Recipe',
'Can get item type.');
is(structuredData.items[0].properties['datePublished'][0], '2009-05-08',
'Can get item property.');
is(structuredData.items[1]
.properties["aggregateRating"][0]
.properties["ratingValue"][0],
'4', 'Can get nested item property.');
});
var test3 = async(function* () {
var structuredData = yield requestStructuredData(MICROFORMATS_URL);
is(structuredData.items && structuredData.items.length, 2,
'There should be two items.');
is(structuredData.items[0].type[0], 'http://microformats.org/profile/hcard',
'Got hCard object.');
is(structuredData.items[0]
.properties["adr"][0]
.properties["country-name"][0],
'France', 'Can read hCard properties.');
is(structuredData.items[0]
.properties["adr"][0]
.properties["type"]
.includes('home') &&
structuredData.items[0]
.properties["adr"][0]
.properties["type"]
.includes('postal'),
true, 'Property can contain multiple values.');
is(structuredData.items[0]
.properties["geo"][0],
'48.816667;2.366667', 'Geo value is formatted as per WHATWG spec.');
is(structuredData.items[1].type[0],
'http://microformats.org/profile/hcalendar#vevent',
'Got hCalendar object.');
is(structuredData.items[1]
.properties["dtstart"][0],
'2005-10-05', 'Can read hCalendar properties');
});
var test4 = async(function* () {
var structuredData = yield requestStructuredData(MICRODATA_ITEMREF_URL);
is(structuredData.items[0].properties["license"][0],
'http://www.opensource.org/licenses/mit-license.php', 'itemref works.');
is(structuredData.items[1].properties["license"][0],
'http://www.opensource.org/licenses/mit-license.php',
'Two items can successfully share an itemref.');
});
var test5 = async(function* () {
var structuredData = yield requestStructuredData(MICRODATA_BAD_ITEMREF_URL);
is(structuredData.items[0]
.properties["band"][0]
.properties["cycle"][0]
.properties["band"][0],
'ERROR', 'Cyclic reference should be detected as an error.');
});
Promise
.all([test1(), test2(), test3(), test4(), test5()])
.then(SimpleTest.finish);
function requestStructuredData(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.getStructuredData();
req.onsuccess = (ev) => {
document.body.removeChild(iframe);
resolve(JSON.parse(req.result));
};
req.onerror = (ev) => {
document.body.removeChild(iframe);
reject(new Error(req.error));
};
});
});
});
}
@@ -0,0 +1,65 @@
/* 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);
browserElementTestHelpers.addPermission();
// 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));
};
});
});
});
}
+10
View File
@@ -0,0 +1,10 @@
[DEFAULT]
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
support-files =
browserElement_NotifyChannel.js
file_browserElement_NotifyChannel.html
manifest.webapp
manifest.webapp^headers^
[test_browserElement_NotifyChannel.html]
@@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test of browser element audio channel method, notifyChannel</title>
</head>
<body>
<script type="application/javascript;version=1.8">
"use strict";
navigator.mozSetMessageHandler('audiochannel-interruption-begin',
function (e) {
alert("audiochannel-interruption-begin");
});
</script>
</body>
</html>
@@ -1,11 +1,16 @@
<html>
<head>
<script>
if (location.search == '?broken') {
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>
@@ -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>");
}
}
@@ -0,0 +1,6 @@
<!doctype html>
<meta charset=utf-8>
<head>
<link rel="manifest" href="file://this_is_not_allowed!">
</head>
<h1>Support Page for Web Manifest Tests</h1>
@@ -0,0 +1,70 @@
<html>
<head>
</head>
<body>
<h1>This example is taken from <a href="https://schema.org/Recipe">https://schema.org/Recipe</a></h1>
<div itemscope itemtype="http://schema.org/Recipe">
<span itemprop="name">Mom's World Famous Banana Bread</span> By <span itemprop="author">John Smith</span>,
<meta itemprop="datePublished" content="2009-05-08">May 8, 2009
<img itemprop="image" src="bananabread.jpg" alt="Banana bread on a plate" />
<span itemprop="description">This classic banana bread recipe comes
from my mom -- the walnuts add a nice texture and flavor to the banana
bread.</span> Prep Time:
<meta itemprop="prepTime" content="PT15M">15 minutes Cook time:
<meta itemprop="cookTime" content="PT1H">1 hour Yield: <span itemprop="recipeYield">1 loaf</span>
<div itemprop="nutrition" itemscope itemtype="http://schema.org/NutritionInformation">
Nutrition facts:
<span itemprop="calories">240 calories</span>,
<span itemprop="fatContent">9 grams fat</span>
</div>
Ingredients: - <span itemprop="recipeIngredient">3 or 4 ripe bananas, smashed</span> - <span itemprop="recipeIngredient">1 egg</span> - <span itemprop="recipeIngredient">3/4 cup of sugar</span> ... Instructions:
<span itemprop="recipeInstructions">
Preheat the oven to 350 degrees. Mix in the ingredients in a bowl. Add
the flour last. Pour the mixture into a loaf pan and bake for one hour.
</span> 140 comments:
<div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter">
<meta itemprop="interactionType" content="http://schema.org/CommentAction" />
<meta itemprop="userInteractionCount" content="140" />
</div>
From Janel, May 5 -- thank you, great recipe! ...
</div>
<h1>This example is taken from <a href="https://schema.org/Book">https://schema.org/Book</a></h1>
<div itemscope itemtype="http://schema.org/Book">
<img itemprop="image" src="catcher-in-the-rye-book-cover.jpg" alt="cover art: red horse, city in background" />
<span itemprop="name">The Catcher in the Rye</span> -
<link itemprop="bookFormat" href="http://schema.org/Paperback">Mass Market Paperback by <a itemprop="author" href="/author/jd_salinger.html">J.D. Salinger</a>
<div itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
<span itemprop="ratingValue">4</span> stars -
<span itemprop="reviewCount">3077</span> reviews
</div>
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
Price: <span itemprop="price" content="6.99">$6.99</span>
<meta itemprop="priceCurrency" content="USD" />
<link itemprop="availability" href="http://schema.org/InStock">In Stock
</div>
Product details
<span itemprop="numberOfPages">224</span> pages Publisher: <span itemprop="publisher">Little, Brown, and Company</span> -
<meta itemprop="datePublished" content="1991-05-01">May 1, 1991 Language: <span itemprop="inLanguage">English</span> ISBN-10:
<span itemprop="isbn">0316769487</span> Reviews:
<div itemprop="review" itemscope itemtype="http://schema.org/Review">
<span itemprop="reviewRating">5</span> stars -
<b>"<span itemprop="name">A masterpiece of literature</span>"</b> by
<span itemprop="author">John Doe</span>, Written on
<meta itemprop="datePublished" content="2006-05-04">May 4, 2006
<span itemprop="reviewBody">I really enjoyed this book. It captures the essential
challenge people face as they try make sense of their lives and grow to adulthood.</span>
</div>
<div itemprop="review" itemscope itemtype="http://schema.org/Review">
<span itemprop="reviewRating">4</span> stars -
<b>"<span itemprop="name">A good read.</span>" </b> by <span itemprop="author">Bob Smith</span>, Written on
<meta itemprop="datePublished" content="2006-06-15">June 15, 2006
<span itemprop="reviewBody">Catcher in the Rye is a fun book. It's a good book to read.</span>
</div>
</div>
</body>
</html>
@@ -0,0 +1,18 @@
<html>
<head>
</head>
<body>
<h1>This example is taken from <a href="https://html.spec.whatwg.org/multipage/microdata.html">https://html.spec.whatwg.org/multipage/microdata.html</a>, and modified.</h1>
<div itemscope id="amanda" itemref="a b"></div>
<p id="a">Name: <span itemprop="name">Amanda</span></p>
<div id="b" itemprop="band" itemscope itemref="c"></div>
<div id="c">
<p>Band: <span itemprop="name">Jazz Band</span></p>
<p>Size: <span itemprop="size">12</span> players</p>
<span itemprop="cycle" itemscope itemref="b">This is an error.</span>
</div>
</body>
</html>
@@ -0,0 +1,23 @@
<html>
<head>
</head>
<body>
<h1>This example is taken from <a href="https://html.spec.whatwg.org/multipage/microdata.html">https://html.spec.whatwg.org/multipage/microdata.html</a></h1>
<figure itemscope itemtype="http://n.whatwg.org/work" itemref="licenses">
<img itemprop="work" src="images/house.jpeg" alt="A white house, boarded up, sits in a forest.">
<figcaption itemprop="title">The house I found.</figcaption>
</figure>
<figure itemscope itemtype="http://n.whatwg.org/work" itemref="licenses">
<img itemprop="work" src="images/mailbox.jpeg" alt="Outside the house is a mailbox. It has a leaflet inside.">
<figcaption itemprop="title">The mailbox.</figcaption>
</figure>
<footer>
<p id="licenses">All images licensed under the <a itemprop="license"
href="http://www.opensource.org/licenses/mit-license.php">MIT
license</a>.</p>
</footer>
</body>
</html>
@@ -0,0 +1,50 @@
<html>
<head>
<meta charset=utf-8>
</head>
<body>
<h1>This example is taken from <a href="http://microformats.org/wiki/hcard-examples">http://microformats.org/wiki/hcard-examples</a></h1>
<div class="vcard">
<span class="fn n">
<a class="url" href="http://t37.net">
<span class="given-name">Fréderic</span>
<span class="family-name">de Villamil</span>
</a>
</span>
<span class="nickname">neuro</span>
<a class="email" href="mailto:neuroNOSPAM@t37.net">
<span class="type">pref</span><span>erred email</span>
</a>
<span class="org">Omatis</span>
<span class="adr">
<abbr class="type" title="dom">France</abbr>
<span class="type">home</span> address
<abbr class="type" title="postal">mail</abbr> and
<abbr class="type" title="parcel">shipments</abbr>:
<span class="street-address">12 rue Danton</span>
<span class="locality">Le Kremlin-Bicetre</span>
<span class="postal-code">94270</span>
<span class="country-name">France</span>
</span>
<span class="geo">
<abbr class="latitude" title="48.816667">N 48° 81.6667</abbr>
<abbr class="longitude" title="2.366667">E 2° 36.6667</abbr>
</span>
</div>
<h1>This example is taken from <a href="http://microformats.org/wiki/hCalendar">http://microformats.org/wiki/hCalendar</a></h1>
<div class="vevent">
<a class="url" href="http://conferences.oreillynet.com/pub/w/40/program.html">
http://conferences.oreillynet.com/pub/w/40/program.html
</a>
<span class="summary">Web 2.0 Conference</span>:
<abbr class="dtstart" title="2005-10-05">October 5</abbr>-
<abbr class="dtend" title="2005-10-07">7</abbr>,
at the <span class="location">Argent Hotel, San Francisco, CA</span>
</div>
</body>
</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>
@@ -0,0 +1 @@
{"name": "pass"}
@@ -0,0 +1,7 @@
{
"name": "NotifyChannel Test",
"launch_path": "/index.html",
"messages": [
{ "audiochannel-interruption-begin": "./file_browserElement_NotifyChannel.html" }
]
}
@@ -0,0 +1 @@
Content-Type: application/manifest+json
@@ -12,6 +12,7 @@ support-files =
browserElement_Find.js
browserElement_OpenTab.js
[test_browserElement_oop_getStructuredData.html]
[test_browserElement_oop_Viewmode.html]
[test_browserElement_oop_ThemeColor.html]
[test_browserElement_inproc_ErrorSecurity.html]
@@ -74,6 +75,8 @@ skip-if = (toolkit == 'gonk') # Disabled on emulator. See bug 1144015 comment 8
[test_browserElement_oop_PrivateBrowsing.html]
[test_browserElement_oop_PromptCheck.html]
[test_browserElement_oop_PromptConfirm.html]
[test_browserElement_oop_Proxy.html]
skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
[test_browserElement_oop_PurgeHistory.html]
[test_browserElement_oop_Reload.html]
[test_browserElement_oop_ReloadPostRequest.html]
@@ -113,3 +116,4 @@ disabled = bug 924771
[test_browserElement_oop_GetContentDimensions.html]
[test_browserElement_oop_AudioChannel.html]
[test_browserElement_oop_SetNFCFocus.html]
[test_browserElement_oop_getWebManifest.html]
@@ -3,6 +3,7 @@ skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || deb
support-files =
../../../browser/base/content/test/general/audio.ogg
../../../dom/media/test/short-video.ogv
async.js
browserElementTestHelpers.js
browserElement_Alert.js
browserElement_AlertInFrame.js
@@ -36,6 +37,8 @@ support-files =
browserElement_FrameWrongURI.js
browserElement_GetScreenshot.js
browserElement_GetScreenshotDppx.js
browserElement_getStructuredData.js
browserElement_getWebManifest.js
browserElement_Iconchange.js
browserElement_LoadEvents.js
browserElement_Manifestchange.js
@@ -51,6 +54,7 @@ support-files =
browserElement_PrivateBrowsing.js
browserElement_PromptCheck.js
browserElement_PromptConfirm.js
browserElement_Proxy.js
browserElement_PurgeHistory.js
browserElement_Reload.js
browserElement_ReloadPostRequest.js
@@ -121,15 +125,25 @@ support-files =
file_empty_script.js
file_focus.html
file_http_401_response.sjs
file_http_407_response.sjs
file_inputmethod.html
file_microdata.html
file_microdata_bad_itemref.html
file_microdata_itemref.html
file_microformats.html
file_inputmethod.html
file_post_request.html
file_wyciwyg.html
file_audio.html
iframe_file_audio.html
file_web_manifest.html
file_web_manifest.json
file_illegal_web_manifest.html
# 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_inproc_getWebManifest.html]
[test_browserElement_NoAttr.html]
[test_browserElement_NoPref.html]
[test_browserElement_NoPermission.html]
@@ -195,6 +209,8 @@ skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_inproc_PrivateBrowsing.html]
[test_browserElement_inproc_PromptCheck.html]
[test_browserElement_inproc_PromptConfirm.html]
[test_browserElement_inproc_Proxy.html]
skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
[test_browserElement_inproc_PurgeHistory.html]
[test_browserElement_inproc_ReloadPostRequest.html]
[test_browserElement_inproc_RemoveBrowserElement.html]
@@ -229,3 +245,4 @@ disabled = bug 774100
[test_browserElement_inproc_GetContentDimensions.html]
[test_browserElement_inproc_AudioChannel.html]
[test_browserElement_inproc_SetNFCFocus.html]
[test_browserElement_inproc_getStructuredData.html]
@@ -47,12 +47,7 @@ function runTest() {
document.body.appendChild(iframe);
}
// This test relies on <audio> elements interacting with the audio channel
// service. This is controled by the media.useAudioChannelService pref.
addEventListener('testready', function() {
SpecialPowers.pushPrefEnv({set: [['media.useAudioChannelService', true]]},
runTest);
});
addEventListener('testready', runTest);
</script>
</body>
@@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test BrowserElementAudioChannel function : notifyChannel().</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.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_NotifyChannel.js">
</script>
</body>
</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>
@@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 1195801</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.8" src="async.js"></script>
<script type="application/javascript;version=1.8" src="browserElement_getStructuredData.js"></script>
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!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>
@@ -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>
@@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 1195801</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.8" src="async.js"></script>
<script type="application/javascript;version=1.8" src="browserElement_getStructuredData.js"></script>
</script>
</body>
</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>
+6
View File
@@ -26,6 +26,8 @@ XPIDL_MODULE = 'browser-element'
EXTRA_COMPONENTS += [
'BrowserElementParent.js',
'BrowserElementParent.manifest',
'BrowserElementProxy.js',
'BrowserElementProxy.manifest',
]
EXTRA_JS_MODULES += [
@@ -52,3 +54,7 @@ MOCHITEST_MANIFESTS += [
'mochitest/mochitest.ini',
'mochitest/priority/mochitest.ini',
]
MOCHITEST_CHROME_MANIFESTS += ['mochitest/chrome.ini']
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
+12 -2
View File
@@ -9,7 +9,7 @@
interface nsIDOMDOMRequest;
interface nsIFrameLoader;
[scriptable, function, uuid(c0c2dd9b-41ef-42dd-a4c1-e456619c1941)]
[scriptable, function, uuid(00d0e19d-bd67-491f-8e85-b9905224d3bb)]
interface nsIBrowserElementNextPaintListener : nsISupports
{
void recvNextPaint();
@@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports
* Interface to the BrowserElementParent implementation. All methods
* but setFrameLoader throw when the remote process is dead.
*/
[scriptable, uuid(9946695c-1ed3-4abb-bc60-6f8947fd5641)]
[scriptable, uuid(57758c10-6036-11e5-a837-0800200c9a66)]
interface nsIBrowserElementAPI : nsISupports
{
const long FIND_CASE_SENSITIVE = 0;
@@ -97,10 +97,20 @@ interface nsIBrowserElementAPI : nsISupports
nsIDOMDOMRequest isAudioChannelActive(in uint32_t audioChannel);
nsIDOMDOMRequest notifyChannel(in DOMString event,
in DOMString manifest,
in uint32_t audioChannel);
void setNFCFocus(in boolean isFocus);
nsIDOMDOMRequest executeScript(in DOMString script, in jsval options);
/**
* Returns an object that represents a Web Manifest:
* http://w3c.github.io/manifest/
*/
nsIDOMDOMRequest getWebManifest();
/**
* Returns a JSON string representing Microdata objects on the page.
* Format is described at:
+2 -1
View File
@@ -1187,7 +1187,8 @@ nsDOMCameraControl::NotifyRecordingStatusChange(const nsString& aMsg)
// Video recording doesn't output any sound, so it's not necessary to check canPlay.
float volume = 0.0;
bool muted = true;
rv = mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
rv = mAudioChannelAgent->NotifyStartedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY,
&volume, &muted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
+2 -1
View File
@@ -75,7 +75,8 @@ ClipboardEvent::Constructor(const GlobalObject& aGlobal,
// support other types of events, make sure that read/write privileges are
// checked properly within DataTransfer.
clipboardData = new DataTransfer(ToSupports(e), eCopy, false, -1);
clipboardData->SetData(aParam.mDataType, aParam.mData);
clipboardData->SetData(aParam.mDataType, aParam.mData, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
}
}
+48 -41
View File
@@ -36,11 +36,21 @@
namespace mozilla {
namespace dom {
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
TransferItem& aField,
const char* aName,
uint32_t aFlags = 0)
{
ImplCycleCollectionTraverse(aCallback, aField.mData, aName, aFlags);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(DataTransfer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DataTransfer)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mItems)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragImage)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@@ -48,6 +58,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DataTransfer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mItems)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragImage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
@@ -269,6 +280,12 @@ DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
FileList*
DataTransfer::GetFiles(ErrorResult& aRv)
{
return GetFilesInternal(aRv, nsContentUtils::SubjectPrincipal());
}
FileList*
DataTransfer::GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal)
{
if (mEventMessage != eDrop &&
mEventMessage != eLegacyDragDrop &&
@@ -283,7 +300,7 @@ DataTransfer::GetFiles(ErrorResult& aRv)
for (uint32_t i = 0; i < count; i++) {
nsCOMPtr<nsIVariant> variant;
aRv = MozGetDataAt(NS_ConvertUTF8toUTF16(kFileMime), i, getter_AddRefs(variant));
aRv = GetDataAtInternal(NS_ConvertUTF8toUTF16(kFileMime), i, aSubjectPrincipal, getter_AddRefs(variant));
if (aRv.Failed()) {
return nullptr;
}
@@ -335,7 +352,7 @@ NS_IMETHODIMP
DataTransfer::GetFiles(nsIDOMFileList** aFileList)
{
ErrorResult rv;
NS_IF_ADDREF(*aFileList = GetFiles(rv));
NS_IF_ADDREF(*aFileList = GetFilesInternal(rv, nsContentUtils::GetSystemPrincipal()));
return rv.StealNSResult();
}
@@ -363,7 +380,7 @@ DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
aData.Truncate();
nsCOMPtr<nsIVariant> data;
nsresult rv = MozGetDataAt(aFormat, 0, getter_AddRefs(data));
nsresult rv = GetDataAtInternal(aFormat, 0, nsContentUtils::SubjectPrincipal(), getter_AddRefs(data));
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_DOM_INDEX_SIZE_ERR) {
aRv.Throw(rv);
@@ -419,18 +436,10 @@ void
DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
ErrorResult& aRv)
{
RefPtr<nsVariant> variant = new nsVariant();
RefPtr<nsVariantCC> variant = new nsVariantCC();
variant->SetAsAString(aData);
aRv = MozSetDataAt(aFormat, variant, 0);
}
NS_IMETHODIMP
DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData)
{
ErrorResult rv;
SetData(aFormat, aData, rv);
return rv.StealNSResult();
aRv = SetDataAtInternal(aFormat, variant, 0, nsContentUtils::SubjectPrincipal());
}
void
@@ -498,7 +507,8 @@ DataTransfer::GetMozSourceNode()
nsCOMPtr<nsIDOMNode> sourceNode;
dragSession->GetSourceNode(getter_AddRefs(sourceNode));
nsCOMPtr<nsINode> node = do_QueryInterface(sourceNode);
if (node && !nsContentUtils::CanCallerAccess(node)) {
if (node && !nsContentUtils::LegacyIsCallerNativeCode()
&& !nsContentUtils::CanCallerAccess(node)) {
return nullptr;
}
@@ -566,9 +576,16 @@ DataTransfer::MozTypesAt(uint32_t aIndex, nsISupports** aTypes)
return rv.StealNSResult();
}
NS_IMETHODIMP
DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
nsIVariant** aData)
nsresult
DataTransfer::GetDataAtNoSecurityCheck(const nsAString& aFormat, uint32_t aIndex,
nsIVariant** aData)
{
return GetDataAtInternal(aFormat, aIndex, nsContentUtils::GetSystemPrincipal(), aData);
}
nsresult
DataTransfer::GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal* aSubjectPrincipal, nsIVariant** aData)
{
*aData = nullptr;
@@ -609,22 +626,18 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
// source of the drag is in a child frame of the caller. In that case,
// we only allow access to data of the same principal. During other events,
// only allow access to the data with the same principal.
nsIPrincipal* principal = nullptr;
if (mIsCrossDomainSubFrameDrop ||
bool checkFormatItemPrincipal = mIsCrossDomainSubFrameDrop ||
(mEventMessage != eDrop && mEventMessage != eLegacyDragDrop &&
mEventMessage != ePaste &&
!nsContentUtils::IsCallerChrome())) {
principal = nsContentUtils::SubjectPrincipal();
}
mEventMessage != ePaste);
uint32_t count = item.Length();
for (uint32_t i = 0; i < count; i++) {
TransferItem& formatitem = item[i];
if (formatitem.mFormat.Equals(format)) {
bool subsumes;
if (formatitem.mPrincipal && principal &&
(NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
if (formatitem.mPrincipal && checkFormatItemPrincipal &&
!aSubjectPrincipal->Subsumes(formatitem.mPrincipal)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!formatitem.mData) {
FillInExternalData(formatitem, aIndex);
@@ -643,12 +656,7 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
MOZ_ASSERT(sp, "This cannot fail on the main thread.");
nsIPrincipal* dataPrincipal = sp->GetPrincipal();
NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
if (!principal) {
principal = nsContentUtils::SubjectPrincipal();
}
bool equals = false;
NS_ENSURE_TRUE(NS_SUCCEEDED(principal->Equals(dataPrincipal, &equals)) && equals,
NS_ERROR_DOM_SECURITY_ERR);
NS_ENSURE_TRUE(aSubjectPrincipal->Subsumes(dataPrincipal), NS_ERROR_DOM_SECURITY_ERR);
}
}
*aData = formatitem.mData;
@@ -667,7 +675,7 @@ DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
mozilla::ErrorResult& aRv)
{
nsCOMPtr<nsIVariant> data;
aRv = MozGetDataAt(aFormat, aIndex, getter_AddRefs(data));
aRv = GetDataAtInternal(aFormat, aIndex, nsContentUtils::SubjectPrincipal(), getter_AddRefs(data));
if (aRv.Failed()) {
return;
}
@@ -684,9 +692,9 @@ DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
}
}
NS_IMETHODIMP
DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
uint32_t aIndex)
nsresult
DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
uint32_t aIndex, nsIPrincipal* aSubjectPrincipal)
{
if (aFormat.IsEmpty()) {
return NS_OK;
@@ -711,7 +719,7 @@ DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
// Don't allow non-chrome to add non-string or file data. We block file
// promises as well which are used internally for drags to the desktop.
if (!nsContentUtils::IsCallerChrome()) {
if (!nsContentUtils::IsSystemPrincipal(aSubjectPrincipal)) {
if (aFormat.EqualsLiteral(kFilePromiseMime) ||
aFormat.EqualsLiteral(kFileMime)) {
return NS_ERROR_DOM_SECURITY_ERR;
@@ -725,8 +733,7 @@ DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
}
}
return SetDataWithPrincipal(aFormat, aData, aIndex,
nsContentUtils::SubjectPrincipal());
return SetDataWithPrincipal(aFormat, aData, aIndex, aSubjectPrincipal);
}
void
@@ -738,7 +745,7 @@ DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
aRv = nsContentUtils::XPConnect()->JSValToVariant(aCx, aData,
getter_AddRefs(data));
if (!aRv.Failed()) {
aRv = MozSetDataAt(aFormat, data, aIndex);
aRv = SetDataAtInternal(aFormat, data, aIndex, nsContentUtils::SubjectPrincipal());
}
}
@@ -1365,7 +1372,7 @@ DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
if (!data)
return;
RefPtr<nsVariant> variant = new nsVariant();
RefPtr<nsVariantCC> variant = new nsVariantCC();
nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
if (supportsstr) {
+12
View File
@@ -68,6 +68,8 @@ public:
friend class mozilla::EventStateManager;
static DataTransfer* Cast(nsIDOMDataTransfer* aArg) { return static_cast<DataTransfer*>(aArg); }
protected:
// hide the default constructor
@@ -183,6 +185,9 @@ public:
return mDragTarget;
}
nsresult GetDataAtNoSecurityCheck(const nsAString& aFormat, uint32_t aIndex,
nsIVariant** aData);
// a readonly dataTransfer cannot have new data added or existing data removed.
// Only the dropEffect and effectAllowed may be modified.
void SetReadOnly() { mReadOnly = true; }
@@ -246,6 +251,13 @@ protected:
// clipboard for a given index.
void FillInExternalData(TransferItem& aItem, uint32_t aIndex);
FileList* GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal);
nsresult GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal* aSubjectPrincipal, nsIVariant** aData);
nsresult SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData, uint32_t aIndex,
nsIPrincipal* aSubjectPrincipal);
friend class ContentParent;
void FillAllExternalData();
+19 -3
View File
@@ -325,6 +325,10 @@ EventListenerManager::AddEventListenerInternal(
EnableDevice(eDeviceLight);
} else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
EnableDevice(eDeviceMotion);
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
} else if (aTypeAtom == nsGkAtoms::onorientationchange) {
EnableDevice(eOrientationChange);
#endif
#ifdef MOZ_B2G
} else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
@@ -431,6 +435,9 @@ EventListenerManager::IsDeviceType(EventMessage aEventMessage)
case eDeviceLight:
case eDeviceProximity:
case eUserProximity:
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
case eOrientationChange:
#endif
return true;
default:
break;
@@ -462,6 +469,11 @@ EventListenerManager::EnableDevice(EventMessage aEventMessage)
window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
window->EnableDeviceSensor(SENSOR_GYROSCOPE);
break;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
case eOrientationChange:
window->EnableOrientationChangeListener();
break;
#endif
default:
NS_WARNING("Enabling an unknown device sensor.");
break;
@@ -492,6 +504,11 @@ EventListenerManager::DisableDevice(EventMessage aEventMessage)
case eDeviceLight:
window->DisableDeviceSensor(SENSOR_LIGHT);
break;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
case eOrientationChange:
window->DisableOrientationChangeListener();
break;
#endif
default:
NS_WARNING("Disabling an unknown device sensor.");
break;
@@ -1458,13 +1475,12 @@ EventListenerManager::MarkForCC()
const TypedEventHandler& typedHandler =
jsEventHandler->GetTypedEventHandler();
if (typedHandler.HasEventHandler()) {
JS::ExposeObjectToActiveJS(typedHandler.Ptr()->Callable());
typedHandler.Ptr()->MarkForCC();
}
} else if (listener.mListenerType == Listener::eWrappedJSListener) {
xpc_TryUnmarkWrappedGrayObject(listener.mListener.GetXPCOMCallback());
} else if (listener.mListenerType == Listener::eWebIDLListener) {
// Callback() unmarks gray
listener.mListener.GetWebIDLCallback()->Callback();
listener.mListener.GetWebIDLCallback()->MarkForCC();
}
}
if (mRefCnt.IsPurple()) {
+6
View File
@@ -511,6 +511,12 @@ WINDOW_EVENT(online,
eOnline,
EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
WINDOW_EVENT(orientationchange,
eOrientationChange,
EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
#endif
WINDOW_EVENT(pagehide,
ePageHide,
EventNameType_HTMLBodyOrFramesetOnly,
+1 -1
View File
@@ -175,7 +175,7 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F22)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F23)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F24)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Fn)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(FLock)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(FnLock)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(PrintScreen)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ScrollLock)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Pause)
+2 -5
View File
@@ -134,10 +134,6 @@ FMRadio::Init(nsPIDOMWindow *aWindow)
RegisterSwitchObserver(SWITCH_HEADPHONES, this);
}
// All of the codes below are for AudioChannel. We can directly return here
// if preferences doesn't enable AudioChannelService.
NS_ENSURE_TRUE_VOID(Preferences::GetBool("media.useAudioChannelService"));
nsCOMPtr<nsIAudioChannelAgent> audioChannelAgent =
do_CreateInstance("@mozilla.org/audiochannelagent;1");
NS_ENSURE_TRUE_VOID(audioChannelAgent);
@@ -456,7 +452,8 @@ FMRadio::EnableAudioChannelAgent()
float volume = 0.0;
bool muted = true;
mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
mAudioChannelAgent->NotifyStartedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY,
&volume, &muted);
WindowVolumeChanged(volume, muted);
mAudioChannelAgentEnabled = true;
+1 -1
View File
@@ -808,7 +808,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir)
aDir->GetPath(unicodePath);
if (unicodePath.IsEmpty()) // nothing to do
return NS_OK;
RefPtr<nsVariant> prefValue = new nsVariant();
RefPtr<nsVariantCC> prefValue = new nsVariantCC();
prefValue->SetAsAString(unicodePath);
// Use the document's current load context to ensure that the content pref
+5 -23
View File
@@ -1121,11 +1121,6 @@ static bool IsScriptedAutoplayEnabled()
return Preferences::GetBool("media.autoplay.allowscripted");
}
static bool UseAudioChannelService()
{
return Preferences::GetBool("media.useAudioChannelService");
}
static bool UseAudioChannelAPI()
{
return Preferences::GetBool("media.useAudioChannelAPI");
@@ -2449,10 +2444,6 @@ bool HTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
bool HTMLMediaElement::CheckAudioChannelPermissions(const nsAString& aString)
{
if (!UseAudioChannelService()) {
return true;
}
// Only normal channel doesn't need permission.
if (aString.EqualsASCII("normal")) {
return true;
@@ -4639,10 +4630,6 @@ ImageContainer* HTMLMediaElement::GetImageContainer()
nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
{
if (!UseAudioChannelService()) {
return NS_OK;
}
if (mAudioChannelVolume != aVolume) {
mAudioChannelVolume = aVolume;
SetVolumeInternal();
@@ -4687,10 +4674,6 @@ HTMLMediaElement::MaybeCreateAudioChannelAgent()
void
HTMLMediaElement::UpdateAudioChannelPlayingState()
{
if (!UseAudioChannelService()) {
return;
}
bool playingThroughTheAudioChannel =
(!mPaused &&
!Muted() &&
@@ -4716,11 +4699,6 @@ HTMLMediaElement::UpdateAudioChannelPlayingState()
void
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
{
// Don't do anything if this element doesn't have any audio tracks.
if (!HasAudio()) {
return;
}
// Immediately check if this should go to the MSG instead of the normal
// media playback route.
WindowAudioCaptureChanged();
@@ -4731,9 +4709,13 @@ HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
AutoNoJSAPI nojsapi;
if (aPlaying) {
// Don't notify playback if this element doesn't have any audio tracks.
uint32_t notify = HasAudio() ? nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY :
nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY;
float volume = 0.0;
bool muted = true;
mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
mAudioChannelAgent->NotifyStartedPlaying(notify, &volume, &muted);
WindowVolumeChanged(volume, muted);
} else {
mAudioChannelAgent->NotifyStoppedPlaying();
+1 -1
View File
@@ -215,7 +215,7 @@ TextTrackManager::UpdateCueDisplay()
mTextTracks->UpdateAndGetShowingCues(activeCues);
if (activeCues.Length() > 0) {
RefPtr<nsVariant> jsCues = new nsVariant();
RefPtr<nsVariantCC> jsCues = new nsVariantCC();
jsCues->SetAsArray(nsIDataType::VTYPE_INTERFACE,
&NS_GET_IID(nsIDOMEventTarget),
+24 -2
View File
@@ -563,6 +563,9 @@ nsBrowserElement::GetAllowedAudioChannels(
return;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("nsBrowserElement, GetAllowedAudioChannels, this = %p\n", this));
GenerateAllowedAudioChannels(window, frameLoader, mBrowserElementAPI,
manifestURL, mBrowserElementAudioChannels,
aRv);
@@ -603,7 +606,8 @@ nsBrowserElement::GenerateAllowedAudioChannels(
RefPtr<BrowserElementAudioChannel> ac =
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
AudioChannel::Normal, aRv);
AudioChannel::Normal,
aManifestURL, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -630,7 +634,7 @@ nsBrowserElement::GenerateAllowedAudioChannels(
RefPtr<BrowserElementAudioChannel> ac =
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
(AudioChannel)audioChannelTable[i].value,
aRv);
aManifestURL, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -778,4 +782,22 @@ nsBrowserElement::GetStructuredData(ErrorResult& aRv)
return req.forget().downcast<DOMRequest>();
}
already_AddRefed<DOMRequest>
nsBrowserElement::GetWebManifest(ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = mBrowserElementAPI->GetWebManifest(getter_AddRefs(req));
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
return req.forget().downcast<DOMRequest>();
}
} // namespace mozilla
+2
View File
@@ -114,6 +114,8 @@ public:
already_AddRefed<dom::DOMRequest> GetStructuredData(ErrorResult& aRv);
already_AddRefed<dom::DOMRequest> GetWebManifest(ErrorResult& aRv);
void SetNFCFocus(bool isFocus,
ErrorResult& aRv);
+1 -46
View File
@@ -8,7 +8,7 @@
interface nsIVariant;
interface nsIDOMFileList;
[builtinclass, uuid(c71180e3-298b-4fbb-9ccb-82c822474741)]
[builtinclass, uuid(655078bf-1675-4aa0-a48d-a133e864ce57)]
interface nsIDOMDataTransfer : nsISupports
{
/**
@@ -81,17 +81,6 @@ interface nsIDOMDataTransfer : nsISupports
*/
void clearData([optional] in DOMString format);
/**
* Set the data for a given format. If data for the format does not exist,
* it is added at the end, such that the last item in the types list will be
* the new format. If data for the format already exists, the existing data
* is replaced in the same position. That is, the order of the types list is
* not changed.
*
* @throws NS_ERROR_NULL_POINTER if the data is null
*/
void setData(in DOMString format, in DOMString data);
/**
* Retrieves the data for a given format, or an empty string if data for
* that format does not exist or the data transfer contains no data.
@@ -171,40 +160,6 @@ interface nsIDOMDataTransfer : nsISupports
*/
void mozClearDataAt(in DOMString format, in unsigned long index);
/*
* A data transfer may store multiple items, each at a given zero-based
* index. setDataAt may only be called with an index argument less than
* itemCount in which case an existing item is modified, or equal to
* itemCount in which case a new item is added, and the itemCount is
* incremented by one.
*
* Data should be added in order of preference, with the most specific
* format added first and the least specific format added last. If data of
* the given format already exists, it is replaced in the same position as
* the old data.
*
* The data should be either a string, a primitive boolean or number type
* (which will be converted into a string) or an nsISupports.
*
* @param format the format to add
* @param data the data to add
* @throws NS_ERROR_NULL_POINTER if the data is null
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater than itemCount
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
void mozSetDataAt(in DOMString format, in nsIVariant data, in unsigned long index);
/**
* Retrieve the data associated with the given format for an item at the
* specified index, or null if it does not exist. The index should be in the
* range from zero to itemCount - 1.
*
* @param format the format of the data to look up
* @returns the data of the given format, or null if it doesn't exist.
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
*/
nsIVariant mozGetDataAt(in DOMString format, in unsigned long index);
/**
* Will be true when the user has cancelled the drag (typically by pressing
* Escape) and when the drag has been cancelled unexpectedly. This will be
+1 -1
View File
@@ -3011,7 +3011,7 @@ ContentChild::RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
auto& items = aTransfers[i].items();
for (uint32_t j = 0; j < items.Length(); ++j) {
const IPCDataTransferItem& item = items[j];
RefPtr<nsVariant> variant = new nsVariant();
RefPtr<nsVariantCC> variant = new nsVariantCC();
if (item.data().type() == IPCDataTransferData::TnsString) {
const nsString& data = item.data().get_nsString();
variant->SetAsAString(data);

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