mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
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:
+41
-2
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
},
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
@@ -24,3 +24,6 @@ UNIFIED_SOURCES += [
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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']:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -99,7 +99,7 @@ function runTest() {
|
||||
iframe.src = "data:text/html,page";
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({ "set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
onload = runTest;
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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>
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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}
|
||||
@@ -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));
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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']
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user