mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and b2g-inbound
This commit is contained in:
commit
71f035b404
@ -391,6 +391,9 @@ pref("dom.sms.strict7BitEncoding", false); // Disabled by default.
|
||||
pref("dom.sms.requestStatusReport", true); // Enabled by default.
|
||||
pref("dom.mms.requestStatusReport", true); // Enabled by default.
|
||||
|
||||
//The waiting time in network manager.
|
||||
pref("network.gonk.ms-release-mms-connection", 30000);
|
||||
|
||||
// WebContacts
|
||||
pref("dom.mozContacts.enabled", true);
|
||||
pref("dom.navigator-property.disable.mozContacts", false);
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "9bf9368a1110d6c365225593e0f145c343ea8cd8",
|
||||
"revision": "ca3e0c37006fb38e756288cc87b67834ad88a9ad",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -3811,8 +3811,13 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
|
||||
if (!mAudioChannelAgent) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDOMHTMLVideoElement> video = do_QueryObject(this);
|
||||
// Use a weak ref so the audio channel agent can't leak |this|.
|
||||
mAudioChannelAgent->InitWithWeakCallback(mAudioChannelType, this);
|
||||
if (AUDIO_CHANNEL_NORMAL == mAudioChannelType && video) {
|
||||
mAudioChannelAgent->InitWithVideo(mAudioChannelType, this, true);
|
||||
} else {
|
||||
mAudioChannelAgent->InitWithWeakCallback(mAudioChannelType, this);
|
||||
}
|
||||
mAudioChannelAgent->SetVisibilityState(!OwnerDoc()->Hidden());
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ AudioChannelAgent::AudioChannelAgent()
|
||||
: mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
|
||||
, mIsRegToService(false)
|
||||
, mVisible(true)
|
||||
, mWithVideo(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -54,10 +55,18 @@ AudioChannelAgent::InitWithWeakCallback(int32_t channelType,
|
||||
return InitInternal(channelType, callback, /* useWeakRef = */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioChannelAgent::InitWithVideo(int32_t channelType,
|
||||
nsIAudioChannelAgentCallback *callback,
|
||||
bool aUseWeakRef)
|
||||
{
|
||||
return InitInternal(channelType, callback, aUseWeakRef, true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AudioChannelAgent::InitInternal(int32_t aChannelType,
|
||||
nsIAudioChannelAgentCallback *aCallback,
|
||||
bool aUseWeakRef)
|
||||
bool aUseWeakRef, bool aWithVideo)
|
||||
{
|
||||
// We syncd the enum of channel type between nsIAudioChannelAgent.idl and
|
||||
// AudioChannelCommon.h the same.
|
||||
@ -91,6 +100,8 @@ AudioChannelAgent::InitInternal(int32_t aChannelType,
|
||||
mCallback = aCallback;
|
||||
}
|
||||
|
||||
mWithVideo = aWithVideo;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -104,7 +115,7 @@ NS_IMETHODIMP AudioChannelAgent::StartPlaying(int32_t *_retval)
|
||||
}
|
||||
|
||||
service->RegisterAudioChannelAgent(this,
|
||||
static_cast<AudioChannelType>(mAudioChannelType));
|
||||
static_cast<AudioChannelType>(mAudioChannelType), mWithVideo);
|
||||
*_retval = service->GetState(this, !mVisible);
|
||||
mIsRegToService = true;
|
||||
return NS_OK;
|
||||
|
@ -41,13 +41,14 @@ private:
|
||||
|
||||
nsresult InitInternal(int32_t aAudioAgentType,
|
||||
nsIAudioChannelAgentCallback* aCallback,
|
||||
bool aUseWeakRef);
|
||||
bool aUseWeakRef, bool aWithVideo=false);
|
||||
|
||||
nsCOMPtr<nsIAudioChannelAgentCallback> mCallback;
|
||||
nsWeakPtr mWeakCallback;
|
||||
int32_t mAudioChannelType;
|
||||
bool mIsRegToService;
|
||||
bool mVisible;
|
||||
bool mWithVideo;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -93,19 +93,21 @@ AudioChannelService::~AudioChannelService()
|
||||
|
||||
void
|
||||
AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
AudioChannelType aType)
|
||||
AudioChannelType aType,
|
||||
bool aWithVideo)
|
||||
{
|
||||
MOZ_ASSERT(aType != AUDIO_CHANNEL_DEFAULT);
|
||||
|
||||
AudioChannelAgentData* data = new AudioChannelAgentData(aType,
|
||||
true /* aElementHidden */,
|
||||
AUDIO_CHANNEL_STATE_MUTED /* aState */);
|
||||
AUDIO_CHANNEL_STATE_MUTED /* aState */,
|
||||
aWithVideo);
|
||||
mAgents.Put(aAgent, data);
|
||||
RegisterType(aType, CONTENT_PROCESS_ID_MAIN);
|
||||
RegisterType(aType, CONTENT_PROCESS_ID_MAIN, aWithVideo);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RegisterType(AudioChannelType aType, uint64_t aChildID)
|
||||
AudioChannelService::RegisterType(AudioChannelType aType, uint64_t aChildID, bool aWithVideo)
|
||||
{
|
||||
AudioChannelInternalType type = GetInternalType(aType, true);
|
||||
mChannelCounters[type].AppendElement(aChildID);
|
||||
@ -116,7 +118,11 @@ AudioChannelService::RegisterType(AudioChannelType aType, uint64_t aChildID)
|
||||
if (mDeferTelChannelTimer && aType == AUDIO_CHANNEL_TELEPHONY) {
|
||||
mDeferTelChannelTimer->Cancel();
|
||||
mDeferTelChannelTimer = nullptr;
|
||||
UnregisterTypeInternal(aType, mTimerElementHidden, mTimerChildID);
|
||||
UnregisterTypeInternal(aType, mTimerElementHidden, mTimerChildID, false);
|
||||
}
|
||||
|
||||
if (aWithVideo) {
|
||||
mWithVideoChildIDs.AppendElement(aChildID);
|
||||
}
|
||||
|
||||
// In order to avoid race conditions, it's safer to notify any existing
|
||||
@ -133,14 +139,16 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
|
||||
mAgents.RemoveAndForget(aAgent, data);
|
||||
|
||||
if (data) {
|
||||
UnregisterType(data->mType, data->mElementHidden, CONTENT_PROCESS_ID_MAIN);
|
||||
UnregisterType(data->mType, data->mElementHidden,
|
||||
CONTENT_PROCESS_ID_MAIN, data->mWithVideo);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::UnregisterType(AudioChannelType aType,
|
||||
bool aElementHidden,
|
||||
uint64_t aChildID)
|
||||
uint64_t aChildID,
|
||||
bool aWithVideo)
|
||||
{
|
||||
// There are two reasons to defer the decrease of telephony channel.
|
||||
// 1. User can have time to remove device from his ear before music resuming.
|
||||
@ -156,13 +164,14 @@ AudioChannelService::UnregisterType(AudioChannelType aType,
|
||||
return;
|
||||
}
|
||||
|
||||
UnregisterTypeInternal(aType, aElementHidden, aChildID);
|
||||
UnregisterTypeInternal(aType, aElementHidden, aChildID, aWithVideo);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::UnregisterTypeInternal(AudioChannelType aType,
|
||||
bool aElementHidden,
|
||||
uint64_t aChildID)
|
||||
uint64_t aChildID,
|
||||
bool aWithVideo)
|
||||
{
|
||||
// The array may contain multiple occurrence of this appId but
|
||||
// this should remove only the first one.
|
||||
@ -181,6 +190,12 @@ AudioChannelService::UnregisterTypeInternal(AudioChannelType aType,
|
||||
!mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID)) {
|
||||
mActiveContentChildIDs.RemoveElement(aChildID);
|
||||
}
|
||||
|
||||
if (aWithVideo) {
|
||||
MOZ_ASSERT(mWithVideoChildIDs.Contains(aChildID));
|
||||
mWithVideoChildIDs.RemoveElement(aChildID);
|
||||
}
|
||||
|
||||
SendAudioChannelChangedNotification(aChildID);
|
||||
Notify();
|
||||
}
|
||||
@ -258,8 +273,19 @@ AudioChannelService::GetStateInternal(AudioChannelType aType, uint64_t aChildID,
|
||||
mActiveContentChildIDs.RemoveElement(aChildID);
|
||||
}
|
||||
}
|
||||
else if (newType == AUDIO_CHANNEL_INT_NORMAL &&
|
||||
oldType == AUDIO_CHANNEL_INT_NORMAL_HIDDEN &&
|
||||
mWithVideoChildIDs.Contains(aChildID)) {
|
||||
if (mActiveContentChildIDsFrozen) {
|
||||
mActiveContentChildIDsFrozen = false;
|
||||
mActiveContentChildIDs.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (newType != oldType && aType == AUDIO_CHANNEL_CONTENT) {
|
||||
if (newType != oldType &&
|
||||
(aType == AUDIO_CHANNEL_CONTENT ||
|
||||
(aType == AUDIO_CHANNEL_NORMAL &&
|
||||
mWithVideoChildIDs.Contains(aChildID)))) {
|
||||
Notify();
|
||||
}
|
||||
|
||||
@ -508,7 +534,7 @@ AudioChannelService::Notify()
|
||||
NS_IMETHODIMP
|
||||
AudioChannelService::Notify(nsITimer* aTimer)
|
||||
{
|
||||
UnregisterTypeInternal(AUDIO_CHANNEL_TELEPHONY, mTimerElementHidden, mTimerChildID);
|
||||
UnregisterTypeInternal(AUDIO_CHANNEL_TELEPHONY, mTimerElementHidden, mTimerChildID, false);
|
||||
mDeferTelChannelTimer = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -569,6 +595,7 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const PR
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t index;
|
||||
uint64_t childID = 0;
|
||||
nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"),
|
||||
&childID);
|
||||
@ -576,14 +603,17 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const PR
|
||||
for (int32_t type = AUDIO_CHANNEL_INT_NORMAL;
|
||||
type < AUDIO_CHANNEL_INT_LAST;
|
||||
++type) {
|
||||
int32_t index;
|
||||
|
||||
while ((index = mChannelCounters[type].IndexOf(childID)) != -1) {
|
||||
mChannelCounters[type].RemoveElementAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
if ((index = mActiveContentChildIDs.IndexOf(childID)) != -1) {
|
||||
mActiveContentChildIDs.RemoveElementAt(index);
|
||||
}
|
||||
while ((index = mActiveContentChildIDs.IndexOf(childID)) != -1) {
|
||||
mActiveContentChildIDs.RemoveElementAt(index);
|
||||
}
|
||||
while ((index = mWithVideoChildIDs.IndexOf(childID)) != -1) {
|
||||
mWithVideoChildIDs.RemoveElementAt(index);
|
||||
}
|
||||
|
||||
// We don't have to remove the agents from the mAgents hashtable because if
|
||||
|
@ -46,7 +46,8 @@ public:
|
||||
* this service, sharing the AudioChannelType.
|
||||
*/
|
||||
virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
AudioChannelType aType);
|
||||
AudioChannelType aType,
|
||||
bool aWithVideo);
|
||||
|
||||
/**
|
||||
* Any audio channel agent that stops playing should unregister itself to
|
||||
@ -90,11 +91,11 @@ protected:
|
||||
void SendAudioChannelChangedNotification(uint64_t aChildID);
|
||||
|
||||
/* Register/Unregister IPC types: */
|
||||
void RegisterType(AudioChannelType aType, uint64_t aChildID);
|
||||
void RegisterType(AudioChannelType aType, uint64_t aChildID, bool aWithVideo);
|
||||
void UnregisterType(AudioChannelType aType, bool aElementHidden,
|
||||
uint64_t aChildID);
|
||||
uint64_t aChildID, bool aWithVideo);
|
||||
void UnregisterTypeInternal(AudioChannelType aType, bool aElementHidden,
|
||||
uint64_t aChildID);
|
||||
uint64_t aChildID, bool aWithVideo);
|
||||
|
||||
AudioChannelState GetStateInternal(AudioChannelType aType, uint64_t aChildID,
|
||||
bool aElementHidden,
|
||||
@ -143,15 +144,18 @@ protected:
|
||||
public:
|
||||
AudioChannelAgentData(AudioChannelType aType,
|
||||
bool aElementHidden,
|
||||
AudioChannelState aState)
|
||||
AudioChannelState aState,
|
||||
bool aWithVideo)
|
||||
: mType(aType)
|
||||
, mElementHidden(aElementHidden)
|
||||
, mState(aState)
|
||||
, mWithVideo(aWithVideo)
|
||||
{}
|
||||
|
||||
AudioChannelType mType;
|
||||
bool mElementHidden;
|
||||
AudioChannelState mState;
|
||||
const bool mWithVideo;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
@ -166,6 +170,7 @@ protected:
|
||||
AudioChannelType mCurrentVisibleHigherChannel;
|
||||
|
||||
nsTArray<uint64_t> mActiveContentChildIDs;
|
||||
nsTArray<uint64_t> mWithVideoChildIDs;
|
||||
bool mActiveContentChildIDsFrozen;
|
||||
|
||||
nsCOMPtr<nsITimer> mDeferTelChannelTimer;
|
||||
|
@ -66,7 +66,6 @@ AudioChannelServiceChild::GetState(AudioChannelAgent* aAgent, bool aElementHidde
|
||||
return AUDIO_CHANNEL_STATE_MUTED;
|
||||
}
|
||||
|
||||
ContentChild *cc = ContentChild::GetSingleton();
|
||||
AudioChannelState state = AUDIO_CHANNEL_STATE_MUTED;
|
||||
bool oldElementHidden = data->mElementHidden;
|
||||
|
||||
@ -75,30 +74,24 @@ AudioChannelServiceChild::GetState(AudioChannelAgent* aAgent, bool aElementHidde
|
||||
// Update visibility.
|
||||
data->mElementHidden = aElementHidden;
|
||||
|
||||
if (cc) {
|
||||
cc->SendAudioChannelGetState(data->mType, aElementHidden, oldElementHidden, &state);
|
||||
}
|
||||
ContentChild* cc = ContentChild::GetSingleton();
|
||||
cc->SendAudioChannelGetState(data->mType, aElementHidden, oldElementHidden, &state);
|
||||
data->mState = state;
|
||||
|
||||
if (cc) {
|
||||
cc->SendAudioChannelChangedNotification();
|
||||
}
|
||||
cc->SendAudioChannelChangedNotification();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelServiceChild::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
AudioChannelType aType)
|
||||
AudioChannelType aType,
|
||||
bool aWithVideo)
|
||||
{
|
||||
MOZ_ASSERT(aType != AUDIO_CHANNEL_DEFAULT);
|
||||
|
||||
AudioChannelService::RegisterAudioChannelAgent(aAgent, aType);
|
||||
AudioChannelService::RegisterAudioChannelAgent(aAgent, aType, aWithVideo);
|
||||
|
||||
ContentChild *cc = ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
cc->SendAudioChannelRegisterType(aType);
|
||||
}
|
||||
ContentChild::GetSingleton()->SendAudioChannelRegisterType(aType, aWithVideo);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
@ -120,10 +113,8 @@ AudioChannelServiceChild::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
|
||||
|
||||
AudioChannelService::UnregisterAudioChannelAgent(aAgent);
|
||||
|
||||
ContentChild *cc = ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
cc->SendAudioChannelUnregisterType(data.mType, data.mElementHidden);
|
||||
}
|
||||
ContentChild::GetSingleton()->SendAudioChannelUnregisterType(
|
||||
data.mType, data.mElementHidden, data.mWithVideo);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
static void Shutdown();
|
||||
|
||||
virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
AudioChannelType aType);
|
||||
AudioChannelType aType,
|
||||
bool aWithVideo);
|
||||
virtual void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
|
||||
* 1. Changes to the playable status of this channel.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(7a4c0b06-63a4-11e2-8c1b-10bf48d64bd4)]
|
||||
[scriptable, uuid(86ef883d-9cec-4c04-994f-5de198286e7c)]
|
||||
interface nsIAudioChannelAgent : nsISupports
|
||||
{
|
||||
const long AUDIO_AGENT_CHANNEL_NORMAL = 0;
|
||||
@ -78,6 +78,14 @@ interface nsIAudioChannelAgent : nsISupports
|
||||
*/
|
||||
void initWithWeakCallback(in long channelType, in nsIAudioChannelAgentCallback callback);
|
||||
|
||||
/**
|
||||
* This method is just like init(), and specify the channel is associated with video.
|
||||
*
|
||||
* @param weak
|
||||
* true if weak reference should be hold.
|
||||
*/
|
||||
void initWithVideo(in long channelType, in nsIAudioChannelAgentCallback callback, in boolean weak);
|
||||
|
||||
/**
|
||||
* Notify the agent that we want to start playing.
|
||||
* Note: Gecko component SHOULD call this function first then start to
|
||||
@ -110,6 +118,5 @@ interface nsIAudioChannelAgent : nsISupports
|
||||
* True if the window associated with the agent is visible.
|
||||
*/
|
||||
void setVisibilityState(in boolean visible);
|
||||
|
||||
};
|
||||
|
||||
|
14
dom/fmradio/test/marionette/manifest.ini
Normal file
14
dom/fmradio/test/marionette/manifest.ini
Normal file
@ -0,0 +1,14 @@
|
||||
[DEFAULT]
|
||||
b2g = true
|
||||
browser = false
|
||||
; We don't support FM radio emulation yet, see bug 872417
|
||||
qemu = false
|
||||
|
||||
[test_enable_disable.js]
|
||||
[test_set_frequency.js]
|
||||
[test_cancel_seek.js]
|
||||
[test_one_seek_at_once.js]
|
||||
[test_seek_up_and_down.js]
|
||||
[test_bug862672.js]
|
||||
[test_bug876597.js]
|
||||
|
53
dom/fmradio/test/marionette/test_bug862672.js
Normal file
53
dom/fmradio/test/marionette/test_bug862672.js
Normal file
@ -0,0 +1,53 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("fmradio", true, document);
|
||||
|
||||
let FMRadio = window.navigator.mozFMRadio;
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(FMRadio);
|
||||
is(FMRadio.enabled, false);
|
||||
enableThenDisable();
|
||||
}
|
||||
|
||||
function enableThenDisable() {
|
||||
log("Enable FM Radio and disable it immediately.");
|
||||
var frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
var request = FMRadio.enable(frequency);
|
||||
ok(request);
|
||||
|
||||
var failedToEnable = false;
|
||||
request.onerror = function() {
|
||||
failedToEnable = true;
|
||||
};
|
||||
|
||||
var enableCompleted = false;
|
||||
request.onsuccess = function() {
|
||||
ok(!failedToEnable);
|
||||
enableCompleted = true;
|
||||
};
|
||||
|
||||
var disableReq = FMRadio.disable();
|
||||
ok(disableReq);
|
||||
|
||||
disableReq.onsuccess = function() {
|
||||
// There are two possibilities which depends on the system
|
||||
// process scheduling (bug 911063 comment 0):
|
||||
// - enable fails
|
||||
// - enable's onsuccess fires before disable's onsucess
|
||||
ok(failedToEnable || enableCompleted);
|
||||
ok(!FMRadio.enabled);
|
||||
finish();
|
||||
};
|
||||
|
||||
disableReq.onerror = function() {
|
||||
ok(false, "Disable request should not fail.");
|
||||
};
|
||||
}
|
||||
|
||||
verifyInitialState();
|
||||
|
90
dom/fmradio/test/marionette/test_bug876597.js
Normal file
90
dom/fmradio/test/marionette/test_bug876597.js
Normal file
@ -0,0 +1,90 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("fmradio", true, document);
|
||||
SpecialPowers.addPermission("settings-read", true, document);
|
||||
SpecialPowers.addPermission("settings-write", true, document);
|
||||
|
||||
let FMRadio = window.navigator.mozFMRadio;
|
||||
let mozSettings = window.navigator.mozSettings;
|
||||
let KEY = "ril.radio.disabled";
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(FMRadio);
|
||||
is(FMRadio.enabled, false);
|
||||
ok(mozSettings);
|
||||
|
||||
checkRilSettings();
|
||||
}
|
||||
|
||||
function checkRilSettings() {
|
||||
log("Checking airplane mode settings");
|
||||
let req = mozSettings.createLock().get(KEY);
|
||||
req.onsuccess = function(event) {
|
||||
ok(!req.result[KEY], "Airplane mode is disabled.");
|
||||
enableFMRadio();
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
ok(false, "Error occurs when reading settings value.");
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
function enableFMRadio() {
|
||||
log("Enable FM radio");
|
||||
let frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
let req = FMRadio.enable(frequency);
|
||||
|
||||
req.onsuccess = function() {
|
||||
enableAirplaneMode();
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
ok(false, "Failed to enable FM radio.");
|
||||
};
|
||||
}
|
||||
|
||||
function enableAirplaneMode() {
|
||||
log("Enable airplane mode");
|
||||
FMRadio.ondisabled = function() {
|
||||
FMRadio.ondisabled = null;
|
||||
enableFMRadioWithAirplaneModeEnabled();
|
||||
};
|
||||
|
||||
let settings = {};
|
||||
settings[KEY] = true;
|
||||
mozSettings.createLock().set(settings);
|
||||
}
|
||||
|
||||
function enableFMRadioWithAirplaneModeEnabled() {
|
||||
log("Enable FM radio with airplane mode enabled");
|
||||
let frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
let req = FMRadio.enable(frequency);
|
||||
req.onerror = cleanUp();
|
||||
|
||||
req.onsuccess = function() {
|
||||
ok(false, "FMRadio could be enabled when airplane mode is enabled.");
|
||||
};
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
let settings = {};
|
||||
settings[KEY] = false;
|
||||
let req = mozSettings.createLock().set(settings);
|
||||
|
||||
req.onsuccess = function() {
|
||||
ok(!FMRadio.enabled);
|
||||
finish();
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
ok(false, "Error occurs when setting value");
|
||||
};
|
||||
}
|
||||
|
||||
verifyInitialState();
|
||||
|
69
dom/fmradio/test/marionette/test_cancel_seek.js
Normal file
69
dom/fmradio/test/marionette/test_cancel_seek.js
Normal file
@ -0,0 +1,69 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("fmradio", true, document);
|
||||
|
||||
let FMRadio = window.navigator.mozFMRadio;
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(FMRadio);
|
||||
is(FMRadio.enabled, false);
|
||||
setUp();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
let frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
FMRadio.enable(frequency);
|
||||
FMRadio.onenabled = seek;
|
||||
}
|
||||
|
||||
function seek() {
|
||||
log("Seek up");
|
||||
var request = FMRadio.seekUp();
|
||||
ok(request);
|
||||
|
||||
var seekUpIsCancelled = false;
|
||||
request.onerror = function() {
|
||||
seekUpIsCancelled = true;
|
||||
};
|
||||
|
||||
var seekUpCompleted = false;
|
||||
request.onsuccess = function() {
|
||||
ok(!seekUpIsCancelled);
|
||||
seekUpCompleted = true;
|
||||
};
|
||||
|
||||
log("Seek up");
|
||||
var cancelSeekReq = FMRadio.cancelSeek();
|
||||
ok(cancelSeekReq);
|
||||
|
||||
// There are two possibilities which depends on the system
|
||||
// process scheduling (bug 911063 comment 0):
|
||||
// - seekup action is canceled
|
||||
// - seekup's onsuccess fires before cancelSeek's onerror
|
||||
|
||||
cancelSeekReq.onsuccess = function() {
|
||||
ok(seekUpIsCancelled, "Seekup request failed.");
|
||||
cleanUp();
|
||||
};
|
||||
|
||||
cancelSeekReq.onerror = function() {
|
||||
ok(seekUpCompleted);
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
FMRadio.disable();
|
||||
FMRadio.ondisabled = function() {
|
||||
FMRadio.ondisabled = null;
|
||||
ok(!FMRadio.enabled);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
verifyInitialState();
|
||||
|
85
dom/fmradio/test/marionette/test_enable_disable.js
Normal file
85
dom/fmradio/test/marionette/test_enable_disable.js
Normal file
@ -0,0 +1,85 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("fmradio", true, document);
|
||||
|
||||
let FMRadio = window.navigator.mozFMRadio;
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(FMRadio);
|
||||
is(FMRadio.enabled, false);
|
||||
|
||||
log("Verifying attributes when disabled.");
|
||||
is(FMRadio.frequency, null);
|
||||
ok(FMRadio.frequencyLowerBound);
|
||||
ok(FMRadio.frequencyUpperBound);
|
||||
ok(FMRadio.frequencyUpperBound > FMRadio.frequencyLowerBound);
|
||||
ok(FMRadio.channelWidth);
|
||||
|
||||
enableFMRadio();
|
||||
}
|
||||
|
||||
function enableFMRadio() {
|
||||
log("Verifying behaviors when enabled.");
|
||||
var frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
var request = FMRadio.enable(frequency);
|
||||
ok(request, "FMRadio.enable(r" + frequency + ") returns request");
|
||||
|
||||
request.onsuccess = function() {
|
||||
ok(FMRadio.enabled);
|
||||
ok(typeof FMRadio.frequency == "number");
|
||||
ok(FMRadio.frequency > FMRadio.frequencyLowerBound);
|
||||
};
|
||||
|
||||
request.onerror = function() {
|
||||
ok(null, "Failed to enable");
|
||||
};
|
||||
|
||||
var enabled = false;
|
||||
FMRadio.onenabled = function() {
|
||||
FMRadio.onenabled = null;
|
||||
enabled = FMRadio.enabled;
|
||||
};
|
||||
|
||||
FMRadio.onfrequencychange = function() {
|
||||
log("Check if 'onfrequencychange' event is fired after the 'enabled' event");
|
||||
FMRadio.onfrequencychange = null;
|
||||
ok(enabled, "FMRadio is enabled when handling `onfrequencychange`");
|
||||
disableFMRadio();
|
||||
};
|
||||
}
|
||||
|
||||
function disableFMRadio() {
|
||||
log("Verify behaviors when disabled");
|
||||
|
||||
// There are two possibilities which depends on the system
|
||||
// process scheduling (bug 911063 comment 0):
|
||||
// - seek fails
|
||||
// - seek's onsuccess fires before disable's onsucess
|
||||
var seekRequest = FMRadio.seekUp();
|
||||
var seekCompletes = false;
|
||||
var failedToSeek = false;
|
||||
seekRequest.onerror = function() {
|
||||
ok(!seekCompletes);
|
||||
failedToSeek = true;
|
||||
};
|
||||
|
||||
seekRequest.onsuccess = function() {
|
||||
ok(!failedToSeek);
|
||||
seekCompletes = true;
|
||||
};
|
||||
|
||||
FMRadio.disable();
|
||||
FMRadio.ondisabled = function() {
|
||||
FMRadio.ondisabled = null;
|
||||
ok(seekCompletes || failedToSeek);
|
||||
ok(!FMRadio.enabled);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
verifyInitialState();
|
||||
|
73
dom/fmradio/test/marionette/test_one_seek_at_once.js
Normal file
73
dom/fmradio/test/marionette/test_one_seek_at_once.js
Normal file
@ -0,0 +1,73 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("fmradio", true, document);
|
||||
|
||||
let FMRadio = window.navigator.mozFMRadio;
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(FMRadio);
|
||||
is(FMRadio.enabled, false);
|
||||
setUp();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
let frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
FMRadio.enable(frequency);
|
||||
FMRadio.onenabled = seek;
|
||||
}
|
||||
|
||||
function seek() {
|
||||
var request = FMRadio.seekUp();
|
||||
ok(request);
|
||||
|
||||
// There are two possibilities which depends on the system
|
||||
// process scheduling (bug 911063 comment 0):
|
||||
// - the second seek fails
|
||||
// - both seeks are executed
|
||||
|
||||
request.onerror = function() {
|
||||
ok(!firstSeekCompletes);
|
||||
cleanUp();
|
||||
};
|
||||
|
||||
var firstSeekCompletes = false;
|
||||
request.onsuccess = function() {
|
||||
firstSeekCompletes = true;
|
||||
};
|
||||
|
||||
var seekAgainReq = FMRadio.seekUp();
|
||||
ok(seekAgainReq);
|
||||
|
||||
seekAgainReq.onerror = function() {
|
||||
log("Cancel the first seek to finish the test");
|
||||
let cancelReq = FMRadio.cancelSeek();
|
||||
ok(cancelReq);
|
||||
|
||||
// It's possible that the first seek completes when the
|
||||
// cancel request is handled.
|
||||
cancelReq.onerror = function() {
|
||||
cleanUp();
|
||||
};
|
||||
};
|
||||
|
||||
seekAgainReq.onsuccess = function() {
|
||||
ok(firstSeekCompletes);
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
FMRadio.disable();
|
||||
FMRadio.ondisabled = function() {
|
||||
FMRadio.ondisabled = null;
|
||||
ok(!FMRadio.enabled);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
verifyInitialState();
|
||||
|
61
dom/fmradio/test/marionette/test_seek_up_and_down.js
Normal file
61
dom/fmradio/test/marionette/test_seek_up_and_down.js
Normal file
@ -0,0 +1,61 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 30000;
|
||||
|
||||
SpecialPowers.addPermission("fmradio", true, document);
|
||||
|
||||
let FMRadio = window.navigator.mozFMRadio;
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(FMRadio);
|
||||
is(FMRadio.enabled, false);
|
||||
setUp();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
let frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
FMRadio.enable(frequency);
|
||||
FMRadio.onenabled = seekUp;
|
||||
}
|
||||
|
||||
function seekUp() {
|
||||
log("Seek up");
|
||||
var request = FMRadio.seekUp();
|
||||
ok(request);
|
||||
|
||||
request.onsuccess = function() {
|
||||
seekDown();
|
||||
};
|
||||
|
||||
request.onerror = function() {
|
||||
ok(false, "Seekup request should not fail.");
|
||||
};
|
||||
}
|
||||
|
||||
function seekDown() {
|
||||
log("Seek down");
|
||||
var request = FMRadio.seekDown();
|
||||
ok(request);
|
||||
|
||||
request.onsuccess = function() {
|
||||
cleanUp();
|
||||
};
|
||||
|
||||
request.onerror = function() {
|
||||
ok(false, "Seekdown request should not fail.");
|
||||
};
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
FMRadio.disable();
|
||||
FMRadio.ondisabled = function() {
|
||||
FMRadio.ondisabled = null;
|
||||
ok(!FMRadio.enabled);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
verifyInitialState();
|
||||
|
87
dom/fmradio/test/marionette/test_set_frequency.js
Normal file
87
dom/fmradio/test/marionette/test_set_frequency.js
Normal file
@ -0,0 +1,87 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("fmradio", true, document);
|
||||
|
||||
let FMRadio = window.navigator.mozFMRadio;
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(FMRadio);
|
||||
is(FMRadio.enabled, false);
|
||||
setUp();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
let frequency = FMRadio.frequencyLowerBound + FMRadio.channelWidth;
|
||||
FMRadio.enable(frequency);
|
||||
FMRadio.onenabled = setFrequency;
|
||||
}
|
||||
|
||||
function setFrequency() {
|
||||
log("Set Frequency");
|
||||
let frequency = FMRadio.frequency + FMRadio.channelWidth;
|
||||
var request = FMRadio.setFrequency(frequency);
|
||||
ok(request);
|
||||
|
||||
request.onsuccess = setOutOfRangeFrequency;
|
||||
request.onerror = function() {
|
||||
ok(false, "setFrequency request should not fail.");
|
||||
};
|
||||
}
|
||||
|
||||
function setOutOfRangeFrequency() {
|
||||
log("Set Frequency that out of the range");
|
||||
var request = FMRadio.setFrequency(FMRadio.frequencyUpperBound + 1);
|
||||
ok(request);
|
||||
|
||||
request.onsuccess = function() {
|
||||
ok(false, "The request of setting an out-of-range frequency should fail.");
|
||||
};
|
||||
request.onerror = setFrequencyWhenSeeking;
|
||||
}
|
||||
|
||||
function setFrequencyWhenSeeking() {
|
||||
log("Set frequency when seeking");
|
||||
var request = FMRadio.seekUp();
|
||||
ok(request);
|
||||
|
||||
// There are two possibilities which depends on the system
|
||||
// process scheduling (bug 911063 comment 0):
|
||||
// - seek fails
|
||||
// - seek's onsuccess fires before setFrequency's onsucess
|
||||
|
||||
var failedToSeek = false;
|
||||
request.onerror = function() {
|
||||
failedToSeek = true;
|
||||
};
|
||||
|
||||
var seekCompletes = false;
|
||||
request.onsuccess = function() {
|
||||
ok(!failedToSeek);
|
||||
seekCompletes = true;
|
||||
};
|
||||
|
||||
var frequency = FMRadio.frequencyUpperBound - FMRadio.channelWidth;
|
||||
var setFreqRequest = FMRadio.setFrequency(frequency);
|
||||
ok(setFreqRequest);
|
||||
|
||||
setFreqRequest.onsuccess = function() {
|
||||
ok(failedToSeek || seekCompletes);
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
FMRadio.disable();
|
||||
FMRadio.ondisabled = function() {
|
||||
FMRadio.ondisabled = null;
|
||||
ok(!FMRadio.enabled);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
verifyInitialState();
|
||||
|
@ -1597,24 +1597,26 @@ ContentParent::RecvAudioChannelGetState(const AudioChannelType& aType,
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvAudioChannelRegisterType(const AudioChannelType& aType)
|
||||
ContentParent::RecvAudioChannelRegisterType(const AudioChannelType& aType,
|
||||
const bool& aWithVideo)
|
||||
{
|
||||
nsRefPtr<AudioChannelService> service =
|
||||
AudioChannelService::GetAudioChannelService();
|
||||
if (service) {
|
||||
service->RegisterType(aType, mChildID);
|
||||
service->RegisterType(aType, mChildID, aWithVideo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvAudioChannelUnregisterType(const AudioChannelType& aType,
|
||||
const bool& aElementHidden)
|
||||
const bool& aElementHidden,
|
||||
const bool& aWithVideo)
|
||||
{
|
||||
nsRefPtr<AudioChannelService> service =
|
||||
AudioChannelService::GetAudioChannelService();
|
||||
if (service) {
|
||||
service->UnregisterType(aType, aElementHidden, mChildID);
|
||||
service->UnregisterType(aType, aElementHidden, mChildID, aWithVideo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -420,9 +420,11 @@ private:
|
||||
const bool& aElementWasHidden,
|
||||
AudioChannelState* aValue);
|
||||
|
||||
virtual bool RecvAudioChannelRegisterType(const AudioChannelType& aType);
|
||||
virtual bool RecvAudioChannelRegisterType(const AudioChannelType& aType,
|
||||
const bool& aWithVideo);
|
||||
virtual bool RecvAudioChannelUnregisterType(const AudioChannelType& aType,
|
||||
const bool& aElementHidden);
|
||||
const bool& aElementHidden,
|
||||
const bool& aWithVideo);
|
||||
|
||||
virtual bool RecvAudioChannelChangedNotification();
|
||||
|
||||
|
@ -442,9 +442,10 @@ parent:
|
||||
bool aElementWasHidden)
|
||||
returns (AudioChannelState value);
|
||||
|
||||
sync AudioChannelRegisterType(AudioChannelType aType);
|
||||
sync AudioChannelRegisterType(AudioChannelType aType, bool aWithVideo);
|
||||
sync AudioChannelUnregisterType(AudioChannelType aType,
|
||||
bool aElementHidden);
|
||||
bool aElementHidden,
|
||||
bool aWithVideo);
|
||||
|
||||
async AudioChannelChangedNotification();
|
||||
async AudioChannelChangeDefVolChannel(AudioChannelType aType,
|
||||
|
@ -332,28 +332,37 @@ TabChild::HandleEvent(nsIDOMEvent* aEvent)
|
||||
if (!nsLayoutUtils::FindIDFor(content, &viewId))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
scrollFrame = nsLayoutUtils::FindScrollableFrameFor(viewId);
|
||||
if (scrollFrame) {
|
||||
CSSIntPoint scrollOffset = scrollFrame->GetScrollPositionCSSPixels();
|
||||
// Note that we cannot use FindScrollableFrameFor(ROOT_SCROLL_ID) because
|
||||
// it might return the root element from a different page in the case where
|
||||
// that page is in the bfcache and this page is not run through layout
|
||||
// before being drawn to the screen. Hence the code blocks below treat
|
||||
// ROOT_SCROLL_ID separately from the non-ROOT_SCROLL_ID case.
|
||||
|
||||
CSSIntPoint scrollOffset;
|
||||
if (viewId != FrameMetrics::ROOT_SCROLL_ID) {
|
||||
scrollFrame = nsLayoutUtils::FindScrollableFrameFor(viewId);
|
||||
if (!scrollFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
scrollOffset = scrollFrame->GetScrollPositionCSSPixels();
|
||||
} else {
|
||||
// For the root frame, we store the last metrics, including the last
|
||||
// scroll offset, sent by APZC. (This is updated in ProcessUpdateFrame()).
|
||||
// We use this here to avoid sending APZC back a scroll event that
|
||||
// originally came from APZC (besides being unnecessary, the event might
|
||||
// be slightly out of date by the time it reaches APZC).
|
||||
// We should probably do this for subframes, too.
|
||||
if (viewId == FrameMetrics::ROOT_SCROLL_ID) {
|
||||
if (RoundedToInt(mLastMetrics.mScrollOffset) == scrollOffset)
|
||||
return NS_OK;
|
||||
else
|
||||
// Update the last scroll offset now, otherwise RecvUpdateDimensions()
|
||||
// might trigger a scroll to the old offset before RecvUpdateFrame()
|
||||
// gets a chance to update it.
|
||||
mLastMetrics.mScrollOffset = scrollOffset;
|
||||
utils->GetScrollXY(false, &scrollOffset.x, &scrollOffset.y);
|
||||
if (RoundedToInt(mLastMetrics.mScrollOffset) == scrollOffset) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SendUpdateScrollOffset(presShellId, viewId, scrollOffset);
|
||||
// Update the last scroll offset now, otherwise RecvUpdateDimensions()
|
||||
// might trigger a scroll to the old offset before RecvUpdateFrame()
|
||||
// gets a chance to update it.
|
||||
mLastMetrics.mScrollOffset = scrollOffset;
|
||||
}
|
||||
SendUpdateScrollOffset(presShellId, viewId, scrollOffset);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -60,7 +60,8 @@ const CONFIG_SEND_REPORT_DEFAULT_YES = 2;
|
||||
const CONFIG_SEND_REPORT_ALWAYS = 3;
|
||||
|
||||
const TIME_TO_BUFFER_MMS_REQUESTS = 30000;
|
||||
const TIME_TO_RELEASE_MMS_CONNECTION = 30000;
|
||||
const PREF_TIME_TO_RELEASE_MMS_CONNECTION =
|
||||
Services.prefs.getIntPref("network.gonk.ms-release-mms-connection");
|
||||
|
||||
const PREF_RETRIEVAL_MODE = 'dom.mms.retrieval_mode';
|
||||
const RETRIEVAL_MODE_MANUAL = "manual";
|
||||
@ -293,11 +294,17 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () {
|
||||
if (this.refCount <= 0) {
|
||||
this.refCount = 0;
|
||||
|
||||
// The waiting is too small, just skip the timer creation.
|
||||
if (PREF_TIME_TO_RELEASE_MMS_CONNECTION < 1000) {
|
||||
this.onDisconnectTimerTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set a timer to delay the release of MMS network connection,
|
||||
// since the MMS requests often come consecutively in a short time.
|
||||
this.disconnectTimer.
|
||||
initWithCallback(this.onDisconnectTimerTimeout.bind(this),
|
||||
TIME_TO_RELEASE_MMS_CONNECTION,
|
||||
PREF_TIME_TO_RELEASE_MMS_CONNECTION,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
},
|
||||
|
@ -337,6 +337,7 @@ class MarionetteTestCase(CommonTestCase):
|
||||
|
||||
class MarionetteJSTestCase(CommonTestCase):
|
||||
|
||||
head_js_re = re.compile(r"MARIONETTE_HEAD_JS(\s*)=(\s*)['|\"](.*?)['|\"];")
|
||||
context_re = re.compile(r"MARIONETTE_CONTEXT(\s*)=(\s*)['|\"](.*?)['|\"];")
|
||||
timeout_re = re.compile(r"MARIONETTE_TIMEOUT(\s*)=(\s*)(\d+);")
|
||||
inactivity_timeout_re = re.compile(r"MARIONETTE_INACTIVITY_TIMEOUT(\s*)=(\s*)(\d+);")
|
||||
@ -376,6 +377,13 @@ class MarionetteJSTestCase(CommonTestCase):
|
||||
else:
|
||||
js += line
|
||||
|
||||
if os.path.basename(self.jsFile).startswith('test_'):
|
||||
head_js = self.head_js_re.search(js);
|
||||
if head_js:
|
||||
head_js = head_js.group(3)
|
||||
head = open(os.path.join(os.path.dirname(self.jsFile), head_js), 'r')
|
||||
js = head.read() + js;
|
||||
|
||||
context = self.context_re.search(js)
|
||||
if context:
|
||||
context = context.group(3)
|
||||
|
Loading…
Reference in New Issue
Block a user