Merge mozilla-central to inbound. r=merge a=merge on a CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2017-12-13 12:24:41 +02:00
Родитель 39bc975ceb b0098afaea
Коммит 71f4a218d8
99 изменённых файлов: 1745 добавлений и 689 удалений

Просмотреть файл

@ -41,7 +41,6 @@ module.exports = {
"security/**",
"testing/**",
"tools/profiler/**",
"xpcom/**"
],
"rules": {
"mozilla/use-services": "off",

Просмотреть файл

@ -1436,6 +1436,19 @@ GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc,
return disp.forget();
}
bool
AccessibleWrap::IsRootForHWND()
{
if (IsRoot()) {
return true;
}
HWND thisHwnd = GetHWNDFor(this);
AccessibleWrap* parent = static_cast<AccessibleWrap*>(Parent());
MOZ_ASSERT(parent);
HWND parentHwnd = GetHWNDFor(parent);
return thisHwnd != parentHwnd;
}
already_AddRefed<IAccessible>
AccessibleWrap::GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct)
{
@ -1484,8 +1497,9 @@ AccessibleWrap::GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct)
// Child indices (> 0) are handled below for both local and remote children.
if (XRE_IsParentProcess() && !IsProxy() &&
varChild.lVal < 0 && !sIDGen.IsChromeID(varChild.lVal)) {
if (!IsRoot()) {
// Bug 1422201: accChild with a remote id is only valid on the root accessible.
if (!IsRootForHWND()) {
// Bug 1422201, 1424657: accChild with a remote id is only valid on the
// root accessible for an HWND.
// Otherwise, we might return remote accessibles which aren't descendants
// of this accessible. This would confuse clients which use accChild to
// check whether something is a descendant of a document.

Просмотреть файл

@ -180,6 +180,12 @@ private:
const LayoutDeviceIntRect& aCaretRect);
public:
/**
* Determine whether this is the root accessible for its HWND.
*/
bool
IsRootForHWND();
/**
* Find an accessible by the given child ID in cached documents.
*/

Просмотреть файл

@ -161,7 +161,7 @@ async function doTest(aBrowser) {
let trackLoaded = false;
let audioListener = () => {
audio.removeEventListener("canplaythrough", audioListener);
audio.removeEventListener("suspend", audioListener);
audioLoaded = true;
if (audioLoaded && trackLoaded) {
@ -180,7 +180,7 @@ async function doTest(aBrowser) {
// Add the event listeners before everything in case we lose events.
audioTrack.addEventListener("load", trackListener);
audio.addEventListener("canplaythrough", audioListener);
audio.addEventListener("suspend", audioListener);
// Assign attributes for the audio element.
audioSource.setAttribute("src", audioURL + URLSuffix);
@ -198,12 +198,12 @@ async function doTest(aBrowser) {
// Append the video element into the body, and wait until it's finished.
await new Promise(resolve => {
let listener = () => {
video.removeEventListener("canplaythrough", listener);
video.removeEventListener("suspend", listener);
resolve();
};
// Add the event listener before everything in case we lose the event.
video.addEventListener("canplaythrough", listener);
video.addEventListener("suspend", listener);
// Assign attributes for the video element.
video.setAttribute("src", videoURL + URLSuffix);

Просмотреть файл

@ -1888,11 +1888,11 @@ Function ShouldInstall64Bit
; Lenovo OneKey Theater can theoretically be in a directory other than this
; one, because some installer versions let you change it, but it's unlikely.
${If} ${FileExists} "C:\Program Files (x86)\Lenovo\Onekey Theater\windowsapihookdll64.dll"
${If} ${FileExists} "$PROGRAMFILES32\Lenovo\Onekey Theater\windowsapihookdll64.dll"
Return
${EndIf}
${If} ${FileExists} "C:\Program Files (x86)\Lenovo\Energy Management\Energy Management.exe"
${If} ${FileExists} "$PROGRAMFILES32\Lenovo\Energy Management\Energy Management.exe"
Return
${EndIf}

Просмотреть файл

@ -420,6 +420,18 @@ void Elf::normalize()
ehdr->e_shoff = shdr_section->getOffset();
ehdr->e_entry = eh_entry.getValue();
ehdr->e_shstrndx = eh_shstrndx->getIndex();
// Check sections consistency
unsigned int minOffset = 0;
for (ElfSection *section = ehdr; section != nullptr; section = section->getNext()) {
unsigned int offset = section->getOffset();
if (offset < minOffset) {
throw std::runtime_error("Sections overlap");
}
if (section->getType() != SHT_NOBITS) {
minOffset = offset + section->getSize();
}
}
}
void Elf::write(std::ofstream &file)

Просмотреть файл

@ -901,13 +901,14 @@ void undo_file(const char *name, bool backup = false)
fprintf(stderr, "Not elfhacked. Skipping\n");
return;
}
if (data != text->getNext()) {
fprintf(stderr, elfhack_data " section not following " elfhack_text ". Skipping\n");
ElfSegment *first = data->getSegmentByType(PT_LOAD);
ElfSegment *second = text->getSegmentByType(PT_LOAD);
if (first != second) {
fprintf(stderr, elfhack_data " and " elfhack_text " not in the same segment. Skipping\n");
return;
}
ElfSegment *first = elf.getSegmentByType(PT_LOAD);
ElfSegment *second = elf.getSegmentByType(PT_LOAD, first);
second = elf.getSegmentByType(PT_LOAD, first);
ElfSegment *filler = nullptr;
// If the second PT_LOAD is a filler from elfhack --fill, check the third.
if (second->isElfHackFillerSegment()) {

Просмотреть файл

@ -421,6 +421,8 @@ public:
file.write(data, getSize());
}
ElfSegment *getSegmentByType(unsigned int type);
private:
friend class ElfSegment;
@ -433,8 +435,6 @@ private:
segments.erase(i, i + 1);
}
ElfSegment *getSegmentByType(unsigned int type);
void insertInSegments(std::vector<ElfSegment *> &segs);
protected:

Просмотреть файл

@ -9,8 +9,14 @@
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { debugLocalAddon, debugRemoteAddon, isTemporaryID, parseFileUri, uninstallAddon } =
require("../../modules/addon");
const {
debugLocalAddon,
debugRemoteAddon,
isLegacyTemporaryExtension,
isTemporaryID,
parseFileUri,
uninstallAddon
} = require("../../modules/addon");
const Services = require("Services");
loader.lazyImporter(this, "BrowserToolboxProcess",
@ -24,6 +30,7 @@ const Strings = Services.strings.createBundle(
const TEMP_ID_URL = "https://developer.mozilla.org/Add-ons" +
"/WebExtensions/WebExtensions_and_the_Add-on_ID";
const LEGACY_WARNING_URL = "https://wiki.mozilla.org/Add-ons/Future_of_Bootstrap";
function filePathForTarget(target) {
// Only show file system paths, and only for temporarily installed add-ons.
@ -90,7 +97,7 @@ function internalIDForTarget(target) {
function showMessages(target) {
const messages = [
...warningMessages(target.warnings),
...warningMessages(target),
...infoMessages(target),
];
if (messages.length > 0) {
@ -112,15 +119,37 @@ function infoMessages(target) {
Strings.GetStringFromName("temporaryID.learnMore")
)));
}
return messages;
}
function warningMessages(warnings = []) {
return warnings.map((warning) => {
function warningMessages(target) {
let messages = [];
if (isLegacyTemporaryExtension(target.form)) {
messages.push(dom.li(
{
className: "addon-target-warning-message addon-target-message"
},
Strings.GetStringFromName("legacyExtensionWarning"),
" ",
dom.a(
{
href: LEGACY_WARNING_URL,
target: "_blank"
},
Strings.GetStringFromName("legacyExtensionWarning.learnMore"))
));
}
let warnings = target.warnings || [];
messages = messages.concat(warnings.map((warning) => {
return dom.li(
{ className: "addon-target-warning-message addon-target-message" },
warning);
});
}));
return messages;
}
class AddonTarget extends Component {

Просмотреть файл

@ -81,6 +81,19 @@ exports.isTemporaryID = function (addonID) {
return AddonManagerPrivate.isTemporaryInstallID(addonID);
};
exports.isLegacyTemporaryExtension = function (addonForm) {
if (!addonForm.type) {
// If about:debugging is connected to an older then 59 remote Firefox, and type is
// not available on the addon/webextension actors, return false to avoid showing
// irrelevant warning messages.
return false;
}
return addonForm.type == "extension" &&
addonForm.temporarilyInstalled &&
!addonForm.isWebExtension &&
!addonForm.isAPIExtension;
};
exports.parseFileUri = function (url) {
// Strip a leading slash from Windows drive letter URIs.
// file:///home/foo ~> /home/foo

Просмотреть файл

@ -520,7 +520,7 @@ MarkupView.prototype = {
}
let parent = target, container;
while (parent !== this.doc.body) {
while (parent) {
if (parent.container) {
container = parent.container;
break;

Просмотреть файл

@ -106,6 +106,15 @@ temporaryID = This WebExtension has a temporary ID.
# the user to MDN.
temporaryID.learnMore = Learn more
# LOCALIZATION NOTE (legacyExtensionWarning):
# This string is displayed as a warning message when loading a temporary legacy extension.
legacyExtensionWarning = This is a legacy extension, be aware that these are no longer fully supported. Please read the linked documentation and then proceed with caution.
# LOCALIZATION NOTE (temporaryID.learnMore):
# This string is displayed as a link next to the legacyExtensionWarning message and leads
# the user to https://wiki.mozilla.org/Add-ons/Future_of_Bootstrap.
legacyExtensionWarning.learnMore = Learn more
# LOCALIZATION NOTE (selectAddonFromFile2):
# This string is displayed as the title of the file picker that appears when
# the user clicks the 'Load Temporary Add-on' button

Просмотреть файл

@ -85,6 +85,9 @@ BrowserAddonActor.prototype = {
iconURL: this._addon.iconURL,
debuggable: this._addon.isDebuggable,
temporarilyInstalled: this._addon.temporarilyInstalled,
type: this._addon.type,
isWebExtension: this._addon.isWebExtension,
isAPIExtension: this._addon.isAPIExtension,
consoleActor: this._consoleActor.actorID,
traits: {

Просмотреть файл

@ -73,7 +73,9 @@ const WebExtensionParentActor = protocol.ActorClassWithSpec(webExtensionSpec, {
iconURL: this.addon.iconURL,
debuggable: this.addon.isDebuggable,
temporarilyInstalled: this.addon.temporarilyInstalled,
isWebExtension: true,
type: this.addon.type,
isWebExtension: this.addon.isWebExtension,
isAPIExtension: this.addon.isAPIExtension,
manifestURL: policy && policy.getURL("manifest.json"),
warnings: ExtensionParent.DebugUtils.getExtensionManifestWarnings(this.id),
};

Просмотреть файл

@ -146,7 +146,7 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE;
MOZ_RELEASE_ASSERT(GetErrorArgCount(errorNumber) <= 2);
JS_ReportErrorNumberUC(aCx, GetErrorMessage, nullptr,
static_cast<const unsigned>(errorNumber),
static_cast<unsigned>(errorNumber),
funcNameStr.get(), ifaceName.get());
return false;
}
@ -253,7 +253,7 @@ TErrorResult<CleanupPolicy>::SetPendingExceptionWithMessage(JSContext* aCx)
args[argCount] = nullptr;
JS_ReportErrorNumberUCArray(aCx, dom::GetErrorMessage, nullptr,
static_cast<const unsigned>(message->mErrorNumber),
static_cast<unsigned>(message->mErrorNumber),
argCount > 0 ? args : nullptr);
ClearMessage();

Просмотреть файл

@ -159,13 +159,4 @@ BaseMediaResource::ModifyLoadFlags(nsLoadFlags aFlags)
}
}
void
BaseMediaResource::DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset)
{
if (aNumBytes <= 0) {
return;
}
mCallback->NotifyBytesConsumed(aNumBytes, aOffset);
}
} // namespace mozilla

Просмотреть файл

@ -133,10 +133,6 @@ protected:
// then the request is added back to the load group.
void ModifyLoadFlags(nsLoadFlags aFlags);
// Dispatches an event to call MediaDecoder::NotifyBytesConsumed(aNumBytes, aOffset)
// on the main thread. This is called automatically after every read.
void DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset);
RefPtr<MediaResourceCallback> mCallback;
// Channel used to download the media data. Must be accessed

Просмотреть файл

@ -170,30 +170,11 @@ ChannelMediaDecoder::ResourceCallback::NotifySuspendedStatusChanged(
}
}
void
ChannelMediaDecoder::ResourceCallback::NotifyBytesConsumed(int64_t aBytes,
int64_t aOffset)
{
RefPtr<ResourceCallback> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"ChannelMediaDecoder::ResourceCallback::NotifyBytesConsumed",
[=]() {
if (self->mDecoder) {
self->mDecoder->NotifyBytesConsumed(aBytes, aOffset);
}
});
mAbstractMainThread->Dispatch(r.forget());
}
ChannelMediaDecoder::ChannelMediaDecoder(MediaDecoderInit& aInit)
: MediaDecoder(aInit)
, mResourceCallback(new ResourceCallback(aInit.mOwner->AbstractMainThread()))
, mWatchManager(this, aInit.mOwner->AbstractMainThread())
{
mResourceCallback->Connect(this);
// mIgnoreProgressData
mWatchManager.Watch(mLogicallySeeking, &ChannelMediaDecoder::SeekingChanged);
}
/* static */
@ -260,7 +241,6 @@ MediaDecoderStateMachine* ChannelMediaDecoder::CreateStateMachine()
void
ChannelMediaDecoder::Shutdown()
{
mWatchManager.Shutdown();
mResourceCallback->Disconnect();
MediaDecoder::Shutdown();
@ -335,7 +315,17 @@ ChannelMediaDecoder::NotifyDownloadEnded(nsresult aStatus)
MediaDecoderOwner* owner = GetOwner();
if (NS_SUCCEEDED(aStatus) || aStatus == NS_BASE_STREAM_CLOSED) {
UpdatePlaybackRate(ComputePlaybackRate());
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
stats = mPlaybackStatistics,
res = RefPtr<BaseMediaResource>(mResource),
duration = mDuration
]() {
auto rate = ComputePlaybackRate(stats, res, duration);
UpdatePlaybackRate(rate, res);
});
nsresult rv = GetStateMachine()->OwnerThread()->Dispatch(r.forget());
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
owner->DownloadSuspended();
// NotifySuspendedStatusChanged will tell the element that download
// has been suspended "by the cache", which is true since we never
@ -349,36 +339,11 @@ ChannelMediaDecoder::NotifyDownloadEnded(nsresult aStatus)
}
}
void
ChannelMediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
AbstractThread::AutoEnter context(AbstractMainThread());
if (mIgnoreProgressData) {
return;
}
MOZ_ASSERT(GetStateMachine());
mDecoderPosition = aOffset + aBytes;
}
void
ChannelMediaDecoder::SeekingChanged()
{
// Stop updating the bytes downloaded for progress notifications when
// seeking to prevent wild changes to the progress notification.
MOZ_ASSERT(NS_IsMainThread());
mIgnoreProgressData = mLogicallySeeking;
}
bool
ChannelMediaDecoder::CanPlayThroughImpl()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(GetStateMachine(), false);
return GetStatistics(ComputePlaybackRate()).CanPlayThrough();
return mCanPlayThrough;
}
bool
@ -423,7 +388,17 @@ ChannelMediaDecoder::DurationChanged()
AbstractThread::AutoEnter context(AbstractMainThread());
MediaDecoder::DurationChanged();
// Duration has changed so we should recompute playback rate
UpdatePlaybackRate(ComputePlaybackRate());
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
stats = mPlaybackStatistics,
res = RefPtr<BaseMediaResource>(mResource),
duration = mDuration
]() {
auto rate = ComputePlaybackRate(stats, res, duration);
UpdatePlaybackRate(rate, res);
});
nsresult rv = GetStateMachine()->OwnerThread()->Dispatch(r.forget());
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
}
void
@ -431,36 +406,59 @@ ChannelMediaDecoder::DownloadProgressed()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
AbstractThread::AutoEnter context(AbstractMainThread());
GetOwner()->DownloadProgressed();
auto rate = ComputePlaybackRate();
UpdatePlaybackRate(rate);
MediaStatistics stats = GetStatistics(rate);
GetStateMachine()->DispatchCanPlayThrough(stats.CanPlayThrough());
mResource->ThrottleReadahead(ShouldThrottleDownload(stats));
using StatsPromise = MozPromise<MediaStatistics, bool, true>;
InvokeAsync(GetStateMachine()->OwnerThread(),
__func__,
[
playbackStats = mPlaybackStatistics,
res = RefPtr<BaseMediaResource>(mResource),
duration = mDuration,
pos = mPlaybackPosition
]() {
auto rate = ComputePlaybackRate(playbackStats, res, duration);
UpdatePlaybackRate(rate, res);
MediaStatistics stats = GetStatistics(rate, res, pos);
return StatsPromise::CreateAndResolve(stats, __func__);
})
->Then(
mAbstractMainThread,
__func__,
[ =, self = RefPtr<ChannelMediaDecoder>(this) ](MediaStatistics aStats) {
if (IsShutdown()) {
return;
}
mCanPlayThrough = aStats.CanPlayThrough();
GetStateMachine()->DispatchCanPlayThrough(mCanPlayThrough);
mResource->ThrottleReadahead(ShouldThrottleDownload(aStats));
AbstractThread::AutoEnter context(AbstractMainThread());
GetOwner()->DownloadProgressed();
},
[]() { MOZ_ASSERT_UNREACHABLE("Promise not resolved"); });
}
ChannelMediaDecoder::PlaybackRateInfo
ChannelMediaDecoder::ComputePlaybackRate()
/* static */ ChannelMediaDecoder::PlaybackRateInfo
ChannelMediaDecoder::ComputePlaybackRate(const MediaChannelStatistics& aStats,
BaseMediaResource* aResource,
double aDuration)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mResource);
MOZ_ASSERT(!NS_IsMainThread());
int64_t length = mResource->GetLength();
if (mozilla::IsFinite<double>(mDuration) && mDuration > 0 && length >= 0) {
return { uint32_t(length / mDuration), true };
int64_t length = aResource->GetLength();
if (mozilla::IsFinite<double>(aDuration) && aDuration > 0 && length >= 0) {
return { uint32_t(length / aDuration), true };
}
bool reliable = false;
uint32_t rate = mPlaybackStatistics.GetRate(&reliable);
uint32_t rate = aStats.GetRate(&reliable);
return { rate, reliable };
}
void
ChannelMediaDecoder::UpdatePlaybackRate(const PlaybackRateInfo& aInfo)
/* static */ void
ChannelMediaDecoder::UpdatePlaybackRate(const PlaybackRateInfo& aInfo,
BaseMediaResource* aResource)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mResource);
MOZ_ASSERT(!NS_IsMainThread());
uint32_t rate = aInfo.mRate;
@ -473,23 +471,23 @@ ChannelMediaDecoder::UpdatePlaybackRate(const PlaybackRateInfo& aInfo)
rate = std::max(rate, 10000u);
}
mResource->SetPlaybackRate(rate);
aResource->SetPlaybackRate(rate);
}
MediaStatistics
ChannelMediaDecoder::GetStatistics(const PlaybackRateInfo& aInfo)
/* static */ MediaStatistics
ChannelMediaDecoder::GetStatistics(const PlaybackRateInfo& aInfo,
BaseMediaResource* aRes,
int64_t aPlaybackPosition)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mResource);
MOZ_ASSERT(!NS_IsMainThread());
MediaStatistics result;
result.mDownloadRate =
mResource->GetDownloadRate(&result.mDownloadRateReliable);
result.mDownloadPosition = mResource->GetCachedDataEnd(mDecoderPosition);
result.mTotalBytes = mResource->GetLength();
result.mDownloadRate = aRes->GetDownloadRate(&result.mDownloadRateReliable);
result.mDownloadPosition = aRes->GetCachedDataEnd(aPlaybackPosition);
result.mTotalBytes = aRes->GetLength();
result.mPlaybackRate = aInfo.mRate;
result.mPlaybackRateReliable = aInfo.mReliable;
result.mPlaybackPosition = mPlaybackPosition;
result.mPlaybackPosition = aPlaybackPosition;
return result;
}

Просмотреть файл

@ -50,7 +50,6 @@ class ChannelMediaDecoder
void NotifyDataEnded(nsresult aStatus) override;
void NotifyPrincipalChanged() override;
void NotifySuspendedStatusChanged(bool aSuspendedByCache) override;
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) override;
static void TimerCallback(nsITimer* aTimer, void* aClosure);
@ -121,8 +120,6 @@ private:
// by the MediaResource read functions.
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset);
void SeekingChanged();
bool CanPlayThroughImpl() override final;
bool IsLiveStream() override final;
@ -133,28 +130,26 @@ private:
bool mReliable; // True if mRate is a reliable estimate.
};
// The actual playback rate computation.
PlaybackRateInfo ComputePlaybackRate();
static PlaybackRateInfo ComputePlaybackRate(
const MediaChannelStatistics& aStats,
BaseMediaResource* aResource,
double aDuration);
// Something has changed that could affect the computed playback rate,
// so recompute it.
void UpdatePlaybackRate(const PlaybackRateInfo& aInfo);
static void UpdatePlaybackRate(const PlaybackRateInfo& aInfo,
BaseMediaResource* aResource);
// Return statistics. This is used for progress events and other things.
// This can be called from any thread. It's only a snapshot of the
// current state, since other threads might be changing the state
// at any time.
MediaStatistics GetStatistics(const PlaybackRateInfo& aInfo);
static MediaStatistics GetStatistics(const PlaybackRateInfo& aInfo,
BaseMediaResource* aRes,
int64_t aPlaybackPosition);
bool ShouldThrottleDownload(const MediaStatistics& aStats);
WatchManager<ChannelMediaDecoder> mWatchManager;
// True when seeking or otherwise moving the play position around in
// such a manner that progress event data is inaccurate. This is set
// during seek and duration operations to prevent the progress indicator
// from jumping around. Read/Write on the main thread only.
bool mIgnoreProgressData = false;
// Data needed to estimate playback data rate. The timeline used for
// this estimate is "decode time" (where the "current time" is the
// time of the last decoded video frame).
@ -169,6 +164,8 @@ private:
// during decoder seek operations, but it's updated at the end when we
// start playing back again.
int64_t mPlaybackPosition = 0;
bool mCanPlayThrough = false;
};
} // namespace mozilla

Просмотреть файл

@ -621,12 +621,7 @@ nsresult ChannelMediaResource::ReadAt(int64_t aOffset,
uint32_t* aBytes)
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
nsresult rv = mCacheStream.ReadAt(aOffset, aBuffer, aCount, aBytes);
if (NS_SUCCEEDED(rv)) {
DispatchBytesConsumed(*aBytes, aOffset);
}
return rv;
return mCacheStream.ReadAt(aOffset, aBuffer, aCount, aBytes);
}
void
@ -778,8 +773,7 @@ ChannelMediaResource::RecreateChannel()
void
ChannelMediaResource::CacheClientNotifyDataReceived()
{
SystemGroup::Dispatch(
TaskCategory::Other,
mCallback->AbstractMainThread()->Dispatch(
NewRunnableMethod("MediaResourceCallback::NotifyDataArrived",
mCallback.get(),
&MediaResourceCallback::NotifyDataArrived));

Просмотреть файл

@ -171,9 +171,6 @@ FileMediaResource::ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount,
if (NS_FAILED(rv)) return rv;
rv = UnsafeRead(aBuffer, aCount, aBytes);
}
if (NS_SUCCEEDED(rv)) {
DispatchBytesConsumed(*aBytes, aOffset);
}
return rv;
}

Просмотреть файл

@ -2436,7 +2436,7 @@ MediaCacheStream::GetNextCachedData(int64_t aOffset)
int64_t
MediaCacheStream::GetCachedDataEnd(int64_t aOffset)
{
// TODO: Assert non-main thread.
MOZ_ASSERT(!NS_IsMainThread());
AutoLock lock(mMediaCache->Monitor());
return GetCachedDataEndInternal(lock, aOffset);
}
@ -2542,18 +2542,14 @@ MediaCacheStream::SetReadMode(ReadMode aMode)
void
MediaCacheStream::SetPlaybackRate(uint32_t aBytesPerSecond)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aBytesPerSecond > 0, "Zero playback rate not allowed");
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"MediaCacheStream::SetPlaybackRate",
[ =, client = RefPtr<ChannelMediaResource>(mClient) ]() {
AutoLock lock(mMediaCache->Monitor());
if (!mClosed && mPlaybackBytesPerSecond != aBytesPerSecond) {
mPlaybackBytesPerSecond = aBytesPerSecond;
mMediaCache->QueueUpdate(lock);
}
});
OwnerThread()->Dispatch(r.forget());
AutoLock lock(mMediaCache->Monitor());
if (!mClosed && mPlaybackBytesPerSecond != aBytesPerSecond) {
mPlaybackBytesPerSecond = aBytesPerSecond;
mMediaCache->QueueUpdate(lock);
}
}
nsresult
@ -2947,7 +2943,7 @@ nsresult MediaCacheStream::GetCachedRanges(MediaByteRangeSet& aRanges)
double
MediaCacheStream::GetDownloadRate(bool* aIsReliable)
{
// TODO: Assert non-main thread.
MOZ_ASSERT(!NS_IsMainThread());
AutoLock lock(mMediaCache->Monitor());
return mDownloadStatistics.GetRate(aIsReliable);
}

Просмотреть файл

@ -60,7 +60,8 @@ public:
}
mAccumulatedBytes += aBytes;
}
double GetRateAtLastStop(bool* aReliable) {
double GetRateAtLastStop(bool* aReliable) const
{
double seconds = mAccumulatedTime.ToSeconds();
*aReliable = (seconds >= 1.0) ||
(mAccumulatedBytes >= RELIABLE_DATA_THRESHOLD);
@ -68,7 +69,8 @@ public:
return 0.0;
return static_cast<double>(mAccumulatedBytes)/seconds;
}
double GetRate(bool* aReliable) {
double GetRate(bool* aReliable) const
{
TimeDuration time = mAccumulatedTime;
if (mIsStarted) {
time += TimeStamp::Now() - mLastStartTime;

Просмотреть файл

@ -652,12 +652,6 @@ protected:
// background.
bool mIsBackgroundVideoDecodingAllowed;
// Current decoding position in the stream. This is where the decoder
// is up to consuming the stream. This is not adjusted during decoder
// seek operations, but it's updated at the end when we start playing
// back again.
int64_t mDecoderPosition = 0;
public:
AbstractCanonical<double>* CanonicalVolume() { return &mVolume; }
AbstractCanonical<bool>* CanonicalPreservesPitch()

Просмотреть файл

@ -833,15 +833,6 @@ public:
mSeekJob = Move(aSeekJob);
mVisibility = aVisibility;
// Always switch off the blank decoder otherwise we might become visible
// in the middle of seeking and won't have a valid video frame to show
// when seek is done.
if (mMaster->mVideoDecodeSuspended) {
mMaster->mVideoDecodeSuspended = false;
mMaster->mOnPlaybackEvent.Notify(MediaPlaybackEvent::ExitVideoSuspend);
Reader()->SetVideoBlankDecode(false);
}
// Suppressed visibility comes from two cases: (1) leaving dormant state,
// and (2) resuming suspended video decoder. We want both cases to be
// transparent to the user. So we only notify the change when the seek
@ -884,8 +875,7 @@ public:
void HandleResumeVideoDecoding(const TimeUnit&) override
{
// We set mVideoDecodeSuspended to false in Enter().
MOZ_ASSERT(false, "Shouldn't have suspended video decoding.");
// Do nothing. We will resume video decoding in the decoding state.
}
protected:
@ -2116,6 +2106,10 @@ StateObject::HandleResumeVideoDecoding(const TimeUnit& aTarget)
{
MOZ_ASSERT(mMaster->mVideoDecodeSuspended);
mMaster->mVideoDecodeSuspended = false;
mMaster->mOnPlaybackEvent.Notify(MediaPlaybackEvent::ExitVideoSuspend);
Reader()->SetVideoBlankDecode(false);
// Start counting recovery time from right now.
TimeStamp start = TimeStamp::Now();
@ -2278,6 +2272,12 @@ DecodingState::Enter()
{
MOZ_ASSERT(mMaster->mSentFirstFrameLoadedEvent);
if (mMaster->mVideoDecodeSuspended &&
mMaster->mVideoDecodeMode == VideoDecodeMode::Normal) {
StateObject::HandleResumeVideoDecoding(mMaster->GetMediaTime());
return;
}
if (mMaster->mVideoDecodeMode == VideoDecodeMode::Suspend &&
!mMaster->mVideoDecodeSuspendTimer.IsScheduled() &&
!mMaster->mVideoDecodeSuspended) {

Просмотреть файл

@ -196,6 +196,9 @@ public:
DECODER_STATE_SHUTDOWN
};
// Returns the state machine task queue.
TaskQueue* OwnerThread() const { return mTaskQueue; }
RefPtr<MediaDecoder::DebugInfoPromise> RequestDebugInfo();
void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
@ -337,9 +340,6 @@ private:
bool HasVideo() const { return mInfo.ref().HasVideo(); }
const MediaInfo& Info() const { return mInfo.ref(); }
// Returns the state machine task queue.
TaskQueue* OwnerThread() const { return mTaskQueue; }
// Schedules the shared state machine thread to run the state machine.
void ScheduleStateMachine();

Просмотреть файл

@ -58,9 +58,6 @@ public:
// Notify that the "cache suspended" status of MediaResource changes.
virtual void NotifySuspendedStatusChanged(bool aSuspendedByCache) {}
// Notify the number of bytes read from the resource.
virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) {}
protected:
virtual ~MediaResourceCallback() {}
};

Просмотреть файл

@ -104,6 +104,7 @@ UNIFIED_SOURCES += [
]
DIRS += [
'rlz',
'widevine-adapter',
]

4
dom/media/gmp/rlz/OWNERS Normal file
Просмотреть файл

@ -0,0 +1,4 @@
rogerta@chromium.org
thakis@chromium.org
# COMPONENT: Internals>Core

Просмотреть файл

@ -0,0 +1,4 @@
Code taken from rlz project in Chromium repository: https://chromium.googlesource.com/chromium/src.git/+/6f3478dfd7d29b9872871718bd08493ed0c8bc8e
Note: base/ contains wrappers/dummies to provide implementations of the
Chromium APIs that this code relies upon.

Просмотреть файл

@ -0,0 +1,14 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 FAKE_ASSERT_H_
#define FAKE_ASSERT_H_
#include <assert.h>
#define ASSERT_STRING(x) { assert(false); }
#define VERIFY(x) { assert(x); };
#endif

Просмотреть файл

@ -0,0 +1,90 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rlz/lib/crc8.h"
namespace {
// The CRC lookup table used for ATM HES (Polynomial = 0x07).
// These are 256 unique 8-bit values.
const unsigned char kCrcTable[256] = {
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
};
} // namespace anonymous
namespace rlz_lib {
bool Crc8::Generate(const unsigned char *data, int length,
unsigned char* check_sum) {
if (!check_sum)
return false;
*check_sum = 0;
if (!data)
return false;
// The inital and final constants are as used in the ATM HEC.
static const unsigned char kInitial = 0x00;
static const unsigned char kFinal = 0x55;
unsigned char crc = kInitial;
for (int i = 0; i < length; ++i) {
crc = kCrcTable[(data[i] ^ crc) & 0xFFU];
}
*check_sum = crc ^ kFinal;
return true;
}
bool Crc8::Verify(const unsigned char* data, int length,
unsigned char check_sum, bool* matches) {
if (!matches)
return false;
*matches = false;
if (!data)
return false;
unsigned char calculated_crc;
if (!Generate(data, length, &calculated_crc))
return false;
*matches = check_sum == calculated_crc;
return true;
}
} // namespace rlz_lib

Просмотреть файл

@ -0,0 +1,24 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Crc8 utility functions.
#ifndef RLZ_LIB_CRC8_H_
#define RLZ_LIB_CRC8_H_
namespace rlz_lib {
// CRC-8 methods:
class Crc8 {
public:
static bool Generate(const unsigned char* data,
int length,
unsigned char* check_sum);
static bool Verify(const unsigned char* data,
int length,
unsigned char checksum,
bool * matches);
};
}; // namespace rlz_lib
#endif // RLZ_LIB_CRC8_H_

Просмотреть файл

@ -0,0 +1,93 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rlz/lib/machine_id.h"
#include <stddef.h>
#include "rlz/lib/assert.h"
#include "rlz/lib/crc8.h"
#include "rlz/lib/string_utils.h"
// Note: The original machine_id.cc code depends on Chromium's sha1 implementation.
// Using Mozilla's implmentation as replacement to reduce the dependency of
// some external files.
#include "mozilla/SHA1.h"
namespace rlz_lib {
bool GetMachineId(std::string* machine_id) {
if (!machine_id)
return false;
static std::string calculated_id;
static bool calculated = false;
if (calculated) {
*machine_id = calculated_id;
return true;
}
std::vector<uint8_t> sid_bytes;
int volume_id;
if (!GetRawMachineId(&sid_bytes, &volume_id))
return false;
if (!testing::GetMachineIdImpl(sid_bytes, volume_id, machine_id))
return false;
calculated = true;
calculated_id = *machine_id;
return true;
}
namespace testing {
bool GetMachineIdImpl(const std::vector<uint8_t>& sid_bytes,
int volume_id,
std::string* machine_id) {
machine_id->clear();
// The ID should be the SID hash + the Hard Drive SNo. + checksum byte.
static const int kSizeWithoutChecksum = mozilla::SHA1Sum::kHashSize + sizeof(int);
std::basic_string<unsigned char> id_binary(kSizeWithoutChecksum + 1, 0);
if (!sid_bytes.empty()) {
// In order to be compatible with the old version of RLZ, the hash of the
// SID must be done with all the original bytes from the unicode string.
// However, the chromebase SHA1 hash function takes only an std::string as
// input, so the unicode string needs to be converted to std::string
// "as is".
size_t byte_count = sid_bytes.size() * sizeof(std::vector<uint8_t>::value_type);
const char* buffer = reinterpret_cast<const char*>(sid_bytes.data());
// Note that digest can have embedded nulls.
mozilla::SHA1Sum SHA1;
mozilla::SHA1Sum::Hash hash;
SHA1.update(buffer, byte_count);
SHA1.finish(hash);
std::string digest(reinterpret_cast<char*>(hash), mozilla::SHA1Sum::kHashSize);
VERIFY(digest.size() == mozilla::SHA1Sum::kHashSize);
std::copy(digest.begin(), digest.end(), id_binary.begin());
}
// Convert from int to binary (makes big-endian).
for (size_t i = 0; i < sizeof(int); i++) {
int shift_bits = 8 * (sizeof(int) - i - 1);
id_binary[mozilla::SHA1Sum::kHashSize + i] = static_cast<unsigned char>(
(volume_id >> shift_bits) & 0xFF);
}
// Append the checksum byte.
if (!sid_bytes.empty() || (0 != volume_id))
rlz_lib::Crc8::Generate(id_binary.c_str(),
kSizeWithoutChecksum,
&id_binary[kSizeWithoutChecksum]);
return rlz_lib::BytesToString(
id_binary.c_str(), kSizeWithoutChecksum + 1, machine_id);
}
} // namespace testing
} // namespace rlz_lib

Просмотреть файл

@ -0,0 +1,33 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef RLZ_LIB_MACHINE_ID_H_
#define RLZ_LIB_MACHINE_ID_H_
#include <string>
#include <vector>
namespace rlz_lib {
// Gets the unique ID for the machine used for RLZ tracking purposes. On
// Windows, this ID is derived from the Windows machine SID, and is the string
// representation of a 20 byte hash + 4 bytes volum id + a 1 byte checksum.
// Included in financial pings with events, unless explicitly forbidden by the
// calling application.
bool GetMachineId(std::string* machine_id);
// Retrieves a raw machine identifier string and a machine-specific
// 4 byte value. GetMachineId() will SHA1 |data|, append |more_data|, compute
// the Crc8 of that, and return a hex-encoded string of that data.
bool GetRawMachineId(std::vector<uint8_t>* data, int* more_data);
namespace testing {
bool GetMachineIdImpl(const std::vector<uint8_t>& sid_bytes,
int volume_id,
std::string* machine_id);
} // namespace testing
} // namespace rlz_lib
#endif // RLZ_LIB_MACHINE_ID_H_

Просмотреть файл

@ -0,0 +1,34 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// String manipulation functions used in the RLZ library.
#include "rlz/lib/string_utils.h"
namespace rlz_lib {
bool BytesToString(const unsigned char* data,
int data_len,
std::string* string) {
if (!string)
return false;
string->clear();
if (data_len < 1 || !data)
return false;
static const char kHex[] = "0123456789ABCDEF";
// Fix the buffer size to begin with to avoid repeated re-allocation.
string->resize(data_len * 2);
int index = data_len;
while (index--) {
string->at(2 * index) = kHex[data[index] >> 4]; // high digit
string->at(2 * index + 1) = kHex[data[index] & 0x0F]; // low digit
}
return true;
}
} // namespace rlz_lib

Просмотреть файл

@ -0,0 +1,20 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// String manipulation functions used in the RLZ library.
#ifndef RLZ_LIB_STRING_UTILS_H_
#define RLZ_LIB_STRING_UTILS_H_
#include <string>
namespace rlz_lib {
bool BytesToString(const unsigned char* data,
int data_len,
std::string* string);
}; // namespace
#endif // RLZ_LIB_STRING_UTILS_H_

Просмотреть файл

@ -0,0 +1,322 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetController.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include <string>
// Note: The original machine_id_mac.cc code is in namespace rlz_lib below.
// It depends on some external files, which would bring in a log of Chromium
// code if imported as well.
// Instead only the necessary code has been extracted from the relevant files,
// and further combined and reduced to limit the maintenance burden.
// [Extracted from base/logging.h]
#define DCHECK assert
namespace base {
// [Extracted from base/mac/scoped_typeref.h and base/mac/scoped_cftyperef.h]
template<typename T>
class ScopedCFTypeRef {
public:
typedef T element_type;
explicit ScopedCFTypeRef(T object)
: object_(object) {
}
ScopedCFTypeRef(const ScopedCFTypeRef<T>& that) = delete;
ScopedCFTypeRef(ScopedCFTypeRef<T>&& that) = delete;
~ScopedCFTypeRef() {
if (object_)
CFRelease(object_);
}
ScopedCFTypeRef& operator=(const ScopedCFTypeRef<T>& that) = delete;
ScopedCFTypeRef& operator=(ScopedCFTypeRef<T>&& that) = delete;
operator T() const {
return object_;
}
// ScopedCFTypeRef<>::release() is like scoped_ptr<>::release. It is NOT
// a wrapper for CFRelease().
T release() {
T temp = object_;
object_ = NULL;
return temp;
}
private:
T object_;
};
namespace mac {
// [Extracted from base/mac/scoped_ioobject.h]
// Just like ScopedCFTypeRef but for io_object_t and subclasses.
template<typename IOT>
class ScopedIOObject {
public:
typedef IOT element_type;
explicit ScopedIOObject(IOT object = IO_OBJECT_NULL)
: object_(object) {
}
~ScopedIOObject() {
if (object_)
IOObjectRelease(object_);
}
ScopedIOObject(const ScopedIOObject&) = delete;
void operator=(const ScopedIOObject&) = delete;
void reset(IOT object = IO_OBJECT_NULL) {
if (object_)
IOObjectRelease(object_);
object_ = object;
}
operator IOT() const {
return object_;
}
private:
IOT object_;
};
// [Extracted from base/mac/foundation_util.h]
template<typename T>
T CFCast(const CFTypeRef& cf_val);
template<>
CFDataRef
CFCast<CFDataRef>(const CFTypeRef& cf_val) {
if (cf_val == NULL) {
return NULL;
}
if (CFGetTypeID(cf_val) == CFDataGetTypeID()) {
return (CFDataRef)(cf_val);
}
return NULL;
}
template<>
CFStringRef
CFCast<CFStringRef>(const CFTypeRef& cf_val) {
if (cf_val == NULL) {
return NULL;
}
if (CFGetTypeID(cf_val) == CFStringGetTypeID()) {
return (CFStringRef)(cf_val);
}
return NULL;
}
} // namespace mac
// [Extracted from base/strings/sys_string_conversions_mac.mm]
static const CFStringEncoding kNarrowStringEncoding = kCFStringEncodingUTF8;
template<typename StringType>
static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring,
CFStringEncoding encoding) {
CFIndex length = CFStringGetLength(cfstring);
if (length == 0)
return StringType();
CFRange whole_string = CFRangeMake(0, length);
CFIndex out_size;
CFIndex converted = CFStringGetBytes(cfstring,
whole_string,
encoding,
0, // lossByte
false, // isExternalRepresentation
NULL, // buffer
0, // maxBufLen
&out_size);
if (converted == 0 || out_size == 0)
return StringType();
// out_size is the number of UInt8-sized units needed in the destination.
// A buffer allocated as UInt8 units might not be properly aligned to
// contain elements of StringType::value_type. Use a container for the
// proper value_type, and convert out_size by figuring the number of
// value_type elements per UInt8. Leave room for a NUL terminator.
typename StringType::size_type elements =
out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1;
std::vector<typename StringType::value_type> out_buffer(elements);
converted = CFStringGetBytes(cfstring,
whole_string,
encoding,
0, // lossByte
false, // isExternalRepresentation
reinterpret_cast<UInt8*>(&out_buffer[0]),
out_size,
NULL); // usedBufLen
if (converted == 0)
return StringType();
out_buffer[elements - 1] = '\0';
return StringType(&out_buffer[0], elements - 1);
}
std::string SysCFStringRefToUTF8(CFStringRef ref)
{
return CFStringToSTLStringWithEncodingT<std::string>(ref,
kNarrowStringEncoding);
}
} // namespace base
namespace rlz_lib {
namespace {
// See http://developer.apple.com/library/mac/#technotes/tn1103/_index.html
// The caller is responsible for freeing |matching_services|.
bool FindEthernetInterfaces(io_iterator_t* matching_services) {
base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict(
IOServiceMatching(kIOEthernetInterfaceClass));
if (!matching_dict)
return false;
base::ScopedCFTypeRef<CFMutableDictionaryRef> primary_interface(
CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
if (!primary_interface)
return false;
CFDictionarySetValue(
primary_interface, CFSTR(kIOPrimaryInterface), kCFBooleanTrue);
CFDictionarySetValue(
matching_dict, CFSTR(kIOPropertyMatchKey), primary_interface);
kern_return_t kern_result = IOServiceGetMatchingServices(
kIOMasterPortDefault, matching_dict.release(), matching_services);
return kern_result == KERN_SUCCESS;
}
bool GetMACAddressFromIterator(io_iterator_t primary_interface_iterator,
uint8_t* buffer, size_t buffer_size) {
if (buffer_size < kIOEthernetAddressSize)
return false;
bool success = false;
bzero(buffer, buffer_size);
base::mac::ScopedIOObject<io_object_t> primary_interface;
for (primary_interface.reset(IOIteratorNext(primary_interface_iterator));
primary_interface;
primary_interface.reset(IOIteratorNext(primary_interface_iterator))) {
io_object_t primary_interface_parent;
kern_return_t kern_result = IORegistryEntryGetParentEntry(
primary_interface, kIOServicePlane, &primary_interface_parent);
base::mac::ScopedIOObject<io_object_t> primary_interface_parent_deleter(
primary_interface_parent);
success = kern_result == KERN_SUCCESS;
if (!success)
continue;
base::ScopedCFTypeRef<CFTypeRef> mac_data(
IORegistryEntryCreateCFProperty(primary_interface_parent,
CFSTR(kIOMACAddress),
kCFAllocatorDefault,
0));
CFDataRef mac_data_data = base::mac::CFCast<CFDataRef>(mac_data);
if (mac_data_data) {
CFDataGetBytes(
mac_data_data, CFRangeMake(0, kIOEthernetAddressSize), buffer);
}
}
return success;
}
bool GetMacAddress(unsigned char* buffer, size_t size) {
io_iterator_t primary_interface_iterator;
if (!FindEthernetInterfaces(&primary_interface_iterator))
return false;
bool result = GetMACAddressFromIterator(
primary_interface_iterator, buffer, size);
IOObjectRelease(primary_interface_iterator);
return result;
}
CFStringRef CopySerialNumber() {
base::mac::ScopedIOObject<io_service_t> expert_device(
IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("IOPlatformExpertDevice")));
if (!expert_device)
return NULL;
base::ScopedCFTypeRef<CFTypeRef> serial_number(
IORegistryEntryCreateCFProperty(expert_device,
CFSTR(kIOPlatformSerialNumberKey),
kCFAllocatorDefault,
0));
CFStringRef serial_number_cfstring =
base::mac::CFCast<CFStringRef>(serial_number.release());
if (!serial_number_cfstring)
return NULL;
return serial_number_cfstring;
}
} // namespace
bool GetRawMachineId(std::vector<uint8_t>* data, int* more_data) {
uint8_t mac_address[kIOEthernetAddressSize];
std::string id;
if (GetMacAddress(mac_address, sizeof(mac_address))) {
id += "mac:";
static const char hex[] =
{ '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
for (int i = 0; i < kIOEthernetAddressSize; ++i) {
uint8_t byte = mac_address[i];
id += hex[byte >> 4];
id += hex[byte & 0xF];
}
}
// A MAC address is enough to uniquely identify a machine, but it's only 6
// bytes, 3 of which are manufacturer-determined. To make brute-forcing the
// SHA1 of this harder, also append the system's serial number.
CFStringRef serial = CopySerialNumber();
if (serial) {
if (!id.empty()) {
id += ' ';
}
id += "serial:";
id += base::SysCFStringRefToUTF8(serial);
CFRelease(serial);
}
// Get the contents of the string 'id' as a bunch of bytes.
data->assign(&id[0], &id[id.size()]);
// On windows, this is set to the volume id. Since it's not scrambled before
// being sent, just set it to 1.
*more_data = 1;
return true;
}
} // namespace rlz_lib

Просмотреть файл

@ -0,0 +1,34 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Note: build rlz in its own moz.build, so it doesn't pickup any of
# Chromium IPC's headers used in the moz.build of the parent file.
FINAL_LIBRARY = 'xul'
if CONFIG['OS_TARGET'] in ['WINNT', 'Darwin']:
UNIFIED_SOURCES += [
'lib/crc8.cc',
'lib/machine_id.cc',
'lib/string_utils.cc',
]
if CONFIG['OS_TARGET'] == 'WINNT':
UNIFIED_SOURCES += [
'win/lib/machine_id_win.cc',
]
if CONFIG['OS_TARGET'] == 'Darwin':
UNIFIED_SOURCES += [
'mac/lib/machine_id_mac.cc',
]
OS_LIBS += [
'-framework IOKit',
]
LOCAL_INCLUDES += [
'..',
]

Просмотреть файл

@ -0,0 +1,136 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <windows.h>
#include <sddl.h> // For ConvertSidToStringSidW.
#include <memory>
#include <string>
#include <vector>
#include "mozilla/ArrayUtils.h"
#include "rlz/lib/assert.h"
namespace rlz_lib {
namespace {
bool GetSystemVolumeSerialNumber(int* number) {
if (!number)
return false;
*number = 0;
// Find the system root path (e.g: C:\).
wchar_t system_path[MAX_PATH + 1];
if (!GetSystemDirectoryW(system_path, MAX_PATH))
return false;
wchar_t* first_slash = wcspbrk(system_path, L"\\/");
if (first_slash != NULL)
*(first_slash + 1) = 0;
DWORD number_local = 0;
if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL,
NULL, 0))
return false;
*number = (int)number_local;
return true;
}
bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) {
static const DWORD kStartDomainLength = 128; // reasonable to start with
std::unique_ptr<wchar_t[]> domain_buffer(new wchar_t[kStartDomainLength]);
DWORD domain_size = kStartDomainLength;
DWORD sid_dword_size = sid_size;
SID_NAME_USE sid_name_use;
BOOL success = ::LookupAccountNameW(NULL, account_name, sid,
&sid_dword_size, domain_buffer.get(),
&domain_size, &sid_name_use);
if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// We could have gotten the insufficient buffer error because
// one or both of sid and szDomain was too small. Check for that
// here.
if (sid_dword_size > sid_size)
return false;
if (domain_size > kStartDomainLength)
domain_buffer.reset(new wchar_t[domain_size]);
success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size,
domain_buffer.get(), &domain_size,
&sid_name_use);
}
return success != FALSE;
}
std::vector<uint8_t> ConvertSidToBytes(SID* sid) {
std::wstring sid_string;
#if _WIN32_WINNT >= 0x500
wchar_t* sid_buffer = NULL;
if (ConvertSidToStringSidW(sid, &sid_buffer)) {
sid_string = sid_buffer;
LocalFree(sid_buffer);
}
#else
SID_IDENTIFIER_AUTHORITY* sia = ::GetSidIdentifierAuthority(sid);
if(sia->Value[0] || sia->Value[1]) {
base::SStringPrintf(
&sid_string, L"S-%d-0x%02hx%02hx%02hx%02hx%02hx%02hx",
SID_REVISION, (USHORT)sia->Value[0], (USHORT)sia->Value[1],
(USHORT)sia->Value[2], (USHORT)sia->Value[3], (USHORT)sia->Value[4],
(USHORT)sia->Value[5]);
} else {
ULONG authority = 0;
for (int i = 2; i < 6; ++i) {
authority <<= 8;
authority |= sia->Value[i];
}
base::SStringPrintf(&sid_string, L"S-%d-%lu", SID_REVISION, authority);
}
int sub_auth_count = *::GetSidSubAuthorityCount(sid);
for(int i = 0; i < sub_auth_count; ++i)
base::StringAppendF(&sid_string, L"-%lu", *::GetSidSubAuthority(sid, i));
#endif
// Get the contents of the string as a bunch of bytes.
return std::vector<uint8_t>(
reinterpret_cast<uint8_t*>(&sid_string[0]),
reinterpret_cast<uint8_t*>(&sid_string[sid_string.size()]));
}
} // namespace
bool GetRawMachineId(std::vector<uint8_t>* sid_bytes, int* volume_id) {
// Calculate the Windows SID.
wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0};
DWORD size = mozilla::ArrayLength(computer_name);
if (GetComputerNameW(computer_name, &size)) {
char sid_buffer[SECURITY_MAX_SID_SIZE];
SID* sid = reinterpret_cast<SID*>(sid_buffer);
if (GetComputerSid(computer_name, sid, SECURITY_MAX_SID_SIZE)) {
*sid_bytes = ConvertSidToBytes(sid);
}
}
// Get the system drive volume serial number.
*volume_id = 0;
if (!GetSystemVolumeSerialNumber(volume_id)) {
ASSERT_STRING("GetMachineId: Failed to retrieve volume serial number");
*volume_id = 0;
}
return true;
}
} // namespace rlz_lib

Просмотреть файл

@ -1731,9 +1731,10 @@ HTMLEditRules::WillInsertBreak(Selection& aSelection,
// If we cannot insert a <p>/<div> element at the selection, we should insert
// a <br> element instead.
if (insertBRElement) {
nsresult rv = StandardBreakImpl(*atStartOfSelection.GetContainer(),
atStartOfSelection.Offset(), aSelection);
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv = InsertBRElement(aSelection, atStartOfSelection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
*aHandled = true;
return NS_OK;
}
@ -1767,8 +1768,7 @@ HTMLEditRules::WillInsertBreak(Selection& aSelection,
}
if (NS_WARN_IF(blockParent == host)) {
// Didn't create a new block for some reason, fall back to <br>
rv = StandardBreakImpl(*atStartOfSelection.GetContainer(),
atStartOfSelection.Offset(), aSelection);
rv = InsertBRElement(aSelection, atStartOfSelection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1784,8 +1784,10 @@ HTMLEditRules::WillInsertBreak(Selection& aSelection,
bool isEmpty;
IsEmptyBlock(*blockParent, &isEmpty);
if (isEmpty) {
nsCOMPtr<Element> br = htmlEditor->CreateBR(blockParent,
blockParent->Length());
AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
EditorRawDOMPoint endOfBlockParent;
endOfBlockParent.SetToEndOf(blockParent);
RefPtr<Element> br = htmlEditor->CreateBR(endOfBlockParent);
NS_ENSURE_STATE(br);
}
@ -1816,6 +1818,7 @@ HTMLEditRules::WillInsertBreak(Selection& aSelection,
blockParent->IsHTMLElement(nsGkAtoms::p)) ||
(separator != ParagraphSeparator::br &&
blockParent->IsAnyOfHTMLElements(nsGkAtoms::p, nsGkAtoms::div))) {
AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
// Paragraphs: special rules to look for <br>s
EditActionResult result = ReturnInParagraph(aSelection, *blockParent);
if (NS_WARN_IF(result.Failed())) {
@ -1829,113 +1832,142 @@ HTMLEditRules::WillInsertBreak(Selection& aSelection,
// If not already handled then do the standard thing
if (!(*aHandled)) {
*aHandled = true;
return StandardBreakImpl(*atStartOfSelection.GetContainer(),
atStartOfSelection.Offset(), aSelection);
return InsertBRElement(aSelection, atStartOfSelection);
}
return NS_OK;
}
nsresult
HTMLEditRules::StandardBreakImpl(nsINode& aNode,
int32_t aOffset,
Selection& aSelection)
HTMLEditRules::InsertBRElement(Selection& aSelection,
const EditorDOMPoint& aPointToBreak)
{
NS_ENSURE_STATE(mHTMLEditor);
if (NS_WARN_IF(!aPointToBreak.IsSet())) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
nsCOMPtr<Element> brNode;
bool bAfterBlock = false;
bool bBeforeBlock = false;
nsCOMPtr<nsINode> node = &aNode;
bool brElementIsAfterBlock = false;
bool brElementIsBeforeBlock = false;
// First, insert a <br> element.
RefPtr<Element> brElement;
if (IsPlaintextEditor()) {
brNode = htmlEditor->CreateBR(node, aOffset);
NS_ENSURE_STATE(brNode);
brElement = htmlEditor->CreateBR(aPointToBreak.AsRaw());
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
} else {
WSRunObject wsObj(htmlEditor, node, aOffset);
EditorDOMPoint pointToBreak(aPointToBreak);
WSRunObject wsObj(htmlEditor, pointToBreak.GetContainer(),
pointToBreak.Offset());
int32_t visOffset = 0;
WSType wsType;
nsCOMPtr<nsINode> visNode;
wsObj.PriorVisibleNode(node, aOffset, address_of(visNode),
&visOffset, &wsType);
wsObj.PriorVisibleNode(pointToBreak.GetContainer(), pointToBreak.Offset(),
address_of(visNode), &visOffset, &wsType);
if (wsType & WSType::block) {
bAfterBlock = true;
brElementIsAfterBlock = true;
}
wsObj.NextVisibleNode(node, aOffset, address_of(visNode),
&visOffset, &wsType);
wsObj.NextVisibleNode(pointToBreak.GetContainer(), pointToBreak.Offset(),
address_of(visNode), &visOffset, &wsType);
if (wsType & WSType::block) {
bBeforeBlock = true;
brElementIsBeforeBlock = true;
}
// If the container of the break is a link, we need to split it and
// insert new <br> between the split links.
nsCOMPtr<nsIDOMNode> linkDOMNode;
if (htmlEditor->IsInLink(GetAsDOMNode(node), address_of(linkDOMNode))) {
// Split the link
if (htmlEditor->IsInLink(pointToBreak.GetContainerAsDOMNode(),
address_of(linkDOMNode))) {
nsCOMPtr<Element> linkNode = do_QueryInterface(linkDOMNode);
NS_ENSURE_STATE(linkNode || !linkDOMNode);
if (NS_WARN_IF(!linkNode)) {
return NS_ERROR_FAILURE;
}
SplitNodeResult splitLinkNodeResult =
htmlEditor->SplitNodeDeep(*linkNode, EditorRawDOMPoint(node, aOffset),
htmlEditor->SplitNodeDeep(*linkNode, pointToBreak.AsRaw(),
SplitAtEdges::eDoNotCreateEmptyContainer);
if (NS_WARN_IF(splitLinkNodeResult.Failed())) {
return splitLinkNodeResult.Rv();
}
EditorRawDOMPoint splitPoint(splitLinkNodeResult.SplitPoint());
node = splitPoint.GetContainer();
aOffset = splitPoint.Offset();
pointToBreak = splitLinkNodeResult.SplitPoint();
}
brNode =
wsObj.InsertBreak(aSelection, EditorRawDOMPoint(node, aOffset),
nsIEditor::eNone);
if (NS_WARN_IF(!brNode)) {
brElement =
wsObj.InsertBreak(aSelection, pointToBreak.AsRaw(), nsIEditor::eNone);
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
}
node = brNode->GetParentNode();
NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
if (bAfterBlock && bBeforeBlock) {
// We just placed a br between block boundaries. This is the one case
// If the <br> element has already been removed from the DOM tree by a
// mutation observer, don't continue handling this.
if (NS_WARN_IF(!brElement->GetParentNode())) {
return NS_ERROR_FAILURE;
}
if (brElementIsAfterBlock && brElementIsBeforeBlock) {
// We just placed a <br> between block boundaries. This is the one case
// where we want the selection to be before the br we just placed, as the
// br will be on a new line, rather than at end of prior line.
// XXX brElementIsAfterBlock and brElementIsBeforeBlock were set before
// modifying the DOM tree. So, now, the <br> element may not be
// between blocks.
aSelection.SetInterlinePosition(true);
EditorRawDOMPoint point(brNode);
nsresult rv = aSelection.Collapse(point.AsRaw());
NS_ENSURE_SUCCESS(rv, rv);
} else {
int32_t offset = node->IndexOf(brNode);
WSRunObject wsObj(htmlEditor, node, offset + 1);
nsCOMPtr<nsINode> secondBR;
int32_t visOffset = 0;
WSType wsType;
wsObj.NextVisibleNode(node, offset + 1, address_of(secondBR),
&visOffset, &wsType);
if (wsType == WSType::br) {
// The next thing after the break we inserted is another break. Move the
// second break to be the first break's sibling. This will prevent them
// from being in different inline nodes, which would break
// SetInterlinePosition(). It will also assure that if the user clicks
// away and then clicks back on their new blank line, they will still get
// the style from the line above.
nsCOMPtr<nsINode> brParent = secondBR->GetParentNode();
int32_t brOffset = brParent ? brParent->IndexOf(secondBR) : -1;
if (brParent != node || brOffset != offset + 1) {
nsresult rv =
htmlEditor->MoveNode(secondBR->AsContent(), node, offset + 1);
NS_ENSURE_SUCCESS(rv, rv);
EditorRawDOMPoint point(brElement);
ErrorResult error;
aSelection.Collapse(point, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
return NS_OK;
}
EditorDOMPoint afterBRElement(brElement);
DebugOnly<bool> advanced = afterBRElement.AdvanceOffset();
NS_WARNING_ASSERTION(advanced,
"Failed to advance offset after the new <br> element");
WSRunObject wsObj(htmlEditor, afterBRElement.GetContainer(),
afterBRElement.Offset());
nsCOMPtr<nsINode> maybeSecondBRNode;
int32_t visOffset = 0;
WSType wsType;
wsObj.NextVisibleNode(afterBRElement.GetContainer(), afterBRElement.Offset(),
address_of(maybeSecondBRNode), &visOffset, &wsType);
if (wsType == WSType::br) {
// The next thing after the break we inserted is another break. Move the
// second break to be the first break's sibling. This will prevent them
// from being in different inline nodes, which would break
// SetInterlinePosition(). It will also assure that if the user clicks
// away and then clicks back on their new blank line, they will still get
// the style from the line above.
EditorDOMPoint atSecondBRElement(maybeSecondBRNode);
if (brElement->GetNextSibling() != maybeSecondBRNode) {
nsresult rv =
htmlEditor->MoveNode(maybeSecondBRNode->AsContent(),
afterBRElement.GetContainer(),
afterBRElement.Offset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// SetInterlinePosition(true) means we want the caret to stick to the
// content on the "right". We want the caret to stick to whatever is past
// the break. This is because the break is on the same line we were on,
// but the next content will be on the following line.
}
// An exception to this is if the break has a next sibling that is a block
// node. Then we stick to the left to avoid an uber caret.
nsCOMPtr<nsIContent> siblingNode = brNode->GetNextSibling();
if (siblingNode && IsBlockNode(*siblingNode)) {
aSelection.SetInterlinePosition(false);
} else {
aSelection.SetInterlinePosition(true);
}
nsresult rv = aSelection.Collapse(node, offset + 1);
NS_ENSURE_SUCCESS(rv, rv);
// SetInterlinePosition(true) means we want the caret to stick to the
// content on the "right". We want the caret to stick to whatever is past
// the break. This is because the break is on the same line we were on,
// but the next content will be on the following line.
// An exception to this is if the break has a next sibling that is a block
// node. Then we stick to the left to avoid an uber caret.
nsIContent* nextSiblingOfBRElement = brElement->GetNextSibling();
aSelection.SetInterlinePosition(!(nextSiblingOfBRElement &&
IsBlockNode(*nextSiblingOfBRElement)));
ErrorResult error;
aSelection.Collapse(afterBRElement.AsRaw(), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
return NS_OK;
}
@ -1951,7 +1983,15 @@ nsresult
HTMLEditRules::SplitMailCites(Selection* aSelection,
bool* aHandled)
{
NS_ENSURE_TRUE(aSelection && aHandled, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aHandled)) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
nsCOMPtr<nsIContent> leftCite, rightCite;
nsCOMPtr<nsINode> selNode;
nsCOMPtr<Element> citeNode;
@ -1970,8 +2010,7 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
// mailquote (in either inline or block case).
// The latter can confuse a user if they click there and start typing,
// because being in the mailquote may affect wrapping behavior, or font color, etc.
NS_ENSURE_STATE(mHTMLEditor);
WSRunObject wsObj(mHTMLEditor, selNode, selOffset);
WSRunObject wsObj(htmlEditor, selNode, selOffset);
nsCOMPtr<nsINode> visNode;
int32_t visOffset=0;
WSType wsType;
@ -1981,18 +2020,16 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
// ok, we are just before a break. is it inside the mailquote?
if (visNode != citeNode && citeNode->Contains(visNode)) {
// it is. so lets reset our selection to be just after it.
NS_ENSURE_STATE(mHTMLEditor);
selNode = mHTMLEditor->GetNodeLocation(visNode, &selOffset);
selNode = EditorBase::GetNodeLocation(visNode, &selOffset);
++selOffset;
}
}
NS_ENSURE_STATE(mHTMLEditor);
NS_ENSURE_STATE(selNode->IsContent());
SplitNodeResult splitCiteNodeResult =
mHTMLEditor->SplitNodeDeep(*citeNode,
EditorRawDOMPoint(selNode, selOffset),
SplitAtEdges::eDoNotCreateEmptyContainer);
htmlEditor->SplitNodeDeep(*citeNode,
EditorRawDOMPoint(selNode, selOffset),
SplitAtEdges::eDoNotCreateEmptyContainer);
if (NS_WARN_IF(splitCiteNodeResult.Failed())) {
return splitCiteNodeResult.Rv();
}
@ -2003,19 +2040,20 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
// important, since when serializing the cite to plain text, the span which
// caused the visual break is discarded. So the added <br> will guarantee
// that the serializer will insert a break where the user saw one.
nsIContent* preveiousNodeOfSplitPoint =
nsIContent* previousNodeOfSplitPoint =
splitCiteNodeResult.GetPreviousNode();
if (preveiousNodeOfSplitPoint &&
preveiousNodeOfSplitPoint->IsHTMLElement(nsGkAtoms::span) &&
preveiousNodeOfSplitPoint->GetPrimaryFrame()->
IsFrameOfType(nsIFrame::eBlockFrame)) {
if (previousNodeOfSplitPoint &&
previousNodeOfSplitPoint->IsHTMLElement(nsGkAtoms::span) &&
previousNodeOfSplitPoint->GetPrimaryFrame()->
IsFrameOfType(nsIFrame::eBlockFrame)) {
nsCOMPtr<nsINode> lastChild =
preveiousNodeOfSplitPoint->GetLastChild();
previousNodeOfSplitPoint->GetLastChild();
if (lastChild && !lastChild->IsHTMLElement(nsGkAtoms::br)) {
// We ignore the result here.
nsCOMPtr<Element> invisBR =
mHTMLEditor->CreateBR(preveiousNodeOfSplitPoint,
preveiousNodeOfSplitPoint->Length());
EditorRawDOMPoint endOfPreviousNodeOfSplitPoint;
endOfPreviousNodeOfSplitPoint.SetToEndOf(previousNodeOfSplitPoint);
RefPtr<Element> invisBR =
htmlEditor->CreateBR(endOfPreviousNodeOfSplitPoint);
}
}
@ -2023,11 +2061,10 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
// left cite hasn't been created because the split point was start of the
// cite node, <br> should be inserted before the current cite.
EditorRawDOMPoint pointToInsertBrNode(splitCiteNodeResult.SplitPoint());
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<Element> brNode =
mHTMLEditor->CreateBR(pointToInsertBrNode.GetContainer(),
pointToInsertBrNode.Offset());
NS_ENSURE_STATE(brNode);
RefPtr<Element> brNode = htmlEditor->CreateBR(pointToInsertBrNode);
if (NS_WARN_IF(!brNode)) {
return NS_ERROR_FAILURE;
}
// Now, offset of pointToInsertBrNode is invalid. Let's clear it.
pointToInsertBrNode.Clear();
@ -2048,8 +2085,7 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
// just after it. If we don't have another br or block boundary adjacent,
// then we will need a 2nd br added to achieve blank line that user expects.
if (IsInlineNode(*citeNode)) {
NS_ENSURE_STATE(mHTMLEditor);
WSRunObject wsObj(mHTMLEditor, selNode, selOffset);
WSRunObject wsObj(htmlEditor, selNode, selOffset);
nsCOMPtr<nsINode> visNode;
int32_t visOffset=0;
WSType wsType;
@ -2057,16 +2093,14 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
&visOffset, &wsType);
if (wsType == WSType::normalWS || wsType == WSType::text ||
wsType == WSType::special) {
NS_ENSURE_STATE(mHTMLEditor);
WSRunObject wsObjAfterBR(mHTMLEditor, selNode, selOffset + 1);
WSRunObject wsObjAfterBR(htmlEditor, selNode, selOffset + 1);
wsObjAfterBR.NextVisibleNode(selNode, selOffset + 1,
address_of(visNode), &visOffset, &wsType);
if (wsType == WSType::normalWS || wsType == WSType::text ||
wsType == WSType::special ||
// In case we're at the very end.
wsType == WSType::thisBlock) {
NS_ENSURE_STATE(mHTMLEditor);
brNode = mHTMLEditor->CreateBR(selNode, selOffset);
brNode = htmlEditor->CreateBR(EditorRawDOMPoint(selNode, selOffset));
NS_ENSURE_STATE(brNode);
}
}
@ -2075,14 +2109,12 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
// delete any empty cites
bool bEmptyCite = false;
if (leftCite) {
NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->IsEmptyNode(leftCite, &bEmptyCite, true, false);
rv = htmlEditor->IsEmptyNode(leftCite, &bEmptyCite, true, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (bEmptyCite) {
NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->DeleteNode(leftCite);
rv = htmlEditor->DeleteNode(leftCite);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -2090,14 +2122,12 @@ HTMLEditRules::SplitMailCites(Selection* aSelection,
}
if (citeNode) {
NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->IsEmptyNode(citeNode, &bEmptyCite, true, false);
rv = htmlEditor->IsEmptyNode(citeNode, &bEmptyCite, true, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (bEmptyCite) {
NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->DeleteNode(citeNode);
rv = htmlEditor->DeleteNode(citeNode);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -2831,36 +2861,41 @@ HTMLEditRules::DeleteNodeIfCollapsedText(nsINode& aNode)
nsresult
HTMLEditRules::InsertBRIfNeeded(Selection* aSelection)
{
NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
// get selection
nsCOMPtr<nsINode> node;
int32_t offset;
nsresult rv =
EditorBase::GetStartNodeAndOffset(aSelection,
getter_AddRefs(node), &offset);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
EditorRawDOMPoint atStartOfSelection(EditorBase::GetStartPoint(aSelection));
if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
return NS_ERROR_FAILURE;
}
// inline elements don't need any br
if (!IsBlockNode(*node)) {
if (!IsBlockNode(*atStartOfSelection.GetContainer())) {
return NS_OK;
}
// examine selection
NS_ENSURE_STATE(mHTMLEditor);
WSRunObject wsObj(mHTMLEditor, node, offset);
WSRunObject wsObj(htmlEditor, atStartOfSelection.GetContainer(),
atStartOfSelection.Offset());
if (((wsObj.mStartReason & WSType::block) ||
(wsObj.mStartReason & WSType::br)) &&
(wsObj.mEndReason & WSType::block)) {
// if we are tucked between block boundaries then insert a br
// first check that we are allowed to
NS_ENSURE_STATE(mHTMLEditor);
if (mHTMLEditor->CanContainTag(*node, *nsGkAtoms::br)) {
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<Element> br =
mHTMLEditor->CreateBR(node, offset, nsIEditor::ePrevious);
return br ? NS_OK : NS_ERROR_FAILURE;
if (htmlEditor->CanContainTag(*atStartOfSelection.GetContainer(),
*nsGkAtoms::br)) {
RefPtr<Element> br =
htmlEditor->CreateBR(atStartOfSelection, nsIEditor::ePrevious);
if (NS_WARN_IF(!br)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
}
return NS_OK;
@ -3383,33 +3418,42 @@ HTMLEditRules::DidDeleteSelection(Selection* aSelection,
return NS_ERROR_NULL_POINTER;
}
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
// find where we are
nsCOMPtr<nsINode> startNode;
int32_t startOffset;
nsresult rv = EditorBase::GetStartNodeAndOffset(aSelection,
getter_AddRefs(startNode),
&startOffset);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
EditorDOMPoint atStartOfSelection(EditorBase::GetStartPoint(aSelection));
if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
return NS_ERROR_FAILURE;
}
// find any enclosing mailcite
nsCOMPtr<Element> citeNode = GetTopEnclosingMailCite(*startNode);
nsCOMPtr<Element> citeNode =
GetTopEnclosingMailCite(*atStartOfSelection.GetContainer());
if (citeNode) {
bool isEmpty = true, seenBR = false;
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->IsEmptyNodeImpl(citeNode, &isEmpty, true, true, false,
&seenBR);
htmlEditor->IsEmptyNodeImpl(citeNode, &isEmpty, true, true, false,
&seenBR);
if (isEmpty) {
int32_t offset;
nsCOMPtr<nsINode> parent = EditorBase::GetNodeLocation(citeNode, &offset);
NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->DeleteNode(citeNode);
NS_ENSURE_SUCCESS(rv, rv);
if (parent && seenBR) {
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<Element> brNode = mHTMLEditor->CreateBR(parent, offset);
NS_ENSURE_STATE(brNode);
aSelection->Collapse(parent, offset);
EditorDOMPoint atCiteNode(citeNode);
{
AutoEditorDOMPointChildInvalidator lockOffset(atCiteNode);
nsresult rv = htmlEditor->DeleteNode(citeNode);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (atCiteNode.IsSet() && seenBR) {
RefPtr<Element> brNode = htmlEditor->CreateBR(atCiteNode.AsRaw());
if (NS_WARN_IF(!brNode)) {
return NS_ERROR_FAILURE;
}
IgnoredErrorResult error;
aSelection->Collapse(EditorRawDOMPoint(brNode), error);
NS_WARNING_ASSERTION(!error.Failed(),
"Failed to collapse selection at the new <br> element");
}
}
}
@ -3881,8 +3925,7 @@ HTMLEditRules::MakeBasicBlock(Selection& aSelection, nsAtom& blockType)
}
EditorRawDOMPoint pointToInsertBrNode(splitNodeResult.SplitPoint());
// Put a br at the split point
brNode = htmlEditor->CreateBR(pointToInsertBrNode.GetContainer(),
pointToInsertBrNode.Offset());
brNode = htmlEditor->CreateBR(pointToInsertBrNode);
NS_ENSURE_STATE(brNode);
// Put selection at the split point
EditorRawDOMPoint atBrNode(brNode);
@ -5076,8 +5119,10 @@ HTMLEditRules::WillAlign(Selection& aSelection,
NS_ENSURE_SUCCESS(rv, rv);
*aHandled = true;
// Put in a moz-br so that it won't get deleted
rv = CreateMozBR(*div, 0);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<Element> brElement = CreateMozBR(EditorRawDOMPoint(div, 0));
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
EditorRawDOMPoint atStartOfDiv(div, 0);
ErrorResult error;
aSelection.Collapse(atStartOfDiv, error);
@ -5292,7 +5337,10 @@ HTMLEditRules::CheckForEmptyBlock(nsINode* aStartNode,
if (aBodyNode && IsInlineNode(*aBodyNode)) {
return NS_OK;
}
NS_ENSURE_STATE(mHTMLEditor);
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
// If we are inside an empty block, delete it. Note: do NOT delete table
@ -5321,22 +5369,24 @@ HTMLEditRules::CheckForEmptyBlock(nsINode* aStartNode,
if (HTMLEditUtils::IsListItem(emptyBlock)) {
// Are we the first list item in the list?
NS_ENSURE_STATE(htmlEditor);
if (htmlEditor->IsFirstEditableChild(emptyBlock)) {
nsCOMPtr<nsINode> listParent = blockParent->GetParentNode();
NS_ENSURE_TRUE(listParent, NS_ERROR_FAILURE);
EditorDOMPoint atBlockParent(blockParent);
if (NS_WARN_IF(!atBlockParent.IsSet())) {
return NS_ERROR_FAILURE;
}
// If we are a sublist, skip the br creation
if (!HTMLEditUtils::IsList(listParent)) {
int32_t listOffset = listParent->IndexOf(blockParent);
if (!HTMLEditUtils::IsList(atBlockParent.GetContainer())) {
// Create a br before list
NS_ENSURE_STATE(htmlEditor);
nsCOMPtr<Element> br =
htmlEditor->CreateBR(listParent, listOffset);
NS_ENSURE_STATE(br);
RefPtr<Element> br = htmlEditor->CreateBR(atBlockParent.AsRaw());
if (NS_WARN_IF(!br)) {
return NS_ERROR_FAILURE;
}
// Adjust selection to be right before it
nsresult rv = aSelection->Collapse(listParent, listOffset);
NS_ENSURE_SUCCESS(rv, rv);
ErrorResult error;
aSelection->Collapse(EditorRawDOMPoint(br), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
// Else just let selection percolate up. We'll adjust it in
// AfterEdit()
@ -5387,7 +5437,6 @@ HTMLEditRules::CheckForEmptyBlock(nsINode* aStartNode,
MOZ_CRASH("CheckForEmptyBlock doesn't support this action yet");
}
}
NS_ENSURE_STATE(htmlEditor);
*aHandled = true;
nsresult rv = htmlEditor->DeleteNode(emptyBlock);
NS_ENSURE_SUCCESS(rv, rv);
@ -6768,8 +6817,10 @@ HTMLEditRules::ReturnInHeader(Selection& aSelection,
rv = htmlEditor->IsEmptyNode(prevItem, &isEmptyNode);
NS_ENSURE_SUCCESS(rv, rv);
if (isEmptyNode) {
rv = CreateMozBR(*prevItem, 0);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<Element> brElement = CreateMozBR(EditorRawDOMPoint(prevItem, 0));
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
}
}
@ -6801,12 +6852,18 @@ HTMLEditRules::ReturnInHeader(Selection& aSelection,
NS_ENSURE_STATE(pNode);
// Append a <br> to it
nsCOMPtr<Element> brNode = htmlEditor->CreateBR(pNode, 0);
NS_ENSURE_STATE(brNode);
RefPtr<Element> brNode =
htmlEditor->CreateBR(EditorRawDOMPoint(pNode, 0));
if (NS_WARN_IF(!brNode)) {
return NS_ERROR_FAILURE;
}
// Set selection to before the break
rv = aSelection.Collapse(pNode, 0);
NS_ENSURE_SUCCESS(rv, rv);
ErrorResult error;
aSelection.Collapse(EditorRawDOMPoint(pNode, 0), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
} else {
EditorRawDOMPoint afterSibling(sibling);
if (NS_WARN_IF(!afterSibling.AdvanceOffset())) {
@ -6933,8 +6990,7 @@ HTMLEditRules::ReturnInParagraph(Selection& aSelection,
return EditActionResult(NS_OK);
}
brNode = htmlEditor->CreateBR(pointToInsertBR.GetContainer(),
pointToInsertBR.Offset());
brNode = htmlEditor->CreateBR(pointToInsertBR);
if (splitAfterNewBR) {
// We split the parent after the br we've just inserted.
pointToSplitParentDivOrP.Set(brNode);
@ -7097,12 +7153,18 @@ HTMLEditRules::ReturnInListItem(Selection& aSelection,
NS_ENSURE_STATE(pNode);
// Append a <br> to it
nsCOMPtr<Element> brNode = htmlEditor->CreateBR(pNode, 0);
NS_ENSURE_STATE(brNode);
RefPtr<Element> brNode =
htmlEditor->CreateBR(EditorRawDOMPoint(pNode, 0));
if (NS_WARN_IF(!brNode)) {
return NS_ERROR_FAILURE;
}
// Set selection to before the break
rv = aSelection.Collapse(pNode, 0);
NS_ENSURE_SUCCESS(rv, rv);
ErrorResult error;
aSelection.Collapse(EditorRawDOMPoint(pNode, 0), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
return NS_OK;
}
@ -7133,8 +7195,10 @@ HTMLEditRules::ReturnInListItem(Selection& aSelection,
rv = htmlEditor->IsEmptyNode(prevItem, &isEmptyNode);
NS_ENSURE_SUCCESS(rv, rv);
if (isEmptyNode) {
rv = CreateMozBR(*prevItem, 0);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<Element> brElement = CreateMozBR(EditorRawDOMPoint(prevItem, 0));
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
} else {
rv = htmlEditor->IsEmptyNode(&aListItem, &isEmptyNode, true);
NS_ENSURE_SUCCESS(rv, rv);
@ -7857,8 +7921,10 @@ HTMLEditRules::AdjustSpecialBreaks()
// still pass the "IsEmptyNode" test, and we want the br's to be after
// them. Also, we want the br to be after the selection if the selection
// is in this node.
nsresult rv = CreateMozBR(*node, (int32_t)node->Length());
if (NS_WARN_IF(NS_FAILED(rv))) {
EditorRawDOMPoint endOfNode;
endOfNode.SetToEndOf(node);
RefPtr<Element> brElement = CreateMozBR(endOfNode);
if (NS_WARN_IF(!brElement)) {
return;
}
}
@ -8011,7 +8077,14 @@ nsresult
HTMLEditRules::AdjustSelection(Selection* aSelection,
nsIEditor::EDirection aAction)
{
NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
// if the selection isn't collapsed, do nothing.
// moose: one thing to do instead is check for the case of
@ -8027,8 +8100,7 @@ HTMLEditRules::AdjustSelection(Selection* aSelection,
}
// are we in an editable node?
NS_ENSURE_STATE(mHTMLEditor);
while (!mHTMLEditor->IsEditable(point.GetContainer())) {
while (!htmlEditor->IsEditable(point.GetContainer())) {
// scan up the tree until we find an editable place to be
point.Set(point.GetContainer());
if (NS_WARN_IF(!point.IsSet())) {
@ -8038,23 +8110,21 @@ HTMLEditRules::AdjustSelection(Selection* aSelection,
// make sure we aren't in an empty block - user will see no cursor. If this
// is happening, put a <br> in the block if allowed.
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<Element> theblock = mHTMLEditor->GetBlock(*point.GetContainer());
RefPtr<Element> theblock = htmlEditor->GetBlock(*point.GetContainer());
if (theblock && mHTMLEditor->IsEditable(theblock)) {
if (theblock && htmlEditor->IsEditable(theblock)) {
bool bIsEmptyNode;
NS_ENSURE_STATE(mHTMLEditor);
nsresult rv =
mHTMLEditor->IsEmptyNode(theblock, &bIsEmptyNode, false, false);
htmlEditor->IsEmptyNode(theblock, &bIsEmptyNode, false, false);
NS_ENSURE_SUCCESS(rv, rv);
// check if br can go into the destination node
NS_ENSURE_STATE(mHTMLEditor);
if (bIsEmptyNode &&
mHTMLEditor->CanContainTag(*point.GetContainer(), *nsGkAtoms::br)) {
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<Element> rootNode = mHTMLEditor->GetRoot();
NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
if (point.GetContainer() == rootNode) {
htmlEditor->CanContainTag(*point.GetContainer(), *nsGkAtoms::br)) {
Element* rootElement = htmlEditor->GetRoot();
if (NS_WARN_IF(!rootElement)) {
return NS_ERROR_FAILURE;
}
if (point.GetContainer() == rootElement) {
// Our root node is completely empty. Don't add a <br> here.
// AfterEditInner() will add one for us when it calls
// CreateBogusNodeIfNeeded()!
@ -8062,7 +8132,11 @@ HTMLEditRules::AdjustSelection(Selection* aSelection,
}
// we know we can skip the rest of this routine given the cirumstance
return CreateMozBR(*point.GetContainer(), point.Offset());
RefPtr<Element> brElement = CreateMozBR(point.AsRaw());
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
}
@ -8076,27 +8150,23 @@ HTMLEditRules::AdjustSelection(Selection* aSelection,
// 2) prior node is a br AND
// 3) that br is not visible
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<nsIContent> nearNode =
mHTMLEditor->GetPreviousEditableHTMLNode(point.AsRaw());
htmlEditor->GetPreviousEditableHTMLNode(point.AsRaw());
if (nearNode) {
// is nearNode also a descendant of same block?
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<Element> block = mHTMLEditor->GetBlock(*point.GetContainer());
nsCOMPtr<Element> nearBlock = mHTMLEditor->GetBlockNodeParent(nearNode);
RefPtr<Element> block = htmlEditor->GetBlock(*point.GetContainer());
RefPtr<Element> nearBlock = htmlEditor->GetBlockNodeParent(nearNode);
if (block && block == nearBlock) {
if (nearNode && TextEditUtils::IsBreak(nearNode)) {
NS_ENSURE_STATE(mHTMLEditor);
if (!mHTMLEditor->IsVisibleBRElement(nearNode)) {
if (!htmlEditor->IsVisibleBRElement(nearNode)) {
// need to insert special moz BR. Why? Because if we don't
// the user will see no new line for the break. Also, things
// like table cells won't grow in height.
RefPtr<Element> br;
nsresult rv =
CreateMozBR(*point.GetContainer(), point.Offset(),
getter_AddRefs(br));
NS_ENSURE_SUCCESS(rv, rv);
point.Set(br);
RefPtr<Element> brElement = CreateMozBR(point.AsRaw());
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
point.Set(brElement);
// selection stays *before* moz-br, sticking to it
aSelection->SetInterlinePosition(true);
ErrorResult error;
@ -8105,9 +8175,8 @@ HTMLEditRules::AdjustSelection(Selection* aSelection,
return error.StealNSResult();
}
} else {
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<nsIContent> nextNode =
mHTMLEditor->GetNextEditableHTMLNodeInBlock(*nearNode);
htmlEditor->GetNextEditableHTMLNodeInBlock(*nearNode);
if (nextNode && TextEditUtils::IsMozBR(nextNode)) {
// selection between br and mozbr. make it stick to mozbr
// so that it will be on blank line.
@ -8119,8 +8188,7 @@ HTMLEditRules::AdjustSelection(Selection* aSelection,
}
// we aren't in a textnode: are we adjacent to text or a break or an image?
NS_ENSURE_STATE(mHTMLEditor);
nearNode = mHTMLEditor->GetPreviousEditableHTMLNodeInBlock(point.AsRaw());
nearNode = htmlEditor->GetPreviousEditableHTMLNodeInBlock(point.AsRaw());
if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
EditorBase::IsTextNode(nearNode) ||
HTMLEditUtils::IsImage(nearNode) ||
@ -8128,8 +8196,7 @@ HTMLEditRules::AdjustSelection(Selection* aSelection,
// this is a good place for the caret to be
return NS_OK;
}
NS_ENSURE_STATE(mHTMLEditor);
nearNode = mHTMLEditor->GetNextEditableHTMLNodeInBlock(point.AsRaw());
nearNode = htmlEditor->GetNextEditableHTMLNodeInBlock(point.AsRaw());
if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
EditorBase::IsTextNode(nearNode) ||
nearNode->IsAnyOfHTMLElements(nsGkAtoms::img,
@ -8345,7 +8412,7 @@ HTMLEditRules::RemoveEmptyNodes()
}
// now delete the empty nodes
for (auto& delNode : arrayOfEmptyNodes) {
for (OwningNonNull<nsINode>& delNode : arrayOfEmptyNodes) {
if (htmlEditor->IsModifiableNode(delNode)) {
rv = htmlEditor->DeleteNode(delNode);
NS_ENSURE_SUCCESS(rv, rv);
@ -8354,17 +8421,17 @@ HTMLEditRules::RemoveEmptyNodes()
// Now delete the empty mailcites. This is a separate step because we want
// to pull out any br's and preserve them.
for (auto& delNode : arrayOfEmptyCites) {
for (OwningNonNull<nsINode>& delNode : arrayOfEmptyCites) {
bool bIsEmptyNode;
rv = htmlEditor->IsEmptyNode(delNode, &bIsEmptyNode, false, true);
NS_ENSURE_SUCCESS(rv, rv);
if (!bIsEmptyNode) {
// We are deleting a cite that has just a br. We want to delete cite,
// but preserve br.
nsCOMPtr<nsINode> parent = delNode->GetParentNode();
int32_t offset = parent ? parent->IndexOf(delNode) : -1;
nsCOMPtr<Element> br = htmlEditor->CreateBR(parent, offset);
NS_ENSURE_STATE(br);
RefPtr<Element> br = htmlEditor->CreateBR(EditorRawDOMPoint(delNode));
if (NS_WARN_IF(!br)) {
return NS_ERROR_FAILURE;
}
}
rv = htmlEditor->DeleteNode(delNode);
NS_ENSURE_SUCCESS(rv, rv);
@ -8735,8 +8802,12 @@ HTMLEditRules::InsertBRIfNeededInternal(nsINode& aNode,
return NS_OK;
}
return aInsertMozBR ? CreateMozBR(aNode, 0) :
CreateBR(aNode, 0);
RefPtr<Element> brElement =
CreateBRInternal(EditorRawDOMPoint(&aNode, 0), aInsertMozBR);
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
@ -9036,27 +9107,24 @@ nsresult
HTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsINode& aNode,
bool aStarts)
{
nsCOMPtr<nsINode> child;
if (aStarts) {
NS_ENSURE_STATE(mHTMLEditor);
child = mHTMLEditor->GetFirstEditableChild(aNode);
} else {
NS_ENSURE_STATE(mHTMLEditor);
child = mHTMLEditor->GetLastEditableChild(aNode);
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_ENSURE_TRUE(child, NS_OK);
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
nsINode* child = aStarts ? htmlEditor->GetFirstEditableChild(aNode) :
htmlEditor->GetLastEditableChild(aNode);
if (NS_WARN_IF(!child)) {
return NS_OK;
}
bool foundCR = false;
if (IsBlockNode(*child) || child->IsHTMLElement(nsGkAtoms::br)) {
foundCR = true;
} else {
nsCOMPtr<nsINode> sibling;
if (aStarts) {
NS_ENSURE_STATE(mHTMLEditor);
sibling = mHTMLEditor->GetPriorHTMLSibling(&aNode);
} else {
NS_ENSURE_STATE(mHTMLEditor);
sibling = mHTMLEditor->GetNextHTMLSibling(&aNode);
}
nsINode* sibling =
aStarts ? htmlEditor->GetPriorHTMLSibling(&aNode) :
htmlEditor->GetNextHTMLSibling(&aNode);
if (sibling) {
if (IsBlockNode(*sibling) || sibling->IsHTMLElement(nsGkAtoms::br)) {
foundCR = true;
@ -9066,12 +9134,13 @@ HTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsINode& aNode,
}
}
if (!foundCR) {
int32_t offset = 0;
EditorRawDOMPoint pointToInsert;
if (!aStarts) {
offset = aNode.GetChildCount();
pointToInsert.SetToEndOf(&aNode);
} else {
pointToInsert.Set(&aNode, 0);
}
NS_ENSURE_STATE(mHTMLEditor);
RefPtr<Element> brNode = mHTMLEditor->CreateBR(&aNode, offset);
RefPtr<Element> brNode = htmlEditor->CreateBR(pointToInsert);
if (NS_WARN_IF(!brNode)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -158,8 +158,17 @@ protected:
nsresult WillLoadHTML(Selection* aSelection, bool* aCancel);
nsresult WillInsertBreak(Selection& aSelection, bool* aCancel,
bool* aHandled);
nsresult StandardBreakImpl(nsINode& aNode, int32_t aOffset,
Selection& aSelection);
/**
* InsertBRElement() inserts a <br> element into aInsertToBreak.
*
* @param aSelection The selection.
* @param aInsertToBreak The point where new <br> element will be
* inserted before.
*/
nsresult InsertBRElement(Selection& aSelection,
const EditorDOMPoint& aInsertToBreak);
nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
nsresult SplitMailCites(Selection* aSelection, bool* aHandled);
nsresult WillDeleteSelection(Selection* aSelection,

Просмотреть файл

@ -3733,8 +3733,10 @@ HTMLEditor::RemoveBlockContainer(nsIContent& aNode)
if (sibling && !IsBlockNode(sibling) &&
!sibling->IsHTMLElement(nsGkAtoms::br) && !IsBlockNode(child)) {
// Insert br node
nsCOMPtr<Element> br = CreateBR(&aNode, 0);
NS_ENSURE_STATE(br);
RefPtr<Element> brElement = CreateBR(EditorRawDOMPoint(&aNode, 0));
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
}
// We need a br at end unless:
@ -3749,8 +3751,12 @@ HTMLEditor::RemoveBlockContainer(nsIContent& aNode)
MOZ_ASSERT(child, "aNode has first editable child but not last?");
if (!IsBlockNode(child) && !child->IsHTMLElement(nsGkAtoms::br)) {
// Insert br node
nsCOMPtr<Element> br = CreateBR(&aNode, aNode.Length());
NS_ENSURE_STATE(br);
EditorRawDOMPoint endOfNode;
endOfNode.SetToEndOf(&aNode);
RefPtr<Element> brElement = CreateBR(endOfNode);
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
}
}
} else {
@ -3767,8 +3773,10 @@ HTMLEditor::RemoveBlockContainer(nsIContent& aNode)
if (sibling && !IsBlockNode(sibling) &&
!sibling->IsHTMLElement(nsGkAtoms::br)) {
// Insert br node
nsCOMPtr<Element> br = CreateBR(&aNode, 0);
NS_ENSURE_STATE(br);
RefPtr<Element> brElement = CreateBR(EditorRawDOMPoint(&aNode, 0));
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
}
}
}
@ -4469,7 +4477,7 @@ HTMLEditor::CopyLastEditableChildStyles(nsINode* aPreviousBlock,
childElement = childElement->GetParentElement();
}
if (deepestStyle) {
RefPtr<Element> retVal = CreateBR(deepestStyle, 0);
RefPtr<Element> retVal = CreateBR(EditorRawDOMPoint(deepestStyle, 0));
retVal.forget(aOutBrNode);
NS_ENSURE_STATE(*aOutBrNode);
}

Просмотреть файл

@ -1376,7 +1376,13 @@ TextEditRules::CreateTrailingBRIfNeeded()
if (!lastChild->IsHTMLElement(nsGkAtoms::br)) {
AutoTransactionsConserveSelection dontChangeMySelection(mTextEditor);
return CreateMozBR(*body, body->Length());
EditorRawDOMPoint endOfBody;
endOfBody.SetToEndOf(body);
RefPtr<Element> brElement = CreateMozBR(endOfBody);
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// Check to see if the trailing BR is a former bogus node - this will have
@ -1638,33 +1644,37 @@ TextEditRules::FillBufWithPWChars(nsAString* aOutString,
}
}
nsresult
TextEditRules::CreateBRInternal(nsINode& inParent,
int32_t inOffset,
bool aMozBR,
Element** aOutBRElement)
already_AddRefed<Element>
TextEditRules::CreateBRInternal(const EditorRawDOMPoint& aPointToInsert,
bool aCreateMozBR)
{
if (NS_WARN_IF(!aPointToInsert.IsSet())) {
return nullptr;
}
if (NS_WARN_IF(!mTextEditor)) {
return NS_ERROR_NOT_AVAILABLE;
return nullptr;
}
RefPtr<TextEditor> textEditor = mTextEditor;
RefPtr<Element> brElem = textEditor->CreateBR(&inParent, inOffset);
if (NS_WARN_IF(!brElem)) {
return NS_ERROR_FAILURE;
RefPtr<Element> brElement = textEditor->CreateBR(aPointToInsert);
if (NS_WARN_IF(!brElement)) {
return nullptr;
}
// give it special moz attr
if (aMozBR) {
nsresult rv = textEditor->SetAttribute(brElem, nsGkAtoms::type,
if (aCreateMozBR) {
// XXX Why do we need to set this attribute with transaction?
nsresult rv = textEditor->SetAttribute(brElement, nsGkAtoms::type,
NS_LITERAL_STRING("_moz"));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
// XXX Don't we need to remove the new <br> element from the DOM tree
// in this case?
return nullptr;
}
}
if (aOutBRElement) {
brElem.forget(aOutBRElement);
}
return NS_OK;
return brElement.forget();
}
NS_IMETHODIMP

Просмотреть файл

@ -218,33 +218,43 @@ protected:
void RemoveIMETextFromPWBuf(uint32_t& aStart, nsAString* aIMEString);
/**
* Create a normal <br> element and insert it to aOffset at aParent.
* Create a normal <br> element and insert it to aPointToInsert.
*
* @param aParent The parent node which will have new <br> element.
* @param aOffset The offset in aParent where the new <br> element will
* be inserted.
* @param aOutBRNode Returns created <br> element.
* @param aPointToInsert The point where the new <br> element will be
* inserted.
* @return Returns created <br> element.
*/
nsresult CreateBR(nsINode& aParent, int32_t aOffset,
Element** aOutBRNode = nullptr)
already_AddRefed<Element> CreateBR(const EditorRawDOMPoint& aPointToInsert)
{
return CreateBRInternal(aParent, aOffset, false, aOutBRNode);
return CreateBRInternal(aPointToInsert, false);
}
/**
* Create a moz-<br> element and insert it to aOffset at aParent.
* Create a moz-<br> element and insert it to aPointToInsert.
*
* @param aParent The parent node which will have new <br> element.
* @param aOffset The offset in aParent where the new <br> element will
* be inserted.
* @param aOutBRNode Returns created <br> element.
* @param aPointToInsert The point where the new moz-<br> element will be
* inserted.
* @return Returns created moz-<br> element.
*/
nsresult CreateMozBR(nsINode& aParent, int32_t aOffset,
Element** aOutBRNode = nullptr)
already_AddRefed<Element> CreateMozBR(const EditorRawDOMPoint& aPointToInsert)
{
return CreateBRInternal(aParent, aOffset, true, aOutBRNode);
return CreateBRInternal(aPointToInsert, true);
}
/**
* Create a normal <br> element or a moz-<br> element and insert it to
* aPointToInsert.
*
* @param aParentToInsert The point where the new <br> element will be
* inserted.
* @param aCreateMozBR true if the caller wants to create a moz-<br>
* element. Otherwise, false.
* @return Returns created <br> element.
*/
already_AddRefed<Element>
CreateBRInternal(const EditorRawDOMPoint& aPointToInsert,
bool aCreateMozBR);
void UndefineCaretBidiLevel(Selection* aSelection);
nsresult CheckBidiLevelForDeletion(Selection* aSelection,
@ -269,23 +279,6 @@ private:
// Note that we do not refcount the editor.
TextEditor* mTextEditor;
/**
* Create a normal <br> element or a moz-<br> element and insert it to
* aOffset at aParent.
*
* @param aParent The parent node which will have new <br> element.
* @param aOffset The offset in aParent where the new <br> element will
* be inserted.
* @param aMozBR true if the caller wants to create a moz-<br> element.
* Otherwise, false.
* @param aOutBRNode Returns created <br> element.
*/
nsresult CreateBRInternal(nsINode& aParent,
int32_t aOffset,
bool aMozBR,
Element** aOutBRNode = nullptr);
protected:
// A buffer we use to store the real value of password editors.
nsString mPasswordText;

Просмотреть файл

@ -417,8 +417,7 @@ TextEditor::TypedText(const nsAString& aString, ETypingAction aAction)
}
already_AddRefed<Element>
TextEditor::CreateBR(nsINode* aNode,
int32_t aOffset,
TextEditor::CreateBR(const EditorRawDOMPoint& aPointToInsert,
EDirection aSelect /* = eNone */)
{
RefPtr<Selection> selection = GetSelection();
@ -426,7 +425,7 @@ TextEditor::CreateBR(nsINode* aNode,
return nullptr;
}
// We assume everything is fine if newBRElement is not null.
return CreateBRImpl(*selection, EditorRawDOMPoint(aNode, aOffset), aSelect);
return CreateBRImpl(*selection, aPointToInsert, aSelect);
}
already_AddRefed<Element>

Просмотреть файл

@ -188,20 +188,19 @@ protected:
const nsACString& aCharset);
/**
* CreateBR() creates new <br> element and inserts it before the point,
* aNode - aOffset, and collapse selection if it's necessary.
* CreateBR() creates new <br> element and inserts it before aPointToInsert,
* and collapse selection if it's necessary.
*
* @param aNode The container node to insert new <br> element.
* @param aOffset The offset in aNode to insert new <br> element.
* @param aSelect If eNone, this won't change selection.
* If eNext, selection will be collapsed after the <br>
* element.
* If ePrevious, selection will be collapsed at the <br>
* element.
* @return The new <br> node. If failed to create new <br> node,
* returns nullptr.
* @param aPointToInsert The point to insert new <br> element.
* @param aSelect If eNone, this won't change selection.
* If eNext, selection will be collapsed after the
* <br> element.
* If ePrevious, selection will be collapsed at the
* <br> element.
* @return The new <br> node. If failed to create new <br>
* node, returns nullptr.
*/
already_AddRefed<Element> CreateBR(nsINode* aNode, int32_t aOffset,
already_AddRefed<Element> CreateBR(const EditorRawDOMPoint& aPointToInsert,
EDirection aSelect = eNone);
/**

Просмотреть файл

@ -1754,6 +1754,11 @@ WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
return NS_ERROR_FAILURE;
}
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_NOT_INITIALIZED;
}
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
// first check for trailing nbsp
WSPoint thePoint = GetPreviousCharPoint(aRun->EndPoint());
if (thePoint.mTextNode && thePoint.mChar == nbsp) {
@ -1800,9 +1805,10 @@ WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
// beginning of soft wrapped lines, and lets the user see 2 spaces when
// they type 2 spaces.
nsCOMPtr<Element> brNode =
mHTMLEditor->CreateBR(aRun->mEndNode, aRun->mEndOffset);
NS_ENSURE_TRUE(brNode, NS_ERROR_FAILURE);
RefPtr<Element> brNode = htmlEditor->CreateBR(aRun->EndPoint());
if (NS_WARN_IF(!brNode)) {
return NS_ERROR_FAILURE;
}
// Refresh thePoint, prevPoint
thePoint = GetPreviousCharPoint(aRun->EndPoint());
@ -1812,11 +1818,11 @@ WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
}
if (leftCheck && rightCheck) {
// Now replace nbsp with space. First, insert a space
AutoTransactionsConserveSelection dontChangeMySelection(mHTMLEditor);
AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
nsAutoString spaceStr(char16_t(32));
nsresult rv =
mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr, *thePoint.mTextNode,
thePoint.mOffset, true);
htmlEditor->InsertTextIntoTextNodeImpl(spaceStr, *thePoint.mTextNode,
thePoint.mOffset, true);
NS_ENSURE_SUCCESS(rv, rv);
// Finally, delete that nbsp
@ -1851,10 +1857,10 @@ WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
}
// Finally, insert that nbsp before the ASCII ws run
AutoTransactionsConserveSelection dontChangeMySelection(mHTMLEditor);
AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
nsAutoString nbspStr(nbsp);
rv = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, *startNode,
startOffset, true);
rv = htmlEditor->InsertTextIntoTextNodeImpl(nbspStr, *startNode,
startOffset, true);
NS_ENSURE_SUCCESS(rv, rv);
}
}

Просмотреть файл

@ -165,7 +165,7 @@ impl BlobImageRenderer for Moz2dImageRenderer {
let buf_size = (descriptor.width
* descriptor.height
* descriptor.format.bytes_per_pixel()) as usize;
let mut output = vec![255u8; buf_size];
let mut output = vec![0u8; buf_size];
let result = unsafe {
if wr_moz2d_render_cb(

Просмотреть файл

@ -4330,6 +4330,7 @@ public:
nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayEventReceiver);
MOZ_ASSERT(aBuilder->IsForEventDelivery());
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayEventReceiver() {

Просмотреть файл

@ -371,7 +371,7 @@ nsSplitterFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsBoxFrame::BuildDisplayList(aBuilder, aLists);
// if the mouse is captured always return us as the frame.
if (mInner->mDragging)
if (mInner->mDragging && aBuilder->IsForEventDelivery())
{
// XXX It's probably better not to check visibility here, right?
aLists.Outlines()->AppendNewToTop(new (aBuilder)

Просмотреть файл

@ -11,6 +11,7 @@ import android.os.HandlerThread;
import android.util.Log;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
@ -28,6 +29,7 @@ import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedT
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
@ -560,8 +562,19 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
mRenderers[0] = mVRenderer;
mRenderers[1] = mARenderer;
// Use default values for constructing DefaultLoadControl except maxBufferMs.
// See Bug 1424168.
int maxBufferMs = Math.max(DefaultLoadControl.DEFAULT_MIN_BUFFER_MS,
DefaultLoadControl.DEFAULT_MAX_BUFFER_MS / 2);
DefaultLoadControl dlc =
new DefaultLoadControl(
new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
DefaultLoadControl.DEFAULT_MIN_BUFFER_MS,
maxBufferMs, /*this value can eliminate the memory usage immensely by experiment*/
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
// Create ExoPlayer instance with specific components.
mPlayer = ExoPlayerFactory.newInstance(mRenderers, mTrackSelector);
mPlayer = ExoPlayerFactory.newInstance(mRenderers, mTrackSelector, dlc);
mPlayer.addListener(this);
Uri uri = Uri.parse(url);

Просмотреть файл

@ -2160,13 +2160,15 @@ nsHttpConnectionMgr::GetSpdyActiveConn(nsConnectionEntry *ent)
//-----------------------------------------------------------------------------
void
nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param)
nsHttpConnectionMgr::AbortAndCloseAllConnections(int32_t, ARefBase *)
{
if (!OnSocketThread()) {
Unused << PostEvent(&nsHttpConnectionMgr::AbortAndCloseAllConnections);
return;
}
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG(("nsHttpConnectionMgr::OnMsgShutdown\n"));
gHttpHandler->StopRequestTokenBucket();
LOG(("nsHttpConnectionMgr::AbortAndCloseAllConnections\n"));
for (auto iter = mCT.Iter(); !iter.Done(); iter.Next()) {
RefPtr<nsConnectionEntry> ent = iter.Data();
@ -2224,6 +2226,23 @@ nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param)
iter.Remove();
}
mActiveTransactions[false].Clear();
mActiveTransactions[true].Clear();
}
void
nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param)
{
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG(("nsHttpConnectionMgr::OnMsgShutdown\n"));
gHttpHandler->StopRequestTokenBucket();
AbortAndCloseAllConnections(0, nullptr);
// If all idle connections are removed we can stop pruning dead
// connections.
ConditionallyStopPruneDeadConnectionsTimer();
if (mTimeoutTick) {
mTimeoutTick->Cancel();
mTimeoutTick = nullptr;
@ -2238,8 +2257,6 @@ nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param)
mTrafficTimer = nullptr;
}
DestroyThrottleTicker();
mActiveTransactions[false].Clear();
mActiveTransactions[true].Clear();
mCoalescingHash.Clear();

Просмотреть файл

@ -95,6 +95,9 @@ public:
// given time.
void PruneDeadConnectionsAfter(uint32_t time);
// this cancels all outstanding transactions but does not shut down the mgr
void AbortAndCloseAllConnections(int32_t, ARefBase *);
// Stops timer scheduled for next pruning of dead connections if
// there are no more idle connections or active spdy ones
void ConditionallyStopPruneDeadConnectionsTimer();

Просмотреть файл

@ -545,6 +545,7 @@ nsHttpHandler::Init()
obsService->AddObserver(this, "net:prune-dead-connections", true);
// Sent by the TorButton add-on in the Tor Browser
obsService->AddObserver(this, "net:prune-all-connections", true);
obsService->AddObserver(this, "net:cancel-all-connections", true);
obsService->AddObserver(this, "last-pb-context-exited", true);
obsService->AddObserver(this, "browser:purge-session-history", true);
obsService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true);
@ -2277,6 +2278,10 @@ nsHttpHandler::Observe(nsISupports *subject,
} else if (!strcmp(topic, "net:clear-active-logins")) {
Unused << mAuthCache.ClearAll();
Unused << mPrivateAuthCache.ClearAll();
} else if (!strcmp(topic, "net:cancel-all-connections")) {
if (mConnMgr) {
mConnMgr->AbortAndCloseAllConnections(0, nullptr);
}
} else if (!strcmp(topic, "net:prune-dead-connections")) {
if (mConnMgr) {
rv = mConnMgr->PruneDeadConnections();

Просмотреть файл

@ -0,0 +1,121 @@
// Test bug 1411316.
//
// Summary:
// The purpose of this test is to test whether the HttpConnectionMgr really
// cancel and close all connecitons when get "net:cancel-all-connections".
//
// Test step:
// 1. Create 6 http requests. Server would not process responses and just put
// all requests in its queue.
// 2. Once server receive all 6 requests, call notifyObservers with the
// topic "net:cancel-all-connections".
// 3. We expect that all 6 active connections should be closed with the status
// NS_ERROR_ABORT.
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Services.jsm");
var Cc = Components.classes;
var Ci = Components.interfaces;
var server = new HttpServer();
server.start(-1);
var baseURL = "http://localhost:" + server.identity.primaryPort + "/";
var maxConnections = 0;
var debug = false;
var requestId = 0;
function log(msg) {
if (!debug) {
return;
}
if (msg) {
dump("TEST INFO | " + msg + "\n");
}
}
function make_channel(url) {
var request = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
request.QueryInterface(Ci.nsIHttpChannel);
return request;
}
function serverStopListener() {
server.stop();
}
function createHttpRequest(status) {
let uri = baseURL;
var chan = make_channel(uri);
var listner = new HttpResponseListener(++requestId, status);
chan.setRequestHeader("X-ID", requestId, false);
chan.setRequestHeader("Cache-control", "no-store", false);
chan.asyncOpen2(listner);
log("Create http request id=" + requestId);
}
function setupHttpRequests(status) {
log("setupHttpRequests");
for (var i = 0; i < maxConnections ; i++) {
createHttpRequest(status);
do_test_pending();
}
}
function HttpResponseListener(id, onStopRequestStatus)
{
this.id = id
this.onStopRequestStatus = onStopRequestStatus;
};
HttpResponseListener.prototype =
{
onStartRequest: function (request, ctx) {
},
onDataAvailable: function (request, ctx, stream, off, cnt) {
},
onStopRequest: function (request, ctx, status) {
log("STOP id=" + this.id + " status=" + status);
do_check_true(this.onStopRequestStatus == status);
do_test_finished();
}
};
var responseQueue = new Array();
function setup_http_server()
{
log("setup_http_server");
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server");
var allDummyHttpRequestReceived = false;
// Start server; will be stopped at test cleanup time.
server.registerPathHandler('/', function(metadata, response)
{
var id = metadata.getHeader("X-ID");
log("Server recived the response id=" + id);
response.processAsync();
response.setHeader("X-ID", id);
responseQueue.push(response);
if (responseQueue.length == maxConnections) {
log("received all http requets");
Services.obs.notifyObservers(null, "net:cancel-all-connections");
}
});
do_register_cleanup(function() {
server.stop(serverStopListener);
});
}
function run_test() {
setup_http_server();
setupHttpRequests(Components.results.NS_ERROR_ABORT);
}

Просмотреть файл

@ -409,3 +409,4 @@ skip-if = os == "android"
[test_tls_flags_separate_connections.js]
[test_tls_flags.js]
[test_uri_mutator.js]
[test_bug1411316_http1.js]

Просмотреть файл

@ -190,7 +190,7 @@ class TupOnly(CommonBackend, PartialBackend):
self._installed_files = '$(MOZ_OBJ_ROOT)/<installed-files>'
def _get_backend_file(self, relobjdir):
objdir = mozpath.join(self.environment.topobjdir, relobjdir)
objdir = mozpath.normpath(mozpath.join(self.environment.topobjdir, relobjdir))
if objdir not in self._backend_files:
self._backend_files[objdir] = \
BackendTupfile(objdir, self.environment,
@ -331,6 +331,8 @@ class TupOnly(CommonBackend, PartialBackend):
if obj.script and obj.method and obj.relobjdir not in skip_directories:
backend_file.export_shell()
cmd = self._py_action('file_generate')
if obj.localized:
cmd.append('--locale=en-US')
cmd.extend([
obj.script,
obj.method,
@ -383,9 +385,9 @@ class TupOnly(CommonBackend, PartialBackend):
return
for path, files in obj.files.walk():
backend_file = self._get_backend_file(mozpath.join(target, path))
for f in files:
if not isinstance(f, ObjDirPath):
backend_file = self._get_backend_file(mozpath.join(target, path))
if '*' in f:
if f.startswith('/') or isinstance(f, AbsolutePath):
basepath, wild = os.path.split(f.full_path)

Просмотреть файл

@ -71,7 +71,7 @@ def generate_placeholder(testcase):
return [timings]
def run_gecko_test(testcase, url, timeout, is_async):
def run_gecko_test(testcase, url, date, timeout, is_async):
with create_gecko_session() as driver:
driver.set_page_load_timeout(timeout)
try:

Просмотреть файл

@ -17,7 +17,7 @@ from statistics import median, StatisticsError
from urllib.parse import urlsplit, urlunsplit, urljoin
DATE = datetime.now().strftime("%Y%m%d")
DATE = datetime.now().strftime("%Y-%m-%d")
MACHINE = platform.machine()
SYSTEM = platform.system()
@ -66,11 +66,11 @@ def execute_test(url, command, timeout):
return ""
def run_servo_test(testcase, url, timeout, is_async):
def run_servo_test(testcase, url, date, timeout, is_async):
if is_async:
print("Servo does not support async test!")
# Return a placeholder
return parse_log("", testcase, url)
return parse_log("", testcase, url, date)
ua_script_path = "{}/user-agent-js".format(os.getcwd())
command = [
@ -92,10 +92,10 @@ def run_servo_test(testcase, url, timeout, is_async):
))
except subprocess.TimeoutExpired:
print("Test FAILED due to timeout: {}".format(testcase))
return parse_log(log, testcase, url)
return parse_log(log, testcase, url, date)
def parse_log(log, testcase, url):
def parse_log(log, testcase, url, date):
blocks = []
block = []
copy = False
@ -149,7 +149,7 @@ def parse_log(log, testcase, url):
return {
"system": SYSTEM,
"machine": MACHINE,
"date": DATE,
"date": date,
"testcase": testcase,
"title": "",
"navigationStart": 0,
@ -177,15 +177,15 @@ def parse_log(log, testcase, url):
# Set the testcase field to contain the original testcase name,
# rather than the url.
def set_testcase(timing, testcase=None):
def set_testcase(timing, testcase=None, date=None):
timing['testcase'] = testcase
timing['system'] = SYSTEM
timing['machine'] = MACHINE
timing['date'] = DATE
timing['date'] = date
return timing
valid_timing_for_case = partial(valid_timing, url=url)
set_testcase_for_case = partial(set_testcase, testcase=testcase)
set_testcase_for_case = partial(set_testcase, testcase=testcase, date=date)
timings = list(map(set_testcase_for_case, filter(valid_timing_for_case, map(parse_block, blocks))))
if len(timings) == 0:
@ -329,6 +329,10 @@ def main():
default=300, # 5 min
help=("kill the test if not finished in time (sec)."
" Default: 5 min"))
parser.add_argument("--date",
type=str,
default=None, # 5 min
help=("the date to use in the CSV file."))
parser.add_argument("--engine",
type=str,
default='servo',
@ -340,6 +344,7 @@ def main():
elif args.engine == 'gecko':
import gecko_driver # Load this only when we need gecko test
run_test = gecko_driver.run_gecko_test
date = args.date or DATE
try:
# Assume the server is up and running
testcases = load_manifest(args.tp5_manifest)
@ -352,7 +357,7 @@ def main():
url))
# results will be a mixure of timings dict and testcase strings
# testcase string indicates a failed test
results += run_test(testcase, url, args.timeout, is_async)
results += run_test(testcase, url, date, args.timeout, is_async)
print("Finished")
# TODO: Record and analyze other performance.timing properties

Просмотреть файл

@ -14,6 +14,7 @@ set -o pipefail
# https://groups.google.com/forum/#!topic/mozilla.dev.servo/JlAZoRgcnpA
port="8123"
base="http://localhost:${port}"
date="$(date +%Y-%m-%d)"
while (( "${#}" ))
do
@ -33,6 +34,10 @@ case "${1}" in
base="${2}"
shift
;;
--date)
date="${2}"
shift
;;
*)
echo "Unknown option ${1}."
exit
@ -56,11 +61,12 @@ trap 'kill $(jobs -pr)' SIGINT SIGTERM EXIT
# MANIFEST="page_load_test/tp5n/20160509.manifest"
MANIFEST="page_load_test/test.manifest" # A manifest that excludes
# timeout test cases
PERF_KEY="perf-$(uname -s)-$(uname -m)-$(date +%s).csv"
PERF_KEY="perf-$(uname -s)-$(uname -m)-${date}.csv"
PERF_FILE="output/${PERF_KEY}"
echo "Running tests"
python3 runner.py ${engine} --runs 4 --timeout "${timeout}" --base "${base}" \
python3 runner.py ${engine} --runs 4 --timeout "${timeout}" \
--base "${base}" --date "${date}" \
"${MANIFEST}" "${PERF_FILE}"
if [[ "${submit:-}" ]];

Просмотреть файл

@ -171,9 +171,11 @@ class MachCommands(CommandBase):
category='testing')
@CommandArgument('--base', default=None,
help="the base URL for testcases")
@CommandArgument('--date', default=None,
help="the datestamp for the data")
@CommandArgument('--submit', '-a', default=False, action="store_true",
help="submit the data to perfherder")
def test_perf(self, base=None, submit=False):
def test_perf(self, base=None, date=None, submit=False):
self.set_software_rendering_env(True)
self.ensure_bootstrapped()
@ -181,6 +183,8 @@ class MachCommands(CommandBase):
cmd = ["bash", "test_perf.sh"]
if base:
cmd += ["--base", base]
if date:
cmd += ["--date", date]
if submit:
cmd += ["--submit"]
return call(cmd,

Просмотреть файл

@ -32,7 +32,7 @@
using namespace mozilla;
// Yikes! Casting a char to unichar can fill with ones!
#define CHAR_TO_UNICHAR(c) ((char16_t)(const unsigned char)c)
#define CHAR_TO_UNICHAR(c) ((char16_t)(unsigned char)c)
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
static NS_DEFINE_CID(kCPreContentIteratorCID, NS_PRECONTENTITERATOR_CID);

Просмотреть файл

@ -1015,7 +1015,7 @@ PendingLookup::GetSpecHash(nsACString& aSpec, nsACString& hexEncodedHash)
static const char* const hex = "0123456789ABCDEF";
hexEncodedHash.SetCapacity(2 * binaryHash.Length());
for (size_t i = 0; i < binaryHash.Length(); ++i) {
auto c = static_cast<const unsigned char>(binaryHash[i]);
auto c = static_cast<unsigned char>(binaryHash[i]);
hexEncodedHash.Append(hex[(c >> 4) & 0x0F]);
hexEncodedHash.Append(hex[c & 0x0F]);
}

Просмотреть файл

@ -104,7 +104,7 @@ struct SafebrowsingHash
aStr.SetCapacity(2 * len);
for (size_t i = 0; i < len; ++i) {
const char c = static_cast<const char>(buf[i]);
const char c = static_cast<char>(buf[i]);
aStr.Append(lut[(c >> 4) & 0x0F]);
aStr.Append(lut[c & 15]);
}

Просмотреть файл

@ -59,7 +59,7 @@ void CStringToHexString(const nsACString& aIn, nsACString& aOut)
aOut.SetCapacity(2 * len);
for (size_t i = 0; i < aIn.Length(); ++i) {
const char c = static_cast<const char>(aIn[i]);
const char c = static_cast<char>(aIn[i]);
aOut.Append(lut[(c >> 4) & 0x0F]);
aOut.Append(lut[c & 15]);
}

Просмотреть файл

@ -1,11 +1,22 @@
const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_silentAudioTrack.html";
async function check_video_decoding_state(isSuspended) {
async function check_video_decoding_state(args) {
let video = content.document.getElementById("autoplay");
if (!video) {
ok(false, "Can't get the video element!");
}
let isSuspended = args.suspend;
let reload = args.reload;
if (reload) {
// It is too late to register event handlers when playback is half
// way done. Let's start playback from the beginning so we won't
// miss any events.
video.load();
video.play();
}
let state = isSuspended ? "suspended" : "resumed";
let event = isSuspended ? "mozentervideosuspend" : "mozexitvideosuspend";
return new Promise(resolve => {
@ -46,13 +57,16 @@ function check_should_not_send_unselected_tab_hover_msg(browser) {
});
}
function get_video_decoding_suspend_promise(browser) {
return ContentTask.spawn(browser, true /* suspend */,
function get_video_decoding_suspend_promise(browser, reload) {
let suspend = true;
return ContentTask.spawn(browser, { suspend, reload },
check_video_decoding_state);
}
function get_video_decoding_resume_promise(browser) {
return ContentTask.spawn(browser, false /* resume */,
let suspend = false;
let reload = false;
return ContentTask.spawn(browser, { suspend, reload },
check_video_decoding_state);
}
@ -97,7 +111,7 @@ add_task(async function resume_and_suspend_background_video_decoding() {
await BrowserTestUtils.browserLoaded(browser);
info("- should suspend background video decoding -");
await get_video_decoding_suspend_promise(browser);
await get_video_decoding_suspend_promise(browser, true);
await check_should_send_unselected_tab_hover_msg(browser);
info("- when cursor is hovering over the tab, resuming the video decoding -");

Просмотреть файл

@ -251,7 +251,7 @@
</toolbarbutton>
<textbox id="header-search" type="search" searchbutton="true"
searchbuttonlabel="&search.buttonlabel;"
placeholder="&search.placeholder2;"/>
placeholder="&search.placeholder2;" maxlength="100"/>
</hbox>
<deck id="headered-views-content" flex="1" selectedIndex="0">

Просмотреть файл

@ -20,6 +20,7 @@
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "mozilla/intl/LocaleService.h"
#include "nsNativeCharsetUtils.h"
#include "nsAppRunner.h"
#include "mozilla/XREAppData.h"
@ -4516,6 +4517,16 @@ XREMain::XRE_mainRun()
}
}
if (NS_IsNativeUTF8()) {
nsCOMPtr<nsIFile> profileDir;
nsAutoCString path;
rv = mDirProvider.GetProfileStartupDir(getter_AddRefs(profileDir));
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(profileDir->GetNativePath(path)) && !IsUTF8(path)) {
PR_fprintf(PR_STDERR, "Error: The profile path is not valid UTF-8. Unable to continue.\n");
return NS_ERROR_FAILURE;
}
}
// Initialize user preferences before notifying startup observers so they're
// ready in time for early consumers, such as the component loader.
mDirProvider.InitializeUserPrefs();

Просмотреть файл

@ -1,3 +1,5 @@
let {Constructor: CC, classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
function get_test_program(prog) {
var progPath = do_get_cwd();
progPath.append(prog);
@ -8,6 +10,8 @@ function get_test_program(prog) {
function set_process_running_environment() {
var envSvc = Components.classes["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
// Importing Services here messes up appInfo for some of the tests.
// eslint-disable-next-line mozilla/use-services
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties);
var greBinDir = dirSvc.get("GreBinD", Components.interfaces.nsIFile);
@ -16,4 +20,3 @@ function set_process_running_environment() {
envSvc.set("LD_LIBRARY_PATH", greBinDir.path);
// XXX: handle windows
}

Просмотреть файл

@ -1,14 +1,10 @@
var Ci = Components.interfaces;
var Cu = Components.utils;
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function run_test() {
var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
var dataFile = do_get_file("data/bug121341.properties");
var channel = NetUtil.newChannel({
uri: ios.newFileURI(dataFile, null, null),
uri: Services.io.newFileURI(dataFile, null, null),
loadUsingSystemPrincipal: true
});
var inp = channel.open2();
@ -55,7 +51,7 @@ function run_test() {
dataFile = do_get_file("data/bug121341-2.properties");
var channel2 = NetUtil.newChannel({
uri: ios.newFileURI(dataFile, null, null),
uri: Services.io.newFileURI(dataFile, null, null),
loadUsingSystemPrincipal: true
});
inp = channel2.open2();

Просмотреть файл

@ -1,6 +1,3 @@
var Cc = Components.classes;
var Ci = Components.interfaces;
// 5 seconds.
const kExpectedDelay1 = 5;
// 1 second.

Просмотреть файл

@ -1,10 +1,7 @@
var Cc = Components.classes;
var Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
function run_test() {
var f =
Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile);
var f = Services.dirsvc.get("CurProcD", Ci.nsIFile);
var terminated = false;
for (var i = 0; i < 100; i++) {

Просмотреть файл

@ -1,5 +1,4 @@
var Ci = Components.interfaces;
var Cc = Components.classes;
Cu.import("resource://gre/modules/Services.jsm");
var nameArray = [
"ascii", // ASCII
@ -12,9 +11,7 @@ var nameArray = [
];
function getTempDir() {
var dirService = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties);
return dirService.get("TmpD", Ci.nsIFile);
return Services.dirsvc.get("TmpD", Ci.nsIFile);
}
function create_file(fileName) {

Просмотреть файл

@ -1,5 +1,4 @@
var Cc = Components.classes;
var Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
var addedTopic = "xpcom-category-entry-added";
var removedTopic = "xpcom-category-entry-removed";
@ -23,9 +22,8 @@ var observer = {
if (topic == "timer-callback") {
do_check_eq(result, expected);
var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.removeObserver(this, addedTopic);
observerService.removeObserver(this, removedTopic);
Services.obs.removeObserver(this, addedTopic);
Services.obs.removeObserver(this, removedTopic);
do_test_finished();
@ -45,9 +43,8 @@ var observer = {
function run_test() {
do_test_pending();
var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver(observer, addedTopic);
observerService.addObserver(observer, removedTopic);
Services.obs.addObserver(observer, addedTopic);
Services.obs.addObserver(observer, removedTopic);
var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
categoryManager.addCategoryEntry(testCategory, testEntry, testValue, false, true);

Просмотреть файл

@ -1,6 +1,3 @@
var Cc = Components.classes;
var Ci = Components.interfaces;
/* global __LOCATION__ */
function run_test() {

Просмотреть файл

@ -1,10 +1,8 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
/* global registerAppManifest */
var Cc = Components.classes;
var Ci = Components.interfaces;
function info(s) {
dump("TEST-INFO | test_bug656331.js | " + s + "\n");
}
@ -22,9 +20,7 @@ const kConsoleListener = {
};
function run_test() {
let cs = Components.classes["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
cs.registerListener(kConsoleListener);
Services.console.registerListener(kConsoleListener);
let manifest = do_get_file("components/bug656331.manifest");
registerAppManifest(manifest);
@ -32,10 +28,9 @@ function run_test() {
do_check_false("{f18fb09b-28b4-4435-bc5b-8027f18df743}" in Components.classesByID);
do_test_pending();
Components.classes["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager).dispatchToMainThread(function() {
cs.unregisterListener(kConsoleListener);
do_check_true(gFound);
do_test_finished();
});
Services.tm.dispatchToMainThread(function() {
Services.console.unregisterListener(kConsoleListener);
do_check_true(gFound);
do_test_finished();
});
}

Просмотреть файл

@ -2,9 +2,6 @@
* 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/. */
var Cc = Components.classes;
var Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/Services.jsm");
const manifest = do_get_file("bug725015.manifest");

Просмотреть файл

@ -9,7 +9,6 @@
// expected byte sizes within SpiderMonkey's jit-tests, we just want to make
// sure that Gecko is providing SpiderMonkey with the callback it needs.
var Cu = Components.utils;
const { byteSize } = Cu.getJSTestingFunctions();
function run_test() {

Просмотреть файл

@ -3,17 +3,14 @@
* 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/. */
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
Cu.import("resource://gre/modules/Services.jsm");
function run_test() {
// Generate a leaf name that is 255 characters long.
var longLeafName = new Array(256).join("T");
// Generate the path for a file located in a directory with a long name.
var tempFile = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
var tempFile = Services.dirsvc.get("TmpD", Ci.nsIFile);
tempFile.append(longLeafName);
tempFile.append("test.txt");

Просмотреть файл

@ -4,20 +4,17 @@
* 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/. */
var Cr = Components.results;
var Ci = Components.interfaces;
var CC = Components.Constructor;
var LocalFile = CC("@mozilla.org/file/local;1", "nsIFile", "initWithPath");
Cu.import("resource://gre/modules/Services.jsm");
function run_test() {
test_normalized_vs_non_normalized();
}
function test_normalized_vs_non_normalized() {
// get a directory that exists on all platforms
var dirProvider = Components.classes["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var tmp1 = dirProvider.get("TmpD", Ci.nsIFile);
var tmp1 = Services.dirsvc.get("TmpD", Ci.nsIFile);
var exists = tmp1.exists();
do_check_true(exists);
if (!exists)

Просмотреть файл

@ -3,14 +3,11 @@
* 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/. */
var Cc = Components.classes;
var Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
function run_test() {
// Create the base directory.
let base = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("TmpD", Ci.nsIFile);
let base = Services.dirsvc.get("TmpD", Ci.nsIFile);
base.append("renameTesting");
if (base.exists()) {
base.remove(true);

Просмотреть файл

@ -1,13 +1,12 @@
var Ci = Components.interfaces;
var Cc = Components.classes;
const NS_OS_TEMP_DIR = "TmpD";
const CWD = do_get_cwd();
Cu.import("resource://gre/modules/Services.jsm");
var hiddenUnixFile;
function createUNIXHiddenFile() {
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var tmpDir = dirSvc.get(NS_OS_TEMP_DIR, Ci.nsIFile);
var tmpDir = Services.dirsvc.get(NS_OS_TEMP_DIR, Ci.nsIFile);
hiddenUnixFile = tmpDir.clone();
hiddenUnixFile.append(".foo");
// we don't care if this already exists because we don't care
@ -25,4 +24,3 @@ function run_test() {
do_check_true(createUNIXHiddenFile());
do_check_true(hiddenUnixFile.isHidden());
}

Просмотреть файл

@ -1,5 +1,4 @@
var Ci = Components.interfaces;
var Cc = Components.classes;
Cu.import("resource://gre/modules/Services.jsm");
const CWD = do_get_cwd();
function checkOS(os) {
@ -13,8 +12,7 @@ const isWin = checkOS("Win");
function run_test() {
var envVar = isWin ? "USERPROFILE" : "HOME";
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
var homeDir = dirSvc.get("Home", Ci.nsIFile);
var homeDir = Services.dirsvc.get("Home", Ci.nsIFile);
var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
var expected = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);

Просмотреть файл

@ -1,7 +1,3 @@
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cr = Components.results;
var testnum = 0;
var factory;
@ -129,6 +125,8 @@ var testdata = [
testdata.push( { filename: "data/iniparser16-utf8BOM.ini",
reference: testdata[15].reference } );
// Intentional test for appInfo that can't be preloaded.
// eslint-disable-next-line mozilla/use-services
let os = Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime).OS;
if ("WINNT" === os) {

Просмотреть файл

@ -3,10 +3,6 @@
* 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/. */
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
const util = Cc["@mozilla.org/io-util;1"].getService(Ci.nsIIOUtil);
function run_test() {

Просмотреть файл

@ -4,10 +4,6 @@
* 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/. */
var Cr = Components.results;
var CC = Components.Constructor;
var Ci = Components.interfaces;
const MAX_TIME_DIFFERENCE = 2500;
const MILLIS_PER_DAY = 1000 * 60 * 60 * 24;

Просмотреть файл

@ -3,11 +3,6 @@
* 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/. */
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
var Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const kCID = Components.ID("{1f9f7181-e6c5-4f4c-8f71-08005cec8468}");
@ -80,4 +75,3 @@ function run_test() {
}
strictEqual(xpcomObject.method3, undefined);
}

Просмотреть файл

@ -2,11 +2,6 @@
* 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/. */
var Ci = Components.interfaces;
var Cr = Components.results;
var Cc = Components.classes;
var CC = Components.Constructor;
var MutableArray = CC("@mozilla.org/array;1", "nsIMutableArray");
var SupportsString = CC("@mozilla.org/supports-string;1", "nsISupportsString");

Просмотреть файл

@ -4,11 +4,6 @@
* 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/. */
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
var CC = Components.Constructor;
var Pipe = CC("@mozilla.org/pipe;1", "nsIPipe", "init");
function run_test() {

Просмотреть файл

@ -1,6 +1,3 @@
var Ci = Components.interfaces;
var Cc = Components.classes;
Components.utils.import("resource://gre/modules/Services.jsm");
function run_test() {

Просмотреть файл

@ -2,11 +2,6 @@
* 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/. */
var Ci = Components.interfaces;
var Cr = Components.results;
var CC = Components.Constructor;
var Cc = Components.classes;
// The string we use as data.
const data = "0123456789";
// Number of streams in the multiplex stream.
@ -160,4 +155,3 @@ function run_test() {
test_multiplex_streams();
test_multiplex_bug797871();
}

Просмотреть файл

@ -6,10 +6,6 @@
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "unusedVariable" }] */
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
function run_test() {
test1();
test2();

Просмотреть файл

@ -2,10 +2,6 @@
* 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/. */
var Ci = Components.interfaces;
var Cr = Components.results;
var CC = Components.Constructor;
var Pipe = CC("@mozilla.org/pipe;1",
"nsIPipe",
"init");

Просмотреть файл

@ -3,10 +3,6 @@
* 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/. */
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
function run_test() {
var s = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);

Просмотреть файл

@ -1,3 +1,5 @@
Cu.import("resource://gre/modules/Services.jsm");
// Versions to test listed in ascending order, none can be equal
var comparisons = [
"0.9",
@ -29,12 +31,9 @@ var equality = [
];
function run_test() {
var vc = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
.getService(Components.interfaces.nsIVersionComparator);
for (var i = 0; i < comparisons.length; i++) {
for (var j = 0; j < comparisons.length; j++) {
var result = vc.compare(comparisons[i], comparisons[j]);
var result = Services.vc.compare(comparisons[i], comparisons[j]);
if (i == j) {
if (result != 0)
do_throw(comparisons[i] + " should be the same as itself");
@ -49,7 +48,7 @@ function run_test() {
for (i = 0; i < equality.length; i++) {
for (j = 0; j < equality.length; j++) {
if (vc.compare(equality[i], equality[j]) != 0)
if (Services.vc.compare(equality[i], equality[j]) != 0)
do_throw(equality[i] + " should equal " + equality[j]);
}
}

Просмотреть файл

@ -1,4 +1,3 @@
let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
let executableFile = Services.dirsvc.get("CurProcD", Ci.nsIFile);

Просмотреть файл

@ -5,12 +5,6 @@
* 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/. */
const Cr = Components.results;
const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
const CC = Components.Constructor;
const nsIWindowsRegKey = Ci.nsIWindowsRegKey;
let regKeyComponent = Cc["@mozilla.org/windows-registry-key;1"];

Просмотреть файл

@ -5,12 +5,6 @@
* 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/. */
var Cr = Components.results;
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cu = Components.utils;
var CC = Components.Constructor;
const LocalFile = CC("@mozilla.org/file/local;1", "nsIFile", "initWithPath");
Cu.import("resource://gre/modules/Services.jsm");