Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-06-16 14:38:49 -04:00
commit 0d95f190c0
72 changed files with 1702 additions and 3446 deletions

View File

@ -328,6 +328,18 @@ var shell = {
.sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
.createInstance(Ci.nsISHistory);
this.allowedAudioChannels = new Map();
let audioChannels = systemAppFrame.allowedAudioChannels;
audioChannels && audioChannels.forEach(function(audioChannel) {
this.allowedAudioChannels.set(audioChannel.name, audioChannel);
audioChannel.addEventListener('activestatechanged', this);
// Set all audio channels as unmuted by default
// because some audio in System app will be played
// before AudioChannelService[1] is Gaia is loaded.
// [1]: https://github.com/mozilla-b2g/gaia/blob/master/apps/system/js/audio_channel_service.js
audioChannel.setMuted(false);
}.bind(this));
// On firefox mulet, shell.html is loaded in a tab
// and we have to listen on the chrome event handler
// to catch key events
@ -561,6 +573,18 @@ var shell = {
case 'unload':
this.stop();
break;
case 'activestatechanged':
var channel = evt.target;
// TODO: We should get the `isActive` state from evt.isActive.
// Then we don't need to do `channel.isActive()` here.
channel.isActive().onsuccess = function(evt) {
this.sendChromeEvent({
type: 'system-audiochannel-state-changed',
name: channel.name,
isActive: evt.target.result
});
}.bind(this);
break;
}
},
@ -739,6 +763,11 @@ var CustomEventManager = {
case 'inputregistry-remove':
KeyboardHelper.handleEvent(detail);
break;
case 'system-audiochannel-list':
case 'system-audiochannel-mute':
case 'system-audiochannel-volume':
SystemAppMozBrowserHelper.handleEvent(detail);
break;
case 'do-command':
DoCommandHelper.handleEvent(detail.cmd);
break;
@ -867,6 +896,63 @@ let KeyboardHelper = {
}
};
let SystemAppMozBrowserHelper = {
handleEvent: function systemAppMozBrowser_handleEvent(detail) {
let request;
let name;
switch (detail.type) {
case 'system-audiochannel-list':
let audioChannels = [];
shell.allowedAudioChannels.forEach(function(value, name) {
audioChannels.push(name);
});
SystemAppProxy._sendCustomEvent('mozSystemWindowChromeEvent', {
type: 'system-audiochannel-list',
audioChannels: audioChannels
});
break;
case 'system-audiochannel-mute':
name = detail.name;
let isMuted = detail.isMuted;
request = shell.allowedAudioChannels.get(name).setMuted(isMuted);
request.onsuccess = function() {
SystemAppProxy._sendCustomEvent('mozSystemWindowChromeEvent', {
type: 'system-audiochannel-mute-onsuccess',
name: name,
isMuted: isMuted
});
};
request.onerror = function() {
SystemAppProxy._sendCustomEvent('mozSystemWindowChromeEvent', {
type: 'system-audiochannel-mute-onerror',
name: name,
isMuted: isMuted
});
};
break;
case 'system-audiochannel-volume':
name = detail.name;
let volume = detail.volume;
request = shell.allowedAudioChannels.get(name).setVolume(volume);
request.onsuccess = function() {
sSystemAppProxy._sendCustomEvent('mozSystemWindowChromeEvent', {
type: 'system-audiochannel-volume-onsuccess',
name: name,
volume: volume
});
};
request.onerror = function() {
SystemAppProxy._sendCustomEvent('mozSystemWindowChromeEvent', {
type: 'system-audiochannel-volume-onerror',
name: name,
volume: volume
});
};
break;
}
}
};
// This is the backend for Gaia's screenshot feature. Gaia requests a
// screenshot by sending a mozContentEvent with detail.type set to
// 'take-screenshot'. Then we take a screenshot and send a

View File

@ -259,8 +259,9 @@ interface nsIContentPolicyBase : nsISupports
/* When adding new content types, please update nsContentBlocker,
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
* implementations, and other things that are not listed here that are
* related to nsIContentPolicy. */
* implementations, the static_assert in dom/cache/DBSchema.cpp,
* and other things that are not listed here that are related to
* nsIContentPolicy. */
//////////////////////////////////////////////////////////////////////

View File

@ -30,6 +30,9 @@ nsNoDataProtocolContentPolicy::ShouldLoad(uint32_t aContentType,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
*aDecision = nsIContentPolicy::ACCEPT;
// Don't block for TYPE_OBJECT since such URIs are sometimes loaded by the

View File

@ -128,7 +128,18 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 &&
nsIContentPolicy::TYPE_XSLT == 18 &&
nsIContentPolicy::TYPE_BEACON == 19 &&
nsIContentPolicy::TYPE_FETCH == 20 &&
nsIContentPolicy::TYPE_IMAGESET == 21,
nsIContentPolicy::TYPE_IMAGESET == 21 &&
nsIContentPolicy::TYPE_WEB_MANIFEST == 22 &&
nsIContentPolicy::TYPE_INTERNAL_SCRIPT == 23 &&
nsIContentPolicy::TYPE_INTERNAL_WORKER == 24 &&
nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER == 25 &&
nsIContentPolicy::TYPE_INTERNAL_EMBED == 26 &&
nsIContentPolicy::TYPE_INTERNAL_OBJECT == 27 &&
nsIContentPolicy::TYPE_INTERNAL_FRAME == 28 &&
nsIContentPolicy::TYPE_INTERNAL_IFRAME == 29 &&
nsIContentPolicy::TYPE_INTERNAL_AUDIO == 30 &&
nsIContentPolicy::TYPE_INTERNAL_VIDEO == 31 &&
nsIContentPolicy::TYPE_INTERNAL_TRACK == 32,
"nsContentPolicytType values are as expected");
namespace {

View File

@ -327,167 +327,6 @@ UploadLastDir::ContentPrefCallback::HandleError(nsresult error)
namespace {
/**
* This enumerator returns File objects after wrapping a single
* nsIFile representing a directory. It enumerates the files under that
* directory and its subdirectories as a flat list of files, ignoring/skipping
* over symbolic links.
*
* The enumeration involves I/O, so this class must NOT be used on the main
* thread or else the main thread could be blocked for a very long time.
*
* This enumerator does not walk the directory tree breadth-first, but it also
* is not guaranteed to walk it depth-first either (since it uses
* nsIFile::GetDirectoryEntries, which is not guaranteed to group a directory's
* subdirectories at the beginning of the list that it returns).
*/
class DirPickerRecursiveFileEnumerator final
: public nsISimpleEnumerator
{
~DirPickerRecursiveFileEnumerator() {}
public:
NS_DECL_ISUPPORTS
explicit DirPickerRecursiveFileEnumerator(nsIFile* aTopDir)
: mTopDir(aTopDir)
{
MOZ_ASSERT(!NS_IsMainThread(), "This class blocks on I/O!");
#ifdef DEBUG
{
bool isDir;
aTopDir->IsDirectory(&isDir);
MOZ_ASSERT(isDir);
}
#endif
if (NS_FAILED(aTopDir->GetParent(getter_AddRefs(mTopDirsParent)))) {
// This just means that the name of the picked directory won't be
// included in the File.path string.
mTopDirsParent = aTopDir;
}
nsCOMPtr<nsISimpleEnumerator> entries;
if (NS_SUCCEEDED(mTopDir->GetDirectoryEntries(getter_AddRefs(entries))) &&
entries) {
mDirEnumeratorStack.AppendElement(entries);
LookupAndCacheNext();
}
}
NS_IMETHOD
GetNext(nsISupports** aResult) override
{
MOZ_ASSERT(!NS_IsMainThread(),
"Walking the directory tree involves I/O, so using this "
"enumerator can block a thread for a long time!");
if (!mNextFile) {
return NS_ERROR_FAILURE;
}
// The parent for this object will be set on the main thread.
nsRefPtr<File> domFile = File::CreateFromFile(nullptr, mNextFile);
nsCString relDescriptor;
nsresult rv =
mNextFile->GetRelativeDescriptor(mTopDirsParent, relDescriptor);
NS_ENSURE_SUCCESS(rv, rv);
NS_ConvertUTF8toUTF16 path(relDescriptor);
nsAutoString leafName;
mNextFile->GetLeafName(leafName);
MOZ_ASSERT(leafName.Length() <= path.Length());
int32_t length = path.Length() - leafName.Length();
MOZ_ASSERT(length >= 0);
if (length > 0) {
// Note that we leave the trailing "/" on the path.
BlobImplFile* blobImpl = static_cast<BlobImplFile*>(domFile->Impl());
MOZ_ASSERT(blobImpl);
blobImpl->SetPath(Substring(path, 0, uint32_t(length)));
}
nsCOMPtr<nsIDOMBlob> blob = domFile.get();
blob.forget(aResult);
LookupAndCacheNext();
return NS_OK;
}
NS_IMETHOD
HasMoreElements(bool* aResult) override
{
*aResult = !!mNextFile;
return NS_OK;
}
private:
void
LookupAndCacheNext()
{
for (;;) {
if (mDirEnumeratorStack.IsEmpty()) {
mNextFile = nullptr;
break;
}
nsISimpleEnumerator* currentDirEntries =
mDirEnumeratorStack.LastElement();
bool hasMore;
DebugOnly<nsresult> rv = currentDirEntries->HasMoreElements(&hasMore);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (!hasMore) {
mDirEnumeratorStack.RemoveElementAt(mDirEnumeratorStack.Length() - 1);
continue;
}
nsCOMPtr<nsISupports> entry;
rv = currentDirEntries->GetNext(getter_AddRefs(entry));
MOZ_ASSERT(NS_SUCCEEDED(rv));
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
MOZ_ASSERT(file);
bool isLink, isSpecial;
file->IsSymlink(&isLink);
file->IsSpecial(&isSpecial);
if (isLink || isSpecial) {
continue;
}
bool isDir;
file->IsDirectory(&isDir);
if (isDir) {
nsCOMPtr<nsISimpleEnumerator> subDirEntries;
rv = file->GetDirectoryEntries(getter_AddRefs(subDirEntries));
MOZ_ASSERT(NS_SUCCEEDED(rv) && subDirEntries);
mDirEnumeratorStack.AppendElement(subDirEntries);
continue;
}
#ifdef DEBUG
{
bool isFile;
file->IsFile(&isFile);
MOZ_ASSERT(isFile);
}
#endif
mNextFile.swap(file);
return;
}
}
private:
nsCOMPtr<nsIFile> mTopDir;
nsCOMPtr<nsIFile> mTopDirsParent; // May be mTopDir if no parent
nsCOMPtr<nsIFile> mNextFile;
nsTArray<nsCOMPtr<nsISimpleEnumerator> > mDirEnumeratorStack;
};
NS_IMPL_ISUPPORTS(DirPickerRecursiveFileEnumerator, nsISimpleEnumerator)
/**
* This may return nullptr if aDomFile's implementation of
* File::mozFullPathInternal does not successfully return a non-empty
@ -518,119 +357,6 @@ DOMFileToLocalFile(File* aDomFile)
} // anonymous namespace
class DirPickerFileListBuilderTask final
: public nsRunnable
{
public:
DirPickerFileListBuilderTask(HTMLInputElement* aInput, nsIFile* aTopDir)
: mPreviousFileListLength(0)
, mInput(aInput)
, mTopDir(aTopDir)
, mFileListLength(0)
, mCanceled(false)
{}
NS_IMETHOD Run() {
if (!NS_IsMainThread()) {
// Build up list of File objects on this dedicated thread:
nsCOMPtr<nsISimpleEnumerator> iter =
new DirPickerRecursiveFileEnumerator(mTopDir);
bool hasMore = true;
nsCOMPtr<nsISupports> tmp;
while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
iter->GetNext(getter_AddRefs(tmp));
nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(tmp);
MOZ_ASSERT(domBlob);
mFileList.AppendElement(static_cast<File*>(domBlob.get()));
mFileListLength = mFileList.Length();
if (mCanceled) {
MOZ_ASSERT(!mInput, "This is bad - how did this happen?");
// There's no point dispatching to the main thread (that doesn't
// guarantee that we'll be destroyed there).
return NS_OK;
}
}
return NS_DispatchToMainThread(this);
}
// Now back on the main thread, set the list on our HTMLInputElement:
if (mCanceled || mFileList.IsEmpty()) {
return NS_OK;
}
MOZ_ASSERT(mInput->mDirPickerFileListBuilderTask,
"But we aren't canceled!");
if (mInput->mProgressTimer) {
mInput->mProgressTimerIsActive = false;
mInput->mProgressTimer->Cancel();
}
mInput->MaybeDispatchProgressEvent(true); // Last progress event.
mInput->mDirPickerFileListBuilderTask = nullptr; // Now null out.
if (mCanceled) { // The last progress event may have canceled us
return NS_OK;
}
// Recreate File with the correct parent object.
nsCOMPtr<nsIGlobalObject> global = mInput->OwnerDoc()->GetScopeObject();
for (uint32_t i = 0; i < mFileList.Length(); ++i) {
MOZ_ASSERT(!mFileList[i]->GetParentObject());
mFileList[i] = File::Create(global, mFileList[i]->Impl());
MOZ_ASSERT(mFileList[i]);
}
// The text control frame (if there is one) isn't going to send a change
// event because it will think this is done by a script.
// So, we can safely send one by ourself.
mInput->SetFiles(mFileList, true);
nsresult rv =
nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
NS_LITERAL_STRING("change"), true,
false);
// Clear mInput to make sure that it can't lose its last strong ref off the
// main thread (which may happen if our dtor runs off the main thread)!
mInput = nullptr;
return rv;
}
void Cancel()
{
MOZ_ASSERT(NS_IsMainThread() && !mCanceled);
// Clear mInput to make sure that it can't lose its last strong ref off the
// main thread (which may happen if our dtor runs off the main thread)!
mInput = nullptr;
mCanceled = true;
}
uint32_t GetFileListLength() const
{
return mFileListLength;
}
/**
* The number of files added to the FileList at the time the last progress
* event was fired.
*
* This is only read/set by HTMLInputElement on the main thread. The reason
* that this member is stored here rather than on HTMLInputElement is so that
* we don't increase the size of HTMLInputElement for something that's rarely
* used.
*/
uint32_t mPreviousFileListLength;
private:
nsRefPtr<HTMLInputElement> mInput;
nsCOMPtr<nsIFile> mTopDir;
nsTArray<nsRefPtr<File>> mFileList;
// We access the list length on both threads, so we need the indirection of
// this atomic member to make the access thread safe:
mozilla::Atomic<uint32_t> mFileListLength;
mozilla::Atomic<bool> mCanceled;
};
NS_IMETHODIMP
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
@ -641,47 +367,9 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
return NS_OK;
}
mInput->CancelDirectoryPickerScanIfRunning();
int16_t mode;
mFilePicker->GetMode(&mode);
if (mode == static_cast<int16_t>(nsIFilePicker::modeGetFolder)) {
// Directory picking is different, since we still need to do more I/O to
// build up the list of File objects. Since this may block for a
// long time, we need to build the list off on another dedicated thread to
// avoid blocking any other activities that the browser is carrying out.
// The user selected this directory, so we always save this dir, even if
// no files are found under it.
nsCOMPtr<nsIFile> pickedDir;
mFilePicker->GetFile(getter_AddRefs(pickedDir));
#ifdef DEBUG
{
bool isDir;
pickedDir->IsDirectory(&isDir);
MOZ_ASSERT(isDir);
}
#endif
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), pickedDir);
nsCOMPtr<nsIEventTarget> target
= do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
NS_ASSERTION(target, "Must have stream transport service");
mInput->StartProgressEventTimer();
// DirPickerFileListBuilderTask takes care of calling SetFiles() and
// dispatching the "change" event.
mInput->mDirPickerFileListBuilderTask =
new DirPickerFileListBuilderTask(mInput.get(), pickedDir.get());
return target->Dispatch(mInput->mDirPickerFileListBuilderTask,
NS_DISPATCH_NORMAL);
}
// Collect new selected filenames
nsTArray<nsRefPtr<File>> newFiles;
if (mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)) {
@ -1164,7 +852,6 @@ HTMLInputElement::HTMLInputElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
, mCanShowInvalidUI(true)
, mHasRange(false)
, mIsDraggingRange(false)
, mProgressTimerIsActive(false)
, mNumberControlSpinnerIsSpinning(false)
, mNumberControlSpinnerSpinsUp(false)
, mPickerRunning(false)
@ -1268,7 +955,6 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLInputElement)
nsIImageLoadingContent,
imgIOnloadBlocker,
nsIDOMNSEditableElement,
nsITimerCallback,
nsIConstraintValidation)
NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLFormElementWithState)
@ -2785,58 +2471,6 @@ HTMLInputElement::GetFiles()
return mFileList;
}
void
HTMLInputElement::OpenDirectoryPicker(ErrorResult& aRv)
{
if (mType != NS_FORM_INPUT_FILE) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
}
InitFilePicker(FILE_PICKER_DIRECTORY);
}
void
HTMLInputElement::CancelDirectoryPickerScanIfRunning()
{
if (!mDirPickerFileListBuilderTask) {
return;
}
if (mProgressTimer) {
mProgressTimerIsActive = false;
mProgressTimer->Cancel();
}
mDirPickerFileListBuilderTask->Cancel();
mDirPickerFileListBuilderTask = nullptr;
}
void
HTMLInputElement::StartProgressEventTimer()
{
if (!mProgressTimer) {
mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
}
if (mProgressTimer) {
mProgressTimerIsActive = true;
mProgressTimer->Cancel();
mProgressTimer->InitWithCallback(this, kProgressEventInterval,
nsITimer::TYPE_ONE_SHOT);
}
}
// nsITimerCallback's only method
NS_IMETHODIMP
HTMLInputElement::Notify(nsITimer* aTimer)
{
if (mProgressTimer == aTimer) {
mProgressTimerIsActive = false;
MaybeDispatchProgressEvent(false);
return NS_OK;
}
// Just in case some JS user wants to QI to nsITimerCallback and play with us...
NS_WARNING("Unexpected timer!");
return NS_ERROR_INVALID_POINTER;
}
/* static */ void
HTMLInputElement::HandleNumberControlSpin(void* aData)
{
@ -2857,65 +2491,6 @@ HTMLInputElement::HandleNumberControlSpin(void* aData)
}
}
void
HTMLInputElement::MaybeDispatchProgressEvent(bool aFinalProgress)
{
nsRefPtr<HTMLInputElement> kungFuDeathGrip;
if (aFinalProgress && mProgressTimerIsActive) {
// mProgressTimer may hold the last reference to us, so take another strong
// ref to make sure we don't die under Cancel() and leave this method
// running on deleted memory.
kungFuDeathGrip = this;
mProgressTimerIsActive = false;
mProgressTimer->Cancel();
}
uint32_t fileListLength = mDirPickerFileListBuilderTask->GetFileListLength();
if (mProgressTimerIsActive ||
fileListLength == mDirPickerFileListBuilderTask->mPreviousFileListLength) {
return;
}
if (!aFinalProgress) {
StartProgressEventTimer();
}
mDirPickerFileListBuilderTask->mPreviousFileListLength = fileListLength;
DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR),
false,
mDirPickerFileListBuilderTask->mPreviousFileListLength,
0);
}
void
HTMLInputElement::DispatchProgressEvent(const nsAString& aType,
bool aLengthComputable,
uint64_t aLoaded, uint64_t aTotal)
{
NS_ASSERTION(!aType.IsEmpty(), "missing event type");
ProgressEventInit init;
init.mBubbles = false;
init.mCancelable = true; // XXXkhuey why?
init.mLengthComputable = aLengthComputable;
init.mLoaded = aLoaded;
init.mTotal = (aTotal == UINT64_MAX) ? 0 : aTotal;
nsRefPtr<ProgressEvent> event =
ProgressEvent::Constructor(this, aType, init);
event->SetTrusted(true);
bool doDefaultAction;
nsresult rv = DispatchEvent(event, &doDefaultAction);
if (NS_SUCCEEDED(rv) && !doDefaultAction) {
CancelDirectoryPickerScanIfRunning();
}
}
nsresult
HTMLInputElement::UpdateFileList()
{

View File

@ -36,7 +36,6 @@ class EventChainPreVisitor;
namespace dom {
class Date;
class DirPickerFileListBuilderTask;
class File;
class FileList;
@ -94,11 +93,8 @@ class HTMLInputElement final : public nsGenericHTMLFormElementWithState,
public nsITextControlElement,
public nsIPhonetic,
public nsIDOMNSEditableElement,
public nsITimerCallback,
public nsIConstraintValidation
{
friend class DirPickerFileListBuilderTask;
public:
using nsIConstraintValidation::GetValidationMessage;
using nsIConstraintValidation::CheckValidity;
@ -276,14 +272,6 @@ public:
return mSelectionProperties;
}
// nsITimerCallback
NS_DECL_NSITIMERCALLBACK
// Avoid warning about the implementation of nsITimerCallback::Notify hiding
// our nsImageLoadingContent base class' implementation of
// imgINotificationObserver::Notify:
using nsImageLoadingContent::Notify;
// nsIConstraintValidation
bool IsTooLong();
bool IsValueMissing() const;
@ -446,15 +434,6 @@ public:
FileList* GetFiles();
void OpenDirectoryPicker(ErrorResult& aRv);
void CancelDirectoryPickerScanIfRunning();
void StartProgressEventTimer();
void MaybeDispatchProgressEvent(bool aFinalProgress);
void DispatchProgressEvent(const nsAString& aType,
bool aLengthComputable,
uint64_t aLoaded, uint64_t aTotal);
// XPCOM GetFormAction() is OK
void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
{
@ -1276,8 +1255,6 @@ protected:
nsRefPtr<FileList> mFileList;
nsRefPtr<DirPickerFileListBuilderTask> mDirPickerFileListBuilderTask;
nsString mStaticDocFileList;
/**
@ -1296,13 +1273,6 @@ protected:
*/
Decimal mRangeThumbDragStartValue;
/**
* Timer that is used when mType == NS_FORM_INPUT_FILE and the user selects a
* directory. It is used to fire progress events while the list of files
* under that directory tree is built.
*/
nsCOMPtr<nsITimer> mProgressTimer;
/**
* The selection properties cache for number controls. This is needed because
* the number controls don't recycle their text field, so the normal cache in
@ -1346,7 +1316,6 @@ protected:
bool mCanShowInvalidUI : 1;
bool mHasRange : 1;
bool mIsDraggingRange : 1;
bool mProgressTimerIsActive : 1;
bool mNumberControlSpinnerIsSpinning : 1;
bool mNumberControlSpinnerSpinsUp : 1;
bool mPickerRunning : 1;

View File

@ -24,3 +24,4 @@ support-files =
[test_sync_edit.html]
[test_two_inputs.html]
[test_two_selects.html]
[test_unload.html]

View File

@ -0,0 +1,167 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1122463
https://bugzilla.mozilla.org/show_bug.cgi?id=820057
-->
<head>
<title>Test focus when page unloads</title>
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1122463">Mozilla Bug 1122463</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=820057">Mozilla Bug 820057</a>
<p id="display"></p>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
inputmethod_setup(function() {
runTest();
});
let appFrameScript = function appFrameScript() {
let form1 = content.document.body.firstElementChild;
let input1 = form1.firstElementChild;
let submit1 = form1.lastElementChild;
let input2;
let cancelSubmit = function(evt) {
evt.preventDefault();
};
// Content of the second page.
form1.action = 'data:text/html,<html><body><input value="Second"></body></html>';
let i = 1;
input1.focus();
addMessageListener('test:next', function() {
i++;
switch (i) {
case 2:
// Click the submit button, trigger the submit event and make our
// installed event listener preventing the submission.
form1.addEventListener('submit', cancelSubmit);
submit1.click();
sendAsyncMessage('test:step');
break;
case 3:
// Actually submit the form.
form1.removeEventListener('submit', cancelSubmit);
submit1.click();
break;
case 4:
if (!content.document.body) {
content.onload = function() {
content.onload = null;
let input2 = content.document.body.firstElementChild;
input2.focus();
};
return;
}
input2 = content.document.body.firstElementChild;
input2.focus();
break;
case 5:
content.location.href = 'data:text/html,Hello!';
break;
}
});
};
function runTest() {
let im = navigator.mozInputMethod;
let i = 0;
function nextStep() {
let inputcontext = navigator.mozInputMethod.inputcontext;
i++;
switch (i) {
// focus on the first input receives the first input context.
case 1:
ok(!!inputcontext, '1) Receving the first input context');
is(inputcontext.textAfterCursor, 'First');
mm.sendAsyncMessage('test:next');
break;
// Cancelled submission should not cause us lost focus.
case 2:
ok(!!inputcontext, '2) Receving the first input context');
is(inputcontext.textAfterCursor, 'First');
mm.sendAsyncMessage('test:next');
break;
// Real submit and page transition should cause us lost focus.
// XXX: Unless we could delay the page transition, we does not know if
// the inputcontext is lost because of the submit or the pagehide/beforeload
// event.
case 3:
is(inputcontext, null, '3) Receving null inputcontext');
mm.sendAsyncMessage('test:next');
break;
// Regaining focus of input in the second page.
case 4:
ok(!!inputcontext, '4) Receving the second input context');
is(inputcontext.textAfterCursor, 'Second');
mm.sendAsyncMessage('test:next');
break;
// Page transition should cause us lost focus
case 5:
is(inputcontext, null, '5) Receving null inputcontext');
inputmethod_cleanup();
break;
}
}
// Set current page as an input method.
SpecialPowers.wrap(im).setActive(true);
let iframe = document.createElement('iframe');
iframe.src = 'data:text/html,<html><body><form id="form"><input value="First"><input type="submit"></form></body></html>';
iframe.setAttribute('mozbrowser', true);
document.body.appendChild(iframe);
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
im.oninputcontextchange = nextStep;
let frameScriptLoaded = false;
iframe.addEventListener('mozbrowserloadend', function() {
if (frameScriptLoaded)
return;
frameScriptLoaded = true;
mm.addMessageListener('test:step', nextStep);
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
});
}
</script>
</pre>
</body>
</html>

View File

@ -46,7 +46,7 @@ PRLogModuleInfo* gTrackUnionStreamLog;
#define STREAM_LOG(type, msg) MOZ_LOG(gTrackUnionStreamLog, type, msg)
TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
ProcessedMediaStream(aWrapper)
ProcessedMediaStream(aWrapper), mNextAvailableTrackID(1)
{
if (!gTrackUnionStreamLog) {
gTrackUnionStreamLog = PR_NewLogModule("TrackUnionStream");
@ -161,23 +161,23 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
uint32_t TrackUnionStream::AddTrack(MediaInputPort* aPort, StreamBuffer::Track* aTrack,
GraphTime aFrom)
{
// Use the ID of the source track if it's not already assigned to a track,
// otherwise allocate a new unique ID.
TrackID id = aTrack->GetID();
TrackID maxTrackID = 0;
for (uint32_t i = 0; i < mTrackMap.Length(); ++i) {
TrackID outID = mTrackMap[i].mOutputTrackID;
maxTrackID = std::max(maxTrackID, outID);
}
// Note: we might have removed it here, but it might still be in the
// StreamBuffer if the TrackUnionStream sees its input stream flip from
// A to B, where both A and B have a track with the same ID
while (1) {
// search until we find one not in use here, and not in mBuffer
if (!mBuffer.FindTrack(id)) {
break;
if (id > mNextAvailableTrackID &&
mUsedTracks.BinaryIndexOf(id) == mUsedTracks.NoIndex) {
// Input id available. Mark it used in mUsedTracks.
mUsedTracks.InsertElementSorted(id);
} else {
// Input id taken, allocate a new one.
id = mNextAvailableTrackID;
// Update mNextAvailableTrackID and prune any mUsedTracks members it now
// covers.
while (1) {
if (!mUsedTracks.RemoveElementSorted(++mNextAvailableTrackID)) {
// Not in use. We're done.
break;
}
}
id = ++maxTrackID;
}
// Round up the track start time so the track, if anything, starts a

View File

@ -50,6 +50,8 @@ protected:
nsAutoPtr<MediaSegment> mSegment;
};
// Add the track to this stream, retaining its TrackID if it has never
// been previously used in this stream, allocating a new TrackID otherwise.
uint32_t AddTrack(MediaInputPort* aPort, StreamBuffer::Track* aTrack,
GraphTime aFrom);
void EndTrack(uint32_t aIndex);
@ -58,6 +60,13 @@ protected:
bool* aOutputTrackFinished);
nsTArray<TrackMapEntry> mTrackMap;
// The next available TrackID, starting at 1 and progressing upwards.
// All TrackIDs in [1, mNextAvailableTrackID) have implicitly been used.
TrackID mNextAvailableTrackID;
// Sorted array of used TrackIDs that require manual tracking.
nsTArray<TrackID> mUsedTracks;
};
}

View File

@ -13,6 +13,7 @@
#include "GMPService.h"
#include "VideoUtils.h"
#include "nsPrintfCString.h"
#include "nsXULAppAPI.h"
namespace mozilla {
namespace dom {
@ -492,6 +493,12 @@ GMPVideoDecoderTrialCreator::MaybeAwaitTrialCreate(const nsAString& aKeySystem,
{
MOZ_ASSERT(NS_IsMainThread());
if (XRE_GetProcessType() == GeckoProcessType_Content) {
// Currently broken with e10s...
aPromisey->Resolve();
return;
}
if (!mTestCreate.Contains(aKeySystem)) {
mTestCreate.Put(aKeySystem, new TrialCreateData(aKeySystem));
}

View File

@ -251,6 +251,9 @@ CSPService::ShouldProcess(uint32_t aContentType,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
if (!aContentLocation)
return NS_ERROR_FAILURE;

View File

@ -787,6 +787,9 @@ nsMixedContentBlocker::ShouldProcess(uint32_t aContentType,
nsIPrincipal* aRequestPrincipal,
int16_t* aDecision)
{
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
if (!aContentLocation) {
// aContentLocation may be null when a plugin is loading without an associated URI resource
if (aContentType == TYPE_OBJECT) {

View File

@ -40,8 +40,6 @@ interface HTMLInputElement : HTMLElement {
readonly attribute HTMLFormElement? form;
[Pure]
readonly attribute FileList? files;
[Throws, Pref="dom.input.dirpicker"]
void openDirectoryPicker();
[Pure, SetterThrows]
attribute DOMString formAction;
[Pure, SetterThrows]

View File

@ -34,6 +34,9 @@ nsWebBrowserContentPolicy::ShouldLoad(uint32_t aContentType,
{
NS_PRECONDITION(aShouldLoad, "Null out param");
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
*aShouldLoad = nsIContentPolicy::ACCEPT;
nsIDocShell* shell = NS_CP_GetDocShellFromContext(aRequestingContext);
@ -84,6 +87,9 @@ nsWebBrowserContentPolicy::ShouldProcess(uint32_t aContentType,
{
NS_PRECONDITION(aShouldProcess, "Null out param");
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
*aShouldProcess = nsIContentPolicy::ACCEPT;
// Object tags will always open channels with TYPE_OBJECT, but may end up

View File

@ -14,6 +14,7 @@
#include "nsContentPolicyUtils.h"
#include "nsIObjectLoadingContent.h"
#include "mozilla/ArrayUtils.h"
#include "nsContentUtils.h"
// Possible behavior pref values
// Those map to the nsIPermissionManager values where possible
@ -150,6 +151,9 @@ nsContentBlocker::ShouldLoad(uint32_t aContentType,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
*aDecision = nsIContentPolicy::ACCEPT;
nsresult rv;
@ -201,6 +205,9 @@ nsContentBlocker::ShouldProcess(uint32_t aContentType,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
// For loads where aRequestingContext is chrome, we should just
// accept. Those are most likely toplevel loads in windows, and
// chrome generally knows what it's doing anyway.

View File

@ -204,7 +204,10 @@ private:
// mListener is only promised to be a weak ref (see imgILoader.idl),
// but we actually keep a strong ref to it until we've seen our
// first OnStopRequest.
imgINotificationObserver* mListener;
imgINotificationObserver* MOZ_UNSAFE_REF("Observers must call Cancel() or "
"CancelAndForgetObserver() before "
"they are destroyed") mListener;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsLoadFlags mLoadFlags;

View File

@ -32,6 +32,7 @@
#endif
#ifdef MOZ_TASK_TRACER
#include "GeckoTaskTracer.h"
#include "TracedTaskCommon.h"
#endif
#include "MessagePump.h"
@ -287,6 +288,7 @@ void MessageLoop::PostIdleTask(
#ifdef MOZ_TASK_TRACER
task = mozilla::tasktracer::CreateTracedTask(task);
(static_cast<mozilla::tasktracer::TracedTask*>(task))->DispatchTask();
#endif
task->SetBirthPlace(from_here);
@ -301,6 +303,7 @@ void MessageLoop::PostTask_Helper(
#ifdef MOZ_TASK_TRACER
task = mozilla::tasktracer::CreateTracedTask(task);
(static_cast<mozilla::tasktracer::TracedTask*>(task))->DispatchTask(delay_ms);
#endif
task->SetBirthPlace(from_here);

View File

@ -1168,7 +1168,10 @@ class MOZ_STACK_CLASS ModuleCompiler
uint32_t funcIndex_;
uint32_t funcPtrTableIndex_;
uint32_t ffiIndex_;
Scalar::Type viewType_;
struct {
Scalar::Type viewType_;
bool isSharedView_;
} viewInfo;
AsmJSMathBuiltinFunction mathBuiltinFunc_;
AsmJSAtomicsBuiltinFunction atomicsBuiltinFunc_;
AsmJSSimdType simdCtorType_;
@ -1223,7 +1226,11 @@ class MOZ_STACK_CLASS ModuleCompiler
}
Scalar::Type viewType() const {
MOZ_ASSERT(isAnyArrayView());
return u.viewType_;
return u.viewInfo.viewType_;
}
bool viewIsSharedView() const {
MOZ_ASSERT(isAnyArrayView());
return u.viewInfo.isSharedView_;
}
bool isMathFunction() const {
return which_ == MathBuiltinFunction;
@ -1800,7 +1807,8 @@ class MOZ_STACK_CLASS ModuleCompiler
return false;
if (!module_->addArrayView(vt, maybeField, isSharedView))
return false;
global->u.viewType_ = vt;
global->u.viewInfo.viewType_ = vt;
global->u.viewInfo.isSharedView_ = isSharedView;
return globals_.putNew(varName, global);
}
bool addArrayViewCtor(PropertyName* varName, Scalar::Type vt, PropertyName* fieldName, bool isSharedView) {
@ -1809,7 +1817,8 @@ class MOZ_STACK_CLASS ModuleCompiler
return false;
if (!module_->addArrayViewCtor(vt, fieldName, isSharedView))
return false;
global->u.viewType_ = vt;
global->u.viewInfo.viewType_ = vt;
global->u.viewInfo.isSharedView_ = isSharedView;
return globals_.putNew(varName, global);
}
bool addMathBuiltinFunction(PropertyName* varName, AsmJSMathBuiltinFunction func, PropertyName* fieldName) {
@ -3981,6 +3990,7 @@ CheckNewArrayView(ModuleCompiler& m, PropertyName* varName, ParseNode* newExpr)
field = nullptr;
type = global->viewType();
shared = global->viewIsSharedView();
}
if (!CheckNewArrayViewArgs(m, ctorExpr, bufferName))
@ -9227,6 +9237,11 @@ CheckModule(ExclusiveContext* cx, AsmJSParser& parser, ParseNode* stmtList,
m.startFunctionBodies();
#if !defined(ENABLE_SHARED_ARRAY_BUFFER)
if (m.module().hasArrayView() && m.module().isSharedView())
return m.fail(nullptr, "shared views not supported by this build");
#endif
if (!CheckFunctions(m))
return false;

View File

@ -0,0 +1,69 @@
// Check gating of shared memory features in asm.js (bug 1171540).
//
// When run with -w this should produce a slew of warnings if shared
// memory is not enabled. There are several cases here because there
// are various checks within Odin.
//
// Note code is not run, so the only issue here is whether it compiles
// properly as asm.js.
if (!isAsmJSCompilationAvailable())
quit(0);
function module_a(stdlib, foreign, heap) {
"use asm";
// Without shared memory, this will be flagged as illegal view type
var view = stdlib.SharedInt32Array;
var i32a = new view(heap);
var ld = stdlib.Atomics.load;
function do_load() {
var v = 0;
v = ld(i32a, 0)|0;
return v|0;
}
return { load: do_load };
}
if (this.SharedArrayBuffer)
assertEq(isAsmJSModule(module_a), true);
function module_b(stdlib, foreign, heap) {
"use asm";
// Without shared memory, this will be flagged as illegal view type
var i32a = new stdlib.SharedInt32Array(heap);
var ld = stdlib.Atomics.load;
function do_load() {
var v = 0;
v = ld(i32a, 0)|0;
return v|0;
}
return { load: do_load };
}
if (this.SharedArrayBuffer)
assertEq(isAsmJSModule(module_b), true);
function module_d(stdlib, foreign, heap) {
"use asm";
var i32a = new stdlib.Int32Array(heap);
var ld = stdlib.Atomics.load;
function do_load() {
var v = 0;
// This should be flagged as a type error (needs shared view) regardless
// of whether shared memory is enabled.
v = ld(i32a, 0)|0;
return v|0;
}
return { load: do_load };
}
// module_d should never load properly.

View File

@ -681,42 +681,85 @@ ErrorReport::~ErrorReport()
js_free(const_cast<char16_t*>(ownedReport.ucmessage));
}
void
ErrorReport::ReportAddonExceptionToTelementry(JSContext* cx)
{
MOZ_ASSERT(exnObject);
RootedObject unwrapped(cx, UncheckedUnwrap(exnObject));
MOZ_ASSERT(unwrapped, "UncheckedUnwrap failed?");
// There is not much we can report if the exception is not an ErrorObject, let's ignore those.
if (!unwrapped->is<ErrorObject>())
return;
Rooted<ErrorObject*> errObj(cx, &unwrapped->as<ErrorObject>());
RootedObject stack(cx, errObj->stack());
// Let's ignore TOP level exceptions. For regular add-ons those will not be reported anyway,
// for SDK based once it should not be a valid case either.
// At this point the frame stack is unwound but the exception object stored the stack so let's
// use that for getting the function name.
if (!stack)
return;
JSCompartment* comp = stack->compartment();
JSAddonId* addonId = comp->addonId;
// We only want to send the report if the scope that just have thrown belongs to an add-on.
// Let's check the compartment of the youngest function on the stack, to determine that.
if (!addonId)
return;
RootedString funnameString(cx);
JS::SavedFrameResult result = GetSavedFrameFunctionDisplayName(cx, stack, &funnameString);
// AccessDenied should never be the case here for add-ons but let's not risk it.
JSAutoByteString bytes;
const char* funname = nullptr;
bool denied = result == JS::SavedFrameResult::AccessDenied;
funname = denied ? "unknown"
: funnameString ? AtomToPrintableString(cx,
&funnameString->asAtom(),
&bytes)
: "anonymous";
UniqueChars addonIdChars(JS_EncodeString(cx, addonId));
const char* filename = nullptr;
if (reportp && reportp->filename) {
filename = strrchr(reportp->filename, '/');
if (filename)
filename++;
}
if (!filename) {
filename = "FILE_NOT_FOUND";
}
char histogramKey[64];
JS_snprintf(histogramKey, sizeof(histogramKey),
"%s %s %s %u",
addonIdChars.get(),
funname,
filename,
(reportp ? reportp->lineno : 0) );
cx->runtime()->addTelemetry(JS_TELEMETRY_ADDON_EXCEPTIONS, 1, histogramKey);
}
bool
ErrorReport::init(JSContext* cx, HandleValue exn)
{
MOZ_ASSERT(!cx->isExceptionPending());
/*
* Because ToString below could error and an exception object could become
* unrooted, we must root our exception object, if any.
*/
if (exn.isObject()) {
// Because ToString below could error and an exception object could become
// unrooted, we must root our exception object, if any.
exnObject = &exn.toObject();
reportp = ErrorFromException(cx, exnObject);
JSCompartment* comp = exnObject->compartment();
JSAddonId* addonId = comp->addonId;
if (addonId) {
UniqueChars addonIdChars(JS_EncodeString(cx, addonId));
const char* filename = nullptr;
if (reportp && reportp->filename) {
filename = strrchr(reportp->filename, '/');
if (filename)
filename++;
}
if (!filename) {
filename = "FILE_NOT_FOUND";
}
char histogramKey[64];
JS_snprintf(histogramKey, sizeof(histogramKey),
"%s %s %u",
addonIdChars.get(),
filename,
(reportp ? reportp->lineno : 0) );
cx->runtime()->addTelemetry(JS_TELEMETRY_ADDON_EXCEPTIONS, 1, histogramKey);
}
// Let's see if the exception is from add-on code, if so, it should be reported
// to telementry.
ReportAddonExceptionToTelementry(cx);
}
// Be careful not to invoke ToString if we've already successfully extracted
// an error report, since the exception might be wrapped in a security
// wrapper, and ToString-ing it might throw.

View File

@ -1396,6 +1396,9 @@ struct MOZ_STACK_CLASS JS_FRIEND_API(ErrorReport)
bool populateUncaughtExceptionReport(JSContext* cx, ...);
bool populateUncaughtExceptionReportVA(JSContext* cx, va_list ap);
// Reports exceptions from add-on scopes to telementry.
void ReportAddonExceptionToTelementry(JSContext* cx);
// We may have a provided JSErrorReport, so need a way to represent that.
JSErrorReport* reportp;

View File

@ -4319,45 +4319,186 @@ GetIntrinsicCoord(const nsStyleCoord& aStyle,
static int32_t gNoiseIndent = 0;
#endif
/**
* Add aOffsets which describes what to add on outside of the content box
* aContentSize (controlled by 'box-sizing') and apply min/max properties.
* We have to account for these properties after getting all the offsets
* (margin, border, padding) because percentages do not operate linearly.
* Doing this is ok because although percentages aren't handled linearly,
* they are handled monotonically.
*
* @param aContentSize the content size calculated so far
(@see IntrinsicForContainer)
* @param aContentMinSize ditto min content size
* @param aStyleSize a 'width' or 'height' property value
* @param aFixedMinSize if aStyleMinSize is a definite size then this points to
* the value, otherwise nullptr
* @param aStyleMinSize a 'min-width' or 'min-height' property value
* @param aFixedMaxSize if aStyleMaxSize is a definite size then this points to
* the value, otherwise nullptr
* @param aStyleMaxSize a 'max-width' or 'max-height' property value
* @param aFlags same as for IntrinsicForContainer
* @param aContainerWM the container's WM
*/
static nscoord
AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
const nsIFrame::IntrinsicISizeOffsetData& aOffsets,
nsLayoutUtils::IntrinsicISizeType aType,
uint8_t aBoxSizing,
nscoord aContentSize,
nscoord aContentMinSize,
const nsStyleCoord& aStyleSize,
const nscoord* aFixedMinSize,
const nsStyleCoord& aStyleMinSize,
const nscoord* aFixedMaxSize,
const nsStyleCoord& aStyleMaxSize,
uint32_t aFlags,
PhysicalAxis aAxis)
{
nscoord result = aContentSize;
nscoord min = aContentMinSize;
nscoord coordOutsideSize = 0;
float pctOutsideSize = 0;
float pctTotal = 0.0f;
if (!(aFlags & nsLayoutUtils::IGNORE_PADDING)) {
coordOutsideSize += aOffsets.hPadding;
pctOutsideSize += aOffsets.hPctPadding;
if (aBoxSizing == NS_STYLE_BOX_SIZING_PADDING) {
min += coordOutsideSize;
result = NSCoordSaturatingAdd(result, coordOutsideSize);
pctTotal += pctOutsideSize;
coordOutsideSize = 0;
pctOutsideSize = 0.0f;
}
}
coordOutsideSize += aOffsets.hBorder;
if (aBoxSizing == NS_STYLE_BOX_SIZING_BORDER) {
min += coordOutsideSize;
result = NSCoordSaturatingAdd(result, coordOutsideSize);
pctTotal += pctOutsideSize;
coordOutsideSize = 0;
pctOutsideSize = 0.0f;
}
coordOutsideSize += aOffsets.hMargin;
pctOutsideSize += aOffsets.hPctMargin;
min += coordOutsideSize;
result = NSCoordSaturatingAdd(result, coordOutsideSize);
pctTotal += pctOutsideSize;
nscoord size;
if (GetAbsoluteCoord(aStyleSize, size) ||
GetIntrinsicCoord(aStyleSize, aRenderingContext, aFrame,
PROP_WIDTH, size)) {
result = AddPercents(aType, size + coordOutsideSize, pctOutsideSize);
} else if (aType == nsLayoutUtils::MIN_ISIZE &&
// The only cases of coord-percent-calc() units that
// GetAbsoluteCoord didn't handle are percent and calc()s
// containing percent.
aStyleSize.IsCoordPercentCalcUnit() &&
aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
// A percentage width on replaced elements means they can shrink to 0.
result = 0; // let |min| handle padding/border/margin
} else {
// NOTE: We could really do a lot better for percents and for some
// cases of calc() containing percent (certainly including any where
// the coefficient on the percent is positive and there are no max()
// expressions). However, doing better for percents wouldn't be
// backwards compatible.
result = AddPercents(aType, result, pctTotal);
}
nscoord maxSize = aFixedMaxSize ? *aFixedMaxSize : 0;
if (aFixedMaxSize ||
GetIntrinsicCoord(aStyleMaxSize, aRenderingContext, aFrame,
PROP_MAX_WIDTH, maxSize)) {
maxSize = AddPercents(aType, maxSize + coordOutsideSize, pctOutsideSize);
if (result > maxSize) {
result = maxSize;
}
}
nscoord minSize = aFixedMinSize ? *aFixedMinSize : 0;
if (aFixedMinSize ||
GetIntrinsicCoord(aStyleMinSize, aRenderingContext, aFrame,
PROP_MIN_WIDTH, minSize)) {
minSize = AddPercents(aType, minSize + coordOutsideSize, pctOutsideSize);
if (result < minSize) {
result = minSize;
}
}
min = AddPercents(aType, min, pctTotal);
if (result < min) {
result = min;
}
const nsStyleDisplay* disp = aFrame->StyleDisplay();
if (aFrame->IsThemed(disp)) {
LayoutDeviceIntSize devSize;
bool canOverride = true;
nsPresContext* pc = aFrame->PresContext();
pc->GetTheme()->GetMinimumWidgetSize(pc, aFrame, disp->mAppearance,
&devSize, &canOverride);
nscoord themeSize =
pc->DevPixelsToAppUnits(aAxis == eAxisVertical ? devSize.height
: devSize.width);
// GetMinimumWidgetSize() returns a border-box width.
themeSize += aOffsets.hMargin;
themeSize = AddPercents(aType, themeSize, aOffsets.hPctMargin);
if (themeSize > result || !canOverride) {
result = themeSize;
}
}
return result;
}
/* static */ nscoord
nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
nsIFrame *aFrame,
IntrinsicISizeType aType,
uint32_t aFlags)
nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
IntrinsicISizeType aType,
uint32_t aFlags)
{
NS_PRECONDITION(aFrame, "null frame");
NS_PRECONDITION(aFrame->GetParent(),
"IntrinsicForContainer called on frame not in tree");
"IntrinsicForAxis called on frame not in tree");
NS_PRECONDITION(aType == MIN_ISIZE || aType == PREF_ISIZE, "bad type");
const bool horizontalAxis = MOZ_LIKELY(aAxis == eAxisHorizontal);
#ifdef DEBUG_INTRINSIC_WIDTH
nsFrame::IndentBy(stderr, gNoiseIndent);
static_cast<nsFrame*>(aFrame)->ListTag(stderr);
printf_stderr(" %s intrinsic inline-size for container:\n",
aType == MIN_ISIZE ? "min" : "pref");
printf_stderr(" %s %s intrinsic size for container:\n",
aType == MIN_ISIZE ? "min" : "pref",
horizontalAxis ? "horizontal" : "vertical");
#endif
// If aFrame is a container for font size inflation, then shrink
// wrapping inside of it should not apply font size inflation.
AutoMaybeDisableFontInflation an(aFrame);
nsIFrame::IntrinsicISizeOffsetData offsets =
aFrame->IntrinsicISizeOffsets(aRenderingContext);
// We want the size this frame will contribute to the parent's inline-size,
// so we work in the parent's writing mode; but if aFrame is orthogonal to
// its parent, we'll need to look at its BSize instead of min/pref-ISize.
WritingMode wm = aFrame->GetParent()->GetWritingMode();
WritingMode ourWM = aFrame->GetWritingMode();
bool isOrthogonal = ourWM.IsOrthogonalTo(wm);
bool isVertical = wm.IsVertical();
const nsStylePosition *stylePos = aFrame->StylePosition();
const nsStylePosition* stylePos = aFrame->StylePosition();
uint8_t boxSizing = stylePos->mBoxSizing;
const nsStyleCoord& styleISize = stylePos->ISize(wm);
const nsStyleCoord& styleMinISize = stylePos->MinISize(wm);
const nsStyleCoord& styleMaxISize = stylePos->MaxISize(wm);
const nsStyleCoord& styleISize =
horizontalAxis ? stylePos->mWidth : stylePos->mHeight;
const nsStyleCoord& styleMinISize =
horizontalAxis ? stylePos->mMinWidth : stylePos->mMinHeight;
const nsStyleCoord& styleMaxISize =
horizontalAxis ? stylePos->mMaxWidth : stylePos->mMaxHeight;
// We build up two values starting with the content box, and then
// adding padding, border and margin. The result is normally
@ -4388,6 +4529,8 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
haveFixedMinISize = GetAbsoluteCoord(styleMinISize, minISize);
}
PhysicalAxis ourInlineAxis =
aFrame->GetWritingMode().PhysicalAxis(eLogicalAxisInline);
// If we have a specified width (or a specified 'min-width' greater
// than the specified 'max-width', which works out to the same thing),
// don't even bother getting the frame's intrinsic width, because in
@ -4406,9 +4549,8 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
#ifdef DEBUG_INTRINSIC_WIDTH
++gNoiseIndent;
#endif
if (isOrthogonal) {
// We need aFrame's block-dir size, which will become its inline-size
// contribution in the container.
if (MOZ_UNLIKELY(aAxis != ourInlineAxis)) {
// We need aFrame's block-dir size.
// XXX Unfortunately, we probably don't know this yet, so this is wrong...
// but it's not clear what we should do. If aFrame's inline size hasn't
// been determined yet, we can't necessarily figure out its block size
@ -4426,8 +4568,10 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
--gNoiseIndent;
nsFrame::IndentBy(stderr, gNoiseIndent);
static_cast<nsFrame*>(aFrame)->ListTag(stderr);
printf_stderr(" %s intrinsic inline-size from frame is %d.\n",
aType == MIN_ISIZE ? "min" : "pref", result);
printf_stderr(" %s %s intrinsic size from frame is %d.\n",
aType == MIN_ISIZE ? "min" : "pref",
horizontalAxis ? "horizontal" : "vertical",
result);
#endif
// Handle elements with an intrinsic ratio (or size) and a specified
@ -4436,9 +4580,12 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
// since that's what it means in all cases except for on flex items -- and
// even there, we're supposed to ignore it (i.e. treat it as 0) until the
// flex container explicitly considers it.
const nsStyleCoord& styleBSize = stylePos->BSize(wm);
const nsStyleCoord& styleMinBSize = stylePos->MinBSize(wm);
const nsStyleCoord& styleMaxBSize = stylePos->MaxBSize(wm);
const nsStyleCoord& styleBSize =
horizontalAxis ? stylePos->mHeight : stylePos->mWidth;
const nsStyleCoord& styleMinBSize =
horizontalAxis ? stylePos->mMinHeight : stylePos->mMinWidth;
const nsStyleCoord& styleMaxBSize =
horizontalAxis ? stylePos->mMaxHeight : stylePos->mMaxWidth;
if (styleBSize.GetUnit() != eStyleUnit_Auto ||
!(styleMinBSize.GetUnit() == eStyleUnit_Auto ||
@ -4446,24 +4593,27 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
styleMinBSize.GetCoordValue() == 0)) ||
styleMaxBSize.GetUnit() != eStyleUnit_None) {
LogicalSize ratio(wm, aFrame->GetIntrinsicRatio());
if (ratio.BSize(wm) != 0) {
nsSize ratio(aFrame->GetIntrinsicRatio());
nscoord ratioISize = (horizontalAxis ? ratio.width : ratio.height);
nscoord ratioBSize = (horizontalAxis ? ratio.height : ratio.width);
if (ratioBSize != 0) {
nscoord bSizeTakenByBoxSizing = 0;
switch (boxSizing) {
case NS_STYLE_BOX_SIZING_BORDER: {
const nsStyleBorder* styleBorder = aFrame->StyleBorder();
bSizeTakenByBoxSizing +=
wm.IsVertical() ? styleBorder->GetComputedBorder().LeftRight()
: styleBorder->GetComputedBorder().TopBottom();
horizontalAxis ? styleBorder->GetComputedBorder().TopBottom()
: styleBorder->GetComputedBorder().LeftRight();
// fall through
}
case NS_STYLE_BOX_SIZING_PADDING: {
if (!(aFlags & IGNORE_PADDING)) {
const nsStyleSides& stylePadding =
aFrame->StylePadding()->mPadding;
const nsStyleCoord& paddingStart = stylePadding.GetBStart(wm);
const nsStyleCoord& paddingEnd = stylePadding.GetBEnd(wm);
const nsStyleCoord& paddingStart =
stylePadding.Get(horizontalAxis ? NS_SIDE_TOP : NS_SIDE_LEFT);
const nsStyleCoord& paddingEnd =
stylePadding.Get(horizontalAxis ? NS_SIDE_BOTTOM : NS_SIDE_RIGHT);
nscoord pad;
if (GetAbsoluteCoord(paddingStart, pad) ||
GetPercentBSize(paddingStart, aFrame, pad)) {
@ -4485,13 +4635,13 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
if (GetAbsoluteCoord(styleBSize, h) ||
GetPercentBSize(styleBSize, aFrame, h)) {
h = std::max(0, h - bSizeTakenByBoxSizing);
result = NSCoordMulDiv(h, ratio.ISize(wm), ratio.BSize(wm));
result = NSCoordMulDiv(h, ratioISize, ratioBSize);
}
if (GetAbsoluteCoord(styleMaxBSize, h) ||
GetPercentBSize(styleMaxBSize, aFrame, h)) {
h = std::max(0, h - bSizeTakenByBoxSizing);
nscoord maxISize = NSCoordMulDiv(h, ratio.ISize(wm), ratio.BSize(wm));
nscoord maxISize = NSCoordMulDiv(h, ratioISize, ratioBSize);
if (maxISize < result)
result = maxISize;
}
@ -4499,7 +4649,7 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
if (GetAbsoluteCoord(styleMinBSize, h) ||
GetPercentBSize(styleMinBSize, aFrame, h)) {
h = std::max(0, h - bSizeTakenByBoxSizing);
nscoord minISize = NSCoordMulDiv(h, ratio.ISize(wm), ratio.BSize(wm));
nscoord minISize = NSCoordMulDiv(h, ratioISize, ratioBSize);
if (minISize > result)
result = minISize;
}
@ -4513,124 +4663,42 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
min = aFrame->GetMinISize(aRenderingContext);
}
// We also need to track what has been added on outside of the box
// (controlled by 'box-sizing') where 'width', 'min-width' and
// 'max-width' are applied. We have to account for these properties
// after getting all the offsets (margin, border, padding) because
// percentages do not operate linearly.
// Doing this is ok because although percentages aren't handled
// linearly, they are handled monotonically.
nscoord coordOutsideISize = 0;
float pctOutsideISize = 0;
float pctTotal = 0.0f;
if (!(aFlags & IGNORE_PADDING)) {
coordOutsideISize += offsets.hPadding;
pctOutsideISize += offsets.hPctPadding;
if (boxSizing == NS_STYLE_BOX_SIZING_PADDING) {
min += coordOutsideISize;
result = NSCoordSaturatingAdd(result, coordOutsideISize);
pctTotal += pctOutsideISize;
coordOutsideISize = 0;
pctOutsideISize = 0.0f;
}
}
coordOutsideISize += offsets.hBorder;
if (boxSizing == NS_STYLE_BOX_SIZING_BORDER) {
min += coordOutsideISize;
result = NSCoordSaturatingAdd(result, coordOutsideISize);
pctTotal += pctOutsideISize;
coordOutsideISize = 0;
pctOutsideISize = 0.0f;
}
coordOutsideISize += offsets.hMargin;
pctOutsideISize += offsets.hPctMargin;
min += coordOutsideISize;
result = NSCoordSaturatingAdd(result, coordOutsideISize);
pctTotal += pctOutsideISize;
nscoord w;
if (GetAbsoluteCoord(styleISize, w) ||
GetIntrinsicCoord(styleISize, aRenderingContext, aFrame,
PROP_WIDTH, w)) {
result = AddPercents(aType, w + coordOutsideISize, pctOutsideISize);
}
else if (aType == MIN_ISIZE &&
// The only cases of coord-percent-calc() units that
// GetAbsoluteCoord didn't handle are percent and calc()s
// containing percent.
styleISize.IsCoordPercentCalcUnit() &&
aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
// A percentage width on replaced elements means they can shrink to 0.
result = 0; // let |min| handle padding/border/margin
}
else {
// NOTE: We could really do a lot better for percents and for some
// cases of calc() containing percent (certainly including any where
// the coefficient on the percent is positive and there are no max()
// expressions). However, doing better for percents wouldn't be
// backwards compatible.
result = AddPercents(aType, result, pctTotal);
}
if (haveFixedMaxISize ||
GetIntrinsicCoord(styleMaxISize, aRenderingContext, aFrame,
PROP_MAX_WIDTH, maxISize)) {
maxISize = AddPercents(aType, maxISize + coordOutsideISize, pctOutsideISize);
if (result > maxISize)
result = maxISize;
}
if (haveFixedMinISize ||
GetIntrinsicCoord(styleMinISize, aRenderingContext, aFrame,
PROP_MIN_WIDTH, minISize)) {
minISize = AddPercents(aType, minISize + coordOutsideISize, pctOutsideISize);
if (result < minISize)
result = minISize;
}
min = AddPercents(aType, min, pctTotal);
if (result < min)
result = min;
const nsStyleDisplay *disp = aFrame->StyleDisplay();
if (aFrame->IsThemed(disp)) {
LayoutDeviceIntSize size;
bool canOverride = true;
nsPresContext *presContext = aFrame->PresContext();
presContext->GetTheme()->
GetMinimumWidgetSize(presContext, aFrame, disp->mAppearance,
&size, &canOverride);
nscoord themeISize =
presContext->DevPixelsToAppUnits(isVertical ? size.height : size.width);
// GMWS() returns a border-box width
themeISize += offsets.hMargin;
themeISize = AddPercents(aType, themeISize, offsets.hPctMargin);
if (themeISize > result || !canOverride) {
result = themeISize;
}
}
nsIFrame::IntrinsicISizeOffsetData offsets =
MOZ_LIKELY(aAxis == ourInlineAxis) ? aFrame->IntrinsicISizeOffsets()
: aFrame->IntrinsicBSizeOffsets();
result = AddIntrinsicSizeOffset(aRenderingContext, aFrame, offsets, aType,
boxSizing, result, min, styleISize,
haveFixedMinISize ? &minISize : nullptr,
styleMinISize,
haveFixedMaxISize ? &maxISize : nullptr,
styleMaxISize,
aFlags, aAxis);
#ifdef DEBUG_INTRINSIC_WIDTH
nsFrame::IndentBy(stderr, gNoiseIndent);
static_cast<nsFrame*>(aFrame)->ListTag(stderr);
printf_stderr(" %s intrinsic inline-size for container is %d twips.\n",
aType == MIN_ISIZE ? "min" : "pref", result);
printf_stderr(" %s %s intrinsic size for container is %d twips.\n",
aType == MIN_ISIZE ? "min" : "pref",
horizontalAxis ? "horizontal" : "vertical",
result);
#endif
return result;
}
/* static */ nscoord
nsLayoutUtils::IntrinsicForContainer(nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
IntrinsicISizeType aType,
uint32_t aFlags)
{
MOZ_ASSERT(aFrame && aFrame->GetParent());
// We want the size aFrame will contribute to its parent's inline-size.
PhysicalAxis axis =
aFrame->GetParent()->GetWritingMode().PhysicalAxis(eLogicalAxisInline);
return IntrinsicForAxis(axis, aRenderingContext, aFrame, aType, aFlags);
}
/* static */ nscoord
nsLayoutUtils::ComputeCBDependentValue(nscoord aPercentBasis,
const nsStyleCoord& aCoord)

View File

@ -1299,18 +1299,27 @@ public:
/**
* Get the contribution of aFrame to its containing block's intrinsic
* width. This considers the child's intrinsic width, its 'width',
* 'min-width', and 'max-width' properties, and its padding, border,
* and margin.
* size for the given physical axis. This considers the child's intrinsic
* width, its 'width', 'min-width', and 'max-width' properties (or 'height'
* variations if that's what matches aAxis) and its padding, border and margin
* in the corresponding dimension.
*/
enum IntrinsicISizeType { MIN_ISIZE, PREF_ISIZE };
enum {
IGNORE_PADDING = 0x01
};
static nscoord IntrinsicForAxis(mozilla::PhysicalAxis aAxis,
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
IntrinsicISizeType aType,
uint32_t aFlags = 0);
/**
* Calls IntrinsicForAxis with aFrame's parent's inline physical axis.
*/
static nscoord IntrinsicForContainer(nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
IntrinsicISizeType aType,
uint32_t aFlags = 0);
nsIFrame* aFrame,
IntrinsicISizeType aType,
uint32_t aFlags = 0);
/*
* Convert nsStyleCoord to nscoord when percentages depend on the

View File

@ -6942,11 +6942,11 @@ PresShell::HandleEvent(nsIFrame* aFrame,
// Make touch events, mouse events and hardware key events to be the source
// events of TaskTracer, and originate the rest correlation tasks from here.
SourceEventType type = SourceEventType::Unknown;
if (WidgetTouchEvent* inputEvent = aEvent->AsTouchEvent()) {
if (aEvent->AsTouchEvent()) {
type = SourceEventType::Touch;
} else if (WidgetMouseEvent* inputEvent = aEvent->AsMouseEvent()) {
} else if (aEvent->AsMouseEvent()) {
type = SourceEventType::Mouse;
} else if (WidgetKeyboardEvent* inputEvent = aEvent->AsKeyboardEvent()) {
} else if (aEvent->AsKeyboardEvent()) {
type = SourceEventType::Key;
}
AutoSourceEvent taskTracerEvent(type);

View File

@ -4055,7 +4055,6 @@ nsIFrame::InlinePrefISizeData::ForceBreak(nsRenderingContext *aRenderingContext)
static void
AddCoord(const nsStyleCoord& aStyle,
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
nscoord* aCoord, float* aPercent,
bool aClampNegativeToZero)
@ -4091,65 +4090,78 @@ AddCoord(const nsStyleCoord& aStyle,
}
}
/* virtual */ nsIFrame::IntrinsicISizeOffsetData
nsFrame::IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext)
static nsIFrame::IntrinsicISizeOffsetData
IntrinsicSizeOffsets(nsIFrame* aFrame, bool aForISize)
{
IntrinsicISizeOffsetData result;
WritingMode wm = GetWritingMode();
const nsStyleMargin *styleMargin = StyleMargin();
AddCoord(wm.IsVertical() ? styleMargin->mMargin.GetTop()
: styleMargin->mMargin.GetLeft(),
aRenderingContext, this, &result.hMargin, &result.hPctMargin,
nsIFrame::IntrinsicISizeOffsetData result;
WritingMode wm = aFrame->GetWritingMode();
const nsStyleMargin* styleMargin = aFrame->StyleMargin();
bool verticalAxis = aForISize == wm.IsVertical();
AddCoord(verticalAxis ? styleMargin->mMargin.GetTop()
: styleMargin->mMargin.GetLeft(),
aFrame, &result.hMargin, &result.hPctMargin,
false);
AddCoord(wm.IsVertical() ? styleMargin->mMargin.GetBottom()
: styleMargin->mMargin.GetRight(),
aRenderingContext, this, &result.hMargin, &result.hPctMargin,
AddCoord(verticalAxis ? styleMargin->mMargin.GetBottom()
: styleMargin->mMargin.GetRight(),
aFrame, &result.hMargin, &result.hPctMargin,
false);
const nsStylePadding *stylePadding = StylePadding();
AddCoord(wm.IsVertical() ? stylePadding->mPadding.GetTop()
: stylePadding->mPadding.GetLeft(),
aRenderingContext, this, &result.hPadding, &result.hPctPadding,
const nsStylePadding* stylePadding = aFrame->StylePadding();
AddCoord(verticalAxis ? stylePadding->mPadding.GetTop()
: stylePadding->mPadding.GetLeft(),
aFrame, &result.hPadding, &result.hPctPadding,
true);
AddCoord(wm.IsVertical() ? stylePadding->mPadding.GetBottom()
: stylePadding->mPadding.GetRight(),
aRenderingContext, this, &result.hPadding, &result.hPctPadding,
AddCoord(verticalAxis ? stylePadding->mPadding.GetBottom()
: stylePadding->mPadding.GetRight(),
aFrame, &result.hPadding, &result.hPctPadding,
true);
const nsStyleBorder *styleBorder = StyleBorder();
result.hBorder += styleBorder->GetComputedBorderWidth(
wm.PhysicalSideForInlineAxis(eLogicalEdgeStart));
result.hBorder += styleBorder->GetComputedBorderWidth(
wm.PhysicalSideForInlineAxis(eLogicalEdgeEnd));
const nsStyleBorder* styleBorder = aFrame->StyleBorder();
if (verticalAxis) {
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_TOP);
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_BOTTOM);
} else {
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_LEFT);
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_RIGHT);
}
const nsStyleDisplay *disp = StyleDisplay();
if (IsThemed(disp)) {
nsPresContext *presContext = PresContext();
const nsStyleDisplay* disp = aFrame->StyleDisplay();
if (aFrame->IsThemed(disp)) {
nsPresContext* presContext = aFrame->PresContext();
nsIntMargin border;
presContext->GetTheme()->GetWidgetBorder(presContext->DeviceContext(),
this, disp->mAppearance,
aFrame, disp->mAppearance,
&border);
result.hBorder =
presContext->DevPixelsToAppUnits(wm.IsVertical() ? border.TopBottom()
: border.LeftRight());
presContext->DevPixelsToAppUnits(verticalAxis ? border.TopBottom()
: border.LeftRight());
nsIntMargin padding;
if (presContext->GetTheme()->GetWidgetPadding(presContext->DeviceContext(),
this, disp->mAppearance,
aFrame, disp->mAppearance,
&padding)) {
result.hPadding =
presContext->DevPixelsToAppUnits(wm.IsVertical() ? padding.TopBottom()
: padding.LeftRight());
presContext->DevPixelsToAppUnits(verticalAxis ? padding.TopBottom()
: padding.LeftRight());
result.hPctPadding = 0;
}
}
return result;
}
/* virtual */ nsIFrame::IntrinsicISizeOffsetData
nsFrame::IntrinsicISizeOffsets()
{
return IntrinsicSizeOffsets(this, true);
}
nsIFrame::IntrinsicISizeOffsetData
nsIFrame::IntrinsicBSizeOffsets()
{
return IntrinsicSizeOffsets(this, false);
}
/* virtual */ IntrinsicSize
nsFrame::GetIntrinsicSize()
{

View File

@ -250,8 +250,7 @@ public:
InlineMinISizeData *aData) override;
virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
InlinePrefISizeData *aData) override;
virtual IntrinsicISizeOffsetData
IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext) override;
virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual nsSize GetIntrinsicRatio() override;

View File

@ -1648,8 +1648,13 @@ public:
, hPctPadding(0.0f), hPctMargin(0.0f)
{}
};
virtual IntrinsicISizeOffsetData
IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext) = 0;
virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() = 0;
/**
* Return the bsize components of padding, border, and margin
* that contribute to the intrinsic width that applies to the parent.
*/
IntrinsicISizeOffsetData IntrinsicBSizeOffsets();
virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html style="writing-mode:vertical-lr;">
<body>
<input type="text" style="-moz-appearance:none; height:200px;" value="123">
<!-- div to cover spin box area -->
<div style="position:absolute; background-color:black; width:100px; height:200px; top:100px; left:0px;">
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html style="writing-mode:vertical-lr;">
<body>
<input type="number" style="-moz-appearance:none; height:200px;" value="123">
<!-- div to cover spin box area -->
<div style="position:absolute; background-color:black; width:100px; height:200px; top:100px; left:0px;">
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html style="writing-mode:vertical-rl;">
<body>
<input type="text" style="-moz-appearance:none; height:200px;" value="123">
<!-- div to cover spin box area -->
<div style="position:absolute; background-color:black; width:100px; height:200px; top:100px; right:0px;">
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html style="writing-mode:vertical-rl;">
<body>
<input type="number" style="-moz-appearance:none; height:200px;" value="123">
<!-- div to cover spin box area -->
<div style="position:absolute; background-color:black; width:100px; height:200px; top:100px; right:0px;">
</body>
</html>

View File

@ -10,6 +10,8 @@ skip-if(!Android&&!B2G&&!Mulet) == number-same-as-text-unthemed.html number-same
# should look the same as type=text, except for the spin box
== number-similar-to-text-unthemed.html number-similar-to-text-unthemed-ref.html
== number-similar-to-text-unthemed-rtl.html number-similar-to-text-unthemed-rtl-ref.html
pref(layout.css.vertical-text.enabled,true) == number-similar-to-text-unthemed-vertical-lr.html number-similar-to-text-unthemed-vertical-lr-ref.html
pref(layout.css.vertical-text.enabled,true) == number-similar-to-text-unthemed-vertical-rl.html number-similar-to-text-unthemed-vertical-rl-ref.html
# dynamic type changes:
fuzzy-if(/^Windows\x20NT\x205\.1/.test(http.oscpu),64,4) fuzzy-if(cocoaWidget,63,4) == to-number-from-other-type-unthemed-1.html to-number-from-other-type-unthemed-1-ref.html

View File

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html><head>
<meta charset="utf-8">
<title>Testcase for bug 1174450</title>
<style type="text/css">
body,html { color:black; background:white; font-size:12px; line-height:16px; padding:0; margin:0; }
div.v, div.h {
display: block;
position: relative;
border: 1px dashed silver;
width:92px;
height:60px;
}
div.h {
width:124px;
height:98px;
}
.h span {
margin: 7px 13px 62px 25px;
padding: 1px 3px 12px 37px;
}
.v span {
margin: 7px 13px 30px 12px;
padding: 1px 3px 6px 18px;
}
span {
display: block;
position: absolute;
width: 30px;
height: 10px;
background: lime;
border-width: 5px 9px 1px 7px;
border-style: solid;
}
.a { position:absolute; }
.t2 {top:100px;}
.t3 {top:200px;}
.t4 {top:300px;}
</style>
</head>
<body>
<div class="a t1">
<pre>vertical container, horizontal child</pre>
<div class="v"><span class="h"></span></div>
</div>
<div class="a t2">
<pre>vertical container, vertical child</pre>
<div class="v"><span class="v"></span></div>
</div>
<div class="a t3">
<pre>horizontal container, horizontal child</pre>
<div class="h"><span class="h"></span></div>
</div>
<div class="a t4">
<pre>horizontal container, vertical child</pre>
<div class="h"><span class="v"></span></div>
</div>
</body>
</html>

View File

@ -0,0 +1,63 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html><head>
<meta charset="utf-8">
<title>Testcase for bug 1174450</title>
<style type="text/css">
body,html { color:black; background:white; font-size:12px; line-height:16px; padding:0; margin:0; }
div.h, div.v {
display: block;
border: 1px dashed silver;
float: left;
}
.v {
writing-mode: vertical-lr;
}
.h {
writing-mode: horizontal-tb;
}
span {
display: block;
width: 30px;
height: 10px;
background: lime;
margin: 7px 13px 50% 20%;
padding: 1px 3px 10% 30%;
border-width: 5px 9px 1px 7px;
border-style: solid;
}
.a { position:absolute; }
.t2 {top:100px;}
.t3 {top:200px;}
.t4 {top:300px;}
</style>
</head>
<body>
<div class="a t1">
<pre>vertical container, horizontal child</pre>
<div class="v"><span class="h"></span></div>
</div>
<div class="a t2">
<pre>vertical container, vertical child</pre>
<div class="v"><span class="v"></span></div>
</div>
<div class="a t3">
<pre>horizontal container, horizontal child</pre>
<div class="h"><span class="h"></span></div>
</div>
<div class="a t4">
<pre>horizontal container, vertical child</pre>
<div class="h"><span class="v"></span></div>
</div>
</body>
</html>

View File

@ -148,6 +148,7 @@ fails == 1147834-relative-overconstrained-vertical-rl-rtl.html 1147834-top-left-
== 1172774-percent-padding-2.html 1172774-percent-horizontal-ref.html
== 1172774-percent-padding-3.html 1172774-percent-vertical-ref.html
== 1172774-percent-padding-4.html 1172774-percent-vertical-ref.html
== 1174450-intrinsic-sizing.html 1174450-intrinsic-sizing-ref.html
# Suite of tests from Gérard Talbot in bug 1079151
include abspos/reftest.list

View File

@ -990,17 +990,24 @@ input[type=number]::-moz-number-text {
}
input[type=number]::-moz-number-spin-box {
writing-mode: horizontal-tb;
display: flex;
flex-direction: column;
%ifdef XP_WIN
/* The Window's Theme's spin buttons have a very narrow minimum width, so
* make it something reasonable:
* XXX What about vertical mode? How will the spin buttons be arranged?
* This may need to be adjusted when bug 1123299 is implemented.
*/
width: 16px;
%endif
height: 0;
/* If the spin-box has auto height, it ends up enlarging the default height
* of the control, so we limit it to 1em here. The height doesn't affect
* the rendering of the spinner-buttons; it's only for layout purposes.
*
* This is a temporary hack until we implement better positioning for the
* spin-box in vertical mode; it works OK at default size but less well
* if the font-size is made substantially larger or smaller. (Bug 1175074.)
*/
max-height: 1em;
align-self: center;
justify-content: center;
}

View File

@ -8,7 +8,6 @@
*/
input[type="number"] {
writing-mode: horizontal-tb !important; /* XXX remove when bug 1123299 is done */
-moz-appearance: number-input;
/* Has to revert some properties applied by the generic input rule. */
-moz-binding: none;

File diff suppressed because it is too large Load Diff

View File

@ -33,49 +33,49 @@ public:
private:
// NOTE: Using prefix "BTLS" to avoid overlapping names with
// the values of nsLayoutUtils::IntrinsicISizeType
enum BtlsWidthType { BTLS_MIN_WIDTH,
BTLS_PREF_WIDTH,
BTLS_FINAL_WIDTH };
enum BtlsISizeType { BTLS_MIN_ISIZE,
BTLS_PREF_ISIZE,
BTLS_FINAL_ISIZE };
// Compute intrinsic width member variables on the columns.
// Compute intrinsic isize member variables on the columns.
void ComputeColumnIntrinsicISizes(nsRenderingContext* aRenderingContext);
// Distribute a colspanning cell's percent width (if any) to its columns.
void DistributePctWidthToColumns(float aSpanPrefPct,
// Distribute a colspanning cell's percent isize (if any) to its columns.
void DistributePctISizeToColumns(float aSpanPrefPct,
int32_t aFirstCol,
int32_t aColCount);
// Distribute a width of some BltsWidthType type to a set of columns.
// aWidth: The amount of width to be distributed
// Distribute an isize of some BltsISizeType type to a set of columns.
// aISize: The amount of isize to be distributed
// aFirstCol: The index (in the table) of the first column to be
// considered for receiving width
// considered for receiving isize
// aColCount: The number of consecutive columns (starting with aFirstCol)
// to be considered for receiving width
// aWidthType: The type of width being distributed. (BTLS_MIN_WIDTH and
// BTLS_PREF_WIDTH are intended to be used for dividing up
// colspan's min & pref width. BTLS_FINAL_WIDTH is intended
// to be used for distributing the table's final width across
// to be considered for receiving isize
// aISizeType: The type of isize being distributed. (BTLS_MIN_ISIZE and
// BTLS_PREF_ISIZE are intended to be used for dividing up
// colspan's min & pref isize. BTLS_FINAL_ISIZE is intended
// to be used for distributing the table's final isize across
// all its columns)
// aSpanHasSpecifiedWidth: Should be true iff:
// aSpanHasSpecifiedISize: Should be true iff:
// - We're distributing a colspanning cell's
// pref or min width to its columns
// - The colspanning cell has a specified width.
void DistributeWidthToColumns(nscoord aWidth,
// pref or min isize to its columns
// - The colspanning cell has a specified isize.
void DistributeISizeToColumns(nscoord aISize,
int32_t aFirstCol,
int32_t aColCount,
BtlsWidthType aWidthType,
bool aSpanHasSpecifiedWidth);
BtlsISizeType aISizeType,
bool aSpanHasSpecifiedISize);
// Compute the min and pref widths of the table from the width
// Compute the min and pref isizes of the table from the isize
// variables on the columns.
void ComputeIntrinsicISizes(nsRenderingContext* aRenderingContext);
nsTableFrame *mTableFrame;
nscoord mMinWidth;
nscoord mPrefWidth;
nscoord mPrefWidthPctExpand;
nscoord mLastCalcWidth;
nscoord mMinISize;
nscoord mPrefISize;
nscoord mPrefISizePctExpand;
nscoord mLastCalcISize;
};
#endif /* !defined(BasicTableLayoutStrategy_h_) */

View File

@ -248,7 +248,7 @@ FixedTableLayoutStrategy::ComputeColumnISizes(const nsHTMLReflowState& aReflowSt
} else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
// XXX This should use real percentage padding
nsIFrame::IntrinsicISizeOffsetData offsets =
cellFrame->IntrinsicISizeOffsets(aReflowState.rendContext);
cellFrame->IntrinsicISizeOffsets();
float pct = styleWidth->GetPercentValue();
colWidth = NSToCoordFloor(pct * float(tableWidth));

View File

@ -788,10 +788,9 @@ nsTableCellFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
}
/* virtual */ nsIFrame::IntrinsicISizeOffsetData
nsTableCellFrame::IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext)
nsTableCellFrame::IntrinsicISizeOffsets()
{
IntrinsicISizeOffsetData result =
nsContainerFrame::IntrinsicISizeOffsets(aRenderingContext);
IntrinsicISizeOffsetData result = nsContainerFrame::IntrinsicISizeOffsets();
result.hMargin = 0;
result.hPctMargin = 0;

View File

@ -117,8 +117,7 @@ public:
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual IntrinsicISizeOffsetData
IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext) override;
virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() override;
virtual void Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,

View File

@ -1542,10 +1542,9 @@ nsTableFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
}
/* virtual */ nsIFrame::IntrinsicISizeOffsetData
nsTableFrame::IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext)
nsTableFrame::IntrinsicISizeOffsets()
{
IntrinsicISizeOffsetData result =
nsContainerFrame::IntrinsicISizeOffsets(aRenderingContext);
IntrinsicISizeOffsetData result = nsContainerFrame::IntrinsicISizeOffsets();
result.hMargin = 0;
result.hPctMargin = 0;

View File

@ -319,8 +319,7 @@ public:
// border to the results of these functions.
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual IntrinsicISizeOffsetData
IntrinsicISizeOffsets(nsRenderingContext* aRenderingContext) override;
virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() override;
virtual mozilla::LogicalSize
ComputeSize(nsRenderingContext *aRenderingContext,

View File

@ -12,7 +12,6 @@ EXPORTS.mtransport += [
'../nriceresolverfake.h',
'../rlogringbuffer.h',
'../runnable_utils.h',
'../runnable_utils_generated.h',
'../sigslot.h',
'../simpletokenbucket.h',
'../stun_udp_socket_filter.h',

View File

@ -129,7 +129,7 @@ nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
mozilla::SyncRunnable::DispatchToThread(
mainThread.get(),
mozilla::WrapRunnableNMRet(&GetInterfaces, &interfaces, &rv),
mozilla::WrapRunnableNMRet(&rv, &GetInterfaces, &interfaces),
false);
if (NS_FAILED(rv)) {
return R_FAILED;

View File

@ -10,7 +10,9 @@
#define runnable_utils_h__
#include "nsThreadUtils.h"
#include "mozilla/IndexSequence.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Tuple.h"
// Abstract base class for all of our templates
namespace mozilla {
@ -53,24 +55,159 @@ class runnable_args_base : public nsRunnable {
NS_IMETHOD Run() = 0;
};
template<typename R>
struct RunnableFunctionCallHelper
{
template<typename FunType, typename... Args, size_t... Indices>
static R apply(FunType func, Tuple<Args...>& args, IndexSequence<Indices...>)
{
return func(Get<Indices>(args)...);
}
};
// A void specialization is needed in the case where the template instantiator
// knows we don't want to return a value, but we don't know whether the called
// function returns void or something else.
template<>
struct RunnableFunctionCallHelper<void>
{
template<typename FunType, typename... Args, size_t... Indices>
static void apply(FunType func, Tuple<Args...>& args, IndexSequence<Indices...>)
{
func(Get<Indices>(args)...);
}
};
template<typename R>
struct RunnableMethodCallHelper
{
template<typename Class, typename M, typename... Args, size_t... Indices>
static R apply(Class obj, M method, Tuple<Args...>& args, IndexSequence<Indices...>)
{
return ((*obj).*method)(Get<Indices>(args)...);
}
};
// A void specialization is needed in the case where the template instantiator
// knows we don't want to return a value, but we don't know whether the called
// method returns void or something else.
template<>
struct RunnableMethodCallHelper<void>
{
template<typename Class, typename M, typename... Args, size_t... Indices>
static void apply(Class obj, M method, Tuple<Args...>& args, IndexSequence<Indices...>)
{
((*obj).*method)(Get<Indices>(args)...);
}
};
}
// The generated file contains four major function templates
// (in variants for arbitrary numbers of arguments up to 10,
// which is why it is machine generated). The four templates
// are:
//
// WrapRunnable(o, m, ...) -- wraps a member function m of an object ptr o
// WrapRunnableRet(o, m, ..., r) -- wraps a member function m of an object ptr o
// the function returns something that can
// be assigned to *r
// WrapRunnableNM(f, ...) -- wraps a function f
// WrapRunnableNMRet(f, ..., r) -- wraps a function f that returns something
// that can be assigned to *r
//
// All of these template functions return a Runnable* which can be passed
// to Dispatch().
#include "runnable_utils_generated.h"
template<typename FunType, typename... Args>
class runnable_args_func : public detail::runnable_args_base<detail::NoResult>
{
public:
// |explicit| to pacify static analysis when there are no |args|.
explicit runnable_args_func(FunType f, Args... args)
: mFunc(f), mArgs(args...)
{}
NS_IMETHOD Run() {
detail::RunnableFunctionCallHelper<void>::apply(mFunc, mArgs, typename IndexSequenceFor<Args...>::Type());
return NS_OK;
}
private:
FunType mFunc;
Tuple<Args...> mArgs;
};
template<typename FunType, typename... Args>
runnable_args_func<FunType, Args...>*
WrapRunnableNM(FunType f, Args... args)
{
return new runnable_args_func<FunType, Args...>(f, args...);
}
template<typename Ret, typename FunType, typename... Args>
class runnable_args_func_ret : public detail::runnable_args_base<detail::ReturnsResult>
{
public:
runnable_args_func_ret(Ret* ret, FunType f, Args... args)
: mReturn(ret), mFunc(f), mArgs(args...)
{}
NS_IMETHOD Run() {
*mReturn = detail::RunnableFunctionCallHelper<Ret>::apply(mFunc, mArgs, typename IndexSequenceFor<Args...>::Type());
return NS_OK;
}
private:
Ret* mReturn;
FunType mFunc;
Tuple<Args...> mArgs;
};
template<typename R, typename FunType, typename... Args>
runnable_args_func_ret<R, FunType, Args...>*
WrapRunnableNMRet(R* ret, FunType f, Args... args)
{
return new runnable_args_func_ret<R, FunType, Args...>(ret, f, args...);
}
template<typename Class, typename M, typename... Args>
class runnable_args_memfn : public detail::runnable_args_base<detail::NoResult>
{
public:
runnable_args_memfn(Class obj, M method, Args... args)
: mObj(obj), mMethod(method), mArgs(args...)
{}
NS_IMETHOD Run() {
detail::RunnableMethodCallHelper<void>::apply(mObj, mMethod, mArgs, typename IndexSequenceFor<Args...>::Type());
return NS_OK;
}
private:
Class mObj;
M mMethod;
Tuple<Args...> mArgs;
};
template<typename Class, typename M, typename... Args>
runnable_args_memfn<Class, M, Args...>*
WrapRunnable(Class obj, M method, Args... args)
{
return new runnable_args_memfn<Class, M, Args...>(obj, method, args...);
}
template<typename Ret, typename Class, typename M, typename... Args>
class runnable_args_memfn_ret : public detail::runnable_args_base<detail::ReturnsResult>
{
public:
runnable_args_memfn_ret(Ret* ret, Class obj, M method, Args... args)
: mReturn(ret), mObj(obj), mMethod(method), mArgs(args...)
{}
NS_IMETHOD Run() {
*mReturn = detail::RunnableMethodCallHelper<Ret>::apply(mObj, mMethod, mArgs, typename IndexSequenceFor<Args...>::Type());
return NS_OK;
}
private:
Ret* mReturn;
Class mObj;
M mMethod;
Tuple<Args...> mArgs;
};
template<typename R, typename Class, typename M, typename... Args>
runnable_args_memfn_ret<R, Class, M, Args...>*
WrapRunnableRet(R* ret, Class obj, M method, Args... args)
{
return new runnable_args_memfn_ret<R, Class, M, Args...>(ret, obj, method, args...);
}
static inline nsresult RUN_ON_THREAD(nsIEventTarget *thread, detail::runnable_args_base<detail::NoResult> *runnable, uint32_t flags) {
return detail::RunOnThreadInternal(thread, static_cast<nsIRunnable *>(runnable), flags);

View File

@ -1,195 +0,0 @@
# 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/.
MAX_ARGS = 15
boilerplate = "/* This Source Code Form is subject to the terms of the Mozilla Public\n\
* License, v. 2.0. If a copy of the MPL was not distributed with this\n\
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n"
def get_args_count(args, member):
if member:
return args + 2
return args + 1
def gen_args_type(args, member):
if member:
ret = ["C o"]
else:
ret = []
ret.append("M m")
for arg in range(0, args):
ret.append("A%d a%d"%(arg, arg))
return ", ".join(ret)
def gen_args(args, member):
if member:
ret = ["o"]
else:
ret = []
ret.append("m")
for arg in range(0, args):
ret.append("a%d"%(arg))
return ", ".join(ret)
def gen_args_(args):
ret = []
for arg in range(0, args):
ret.append("a%d_"%(arg))
return ", ".join(ret)
def gen_init(args, r = False, member = False):
if member:
ret = ["o_(o)"]
else:
ret = []
ret.append("m_(m)")
if r:
ret.append("r_(r)")
for arg in range(0, args):
ret.append("a%d_(a%d)"%(arg, arg))
return ", ".join(ret)
def gen_typenames(args, member):
if member:
ret = ["typename C"]
else:
ret = []
ret.append("typename M")
for arg in range(0, args):
ret.append("typename A%d"%(arg))
return ", ".join(ret)
def gen_types(args, member):
if member:
ret = ["C"]
else:
ret = []
ret.append("M")
for arg in range(0, args):
ret.append("A%d"%(arg))
return ", ".join(ret)
def runnable_class_name(args, ret=False, member=True):
if member:
nm = "m"
else:
nm = "nm"
if ret:
class_suffix = "_ret"
enum_specializer = "detail::ReturnsResult"
else:
class_suffix = ""
enum_specializer = "detail::NoResult"
return "runnable_args_%s_%d%s" % (nm, args, class_suffix), enum_specializer
def generate_class_template(args, ret = False, member = True):
print "// %d arguments --"%args
class_name, specializer = runnable_class_name(args, ret, member)
base_class = "detail::runnable_args_base<%s>" % specializer
if not ret:
print "template<"+ gen_typenames(args, member) + "> class %s : public %s {" % (class_name, base_class)
else:
print "template<"+ gen_typenames(args, member) + ", typename R> class %s : public %s {" % (class_name, base_class)
print " public:"
if not ret:
explicit = ""
if get_args_count(args, member) == 1:
explicit = "explicit "
print " %s%s(" % (explicit, class_name) + gen_args_type(args, member) + ") :"
print " " + gen_init(args, False, member) + " {}"
else:
print " %s(" % class_name + gen_args_type(args, member) + ", R *r) :"
print " " + gen_init(args, True, member) + " {}"
print
print " NS_IMETHOD Run() {"
if ret:
print " *r_ =",
else:
print " ",
if member:
print "((*o_).*m_)(" + gen_args_(args) + ");"
else:
print "m_(" + gen_args_(args) + ");"
print " return NS_OK;"
print " }"
print
print " private:"
if member:
print " C o_;"
print " M m_;"
if ret:
print " R* r_;"
for arg in range(0, args):
print " A%d a%d_;"%(arg, arg)
print "};"
print
print
print
def generate_function_template(args, member):
if member:
NM = "";
else:
NM = "NM";
class_name, _ = runnable_class_name(args, False, member)
print "// %d arguments --"%args
print "template<" + gen_typenames(args, member) + ">"
print "%s<" % class_name + gen_types(args, member) + ">* WrapRunnable%s("%NM + gen_args_type(args, member) + ") {"
print " return new %s<" % class_name + gen_types(args, member) + ">"
print " (" + gen_args(args, member) + ");"
print "}"
print
def generate_function_template_ret(args, member):
if member:
NM = "";
else:
NM = "NM";
class_name, _ = runnable_class_name(args, True, member)
print "// %d arguments --"%args
print "template<" + gen_typenames(args, member) + ", typename R>"
print "%s<" % class_name + gen_types(args, member) + ", R>* WrapRunnable%sRet("%NM + gen_args_type(args, member) + ", R* r) {"
print " return new %s<" % class_name + gen_types(args, member) + ", R>"
print " (" + gen_args(args, member) + ", r);"
print "}"
print
print boilerplate
print
for num_args in range (0, MAX_ARGS):
generate_class_template(num_args, False, False)
generate_class_template(num_args, True, False)
generate_class_template(num_args, False, True)
generate_class_template(num_args, True, True)
print
print
print
for num_args in range(0, MAX_ARGS):
generate_function_template(num_args, False)
generate_function_template_ret(num_args, False)
generate_function_template(num_args, True)
generate_function_template_ret(num_args, True)

File diff suppressed because it is too large Load Diff

View File

@ -381,7 +381,7 @@ class IceTestPeer : public sigslot::has_slots<> {
nsresult res;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res),
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
@ -420,7 +420,7 @@ class IceTestPeer : public sigslot::has_slots<> {
RUN_ON_THREAD(
test_utils->sts_target(),
WrapRunnableRet(this, &IceTestPeer::GetCandidates_s, stream, &v));
WrapRunnableRet(&v, this, &IceTestPeer::GetCandidates_s, stream));
return v;
}
@ -480,7 +480,7 @@ class IceTestPeer : public sigslot::has_slots<> {
{
bool result;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(this, &IceTestPeer::is_ready_s, stream, &result),
WrapRunnableRet(&result, this, &IceTestPeer::is_ready_s, stream),
NS_DISPATCH_SYNC);
return result;
}
@ -706,7 +706,7 @@ class IceTestPeer : public sigslot::has_slots<> {
// Now start checks
test_utils->sts_target()->Dispatch(
WrapRunnableRet(ice_ctx_, &NrIceCtx::StartChecks, &res),
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartChecks),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
@ -783,11 +783,10 @@ class IceTestPeer : public sigslot::has_slots<> {
std::vector<NrIceCandidatePair>* pairs) {
nsresult v;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(this,
WrapRunnableRet(&v, this,
&IceTestPeer::GetCandidatePairs_s,
stream_index,
pairs,
&v),
pairs),
NS_DISPATCH_SYNC);
return v;
}
@ -993,10 +992,9 @@ class IceTestPeer : public sigslot::has_slots<> {
void SetControlling(NrIceCtx::Controlling controlling) {
nsresult res;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(ice_ctx_,
WrapRunnableRet(&res, ice_ctx_,
&NrIceCtx::SetControlling,
controlling,
&res),
controlling),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}

View File

@ -38,7 +38,7 @@ class TimerTest : public ::testing::Test {
int ret;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(this, &TimerTest::ArmTimer_w, timeout, &ret),
WrapRunnableRet(&ret, this, &TimerTest::ArmTimer_w, timeout),
NS_DISPATCH_SYNC);
return ret;
@ -48,7 +48,7 @@ class TimerTest : public ::testing::Test {
int ret;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(this, &TimerTest::ArmCancelTimer_w, timeout, &ret),
WrapRunnableRet(&ret, this, &TimerTest::ArmCancelTimer_w, timeout),
NS_DISPATCH_SYNC);
return ret;
@ -71,7 +71,7 @@ class TimerTest : public ::testing::Test {
int ret;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(this, &TimerTest::CancelTimer_w, &ret),
WrapRunnableRet(&ret, this, &TimerTest::CancelTimer_w),
NS_DISPATCH_SYNC);
return ret;
@ -85,7 +85,7 @@ class TimerTest : public ::testing::Test {
int ret;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(this, &TimerTest::Schedule_w, &ret),
WrapRunnableRet(&ret, this, &TimerTest::Schedule_w),
NS_DISPATCH_SYNC);
return ret;

View File

@ -138,7 +138,7 @@ class DispatchTest : public ::testing::Test {
int z;
int x = 10;
target_->Dispatch(WrapRunnableRet(&cl_, &TargetClass::return_int, x, &z),
target_->Dispatch(WrapRunnableRet(&z, &cl_, &TargetClass::return_int, x),
NS_DISPATCH_SYNC);
ASSERT_EQ(10, z);
}
@ -195,7 +195,7 @@ TEST_F(DispatchTest, TestNonMethodRet) {
int z;
test_utils->sts_target()->Dispatch(
WrapRunnableNMRet(SetNonMethodRet, &cl_, 10, &z), NS_DISPATCH_SYNC);
WrapRunnableNMRet(&z, SetNonMethodRet, &cl_, 10), NS_DISPATCH_SYNC);
ASSERT_EQ(1, ran_);
ASSERT_EQ(10, z);

View File

@ -96,11 +96,11 @@ class TestNrSocketTest : public ::testing::Test {
const char* ip_str = "127.0.0.1") {
nsRefPtr<TestNat> result;
sts_->Dispatch(
WrapRunnableRet(this,
WrapRunnableRet(&result,
this,
&TestNrSocketTest::CreatePrivateAddrs_s,
size,
ip_str,
&result),
ip_str),
NS_DISPATCH_SYNC);
return result;
}
@ -132,11 +132,11 @@ class TestNrSocketTest : public ::testing::Test {
}
int result = 0;
sts_->Dispatch(WrapRunnableRet(this,
sts_->Dispatch(WrapRunnableRet(&result,
this,
&TestNrSocketTest::SendData_s,
from,
via,
&result),
via),
NS_DISPATCH_SYNC);
if (result) {
return false;
@ -152,11 +152,11 @@ class TestNrSocketTest : public ::testing::Test {
}
MOZ_ASSERT(to);
sts_->Dispatch(WrapRunnableRet(this,
sts_->Dispatch(WrapRunnableRet(&result,
this,
&TestNrSocketTest::RecvData_s,
to,
sender_external_address,
&result),
sender_external_address),
NS_DISPATCH_SYNC);
return !result;
@ -182,11 +182,11 @@ class TestNrSocketTest : public ::testing::Test {
MOZ_ASSERT(sock);
MOZ_ASSERT(address);
int r;
sts_->Dispatch(WrapRunnableRet(this,
sts_->Dispatch(WrapRunnableRet(&r,
this,
&TestNrSocketTest::GetAddress_s,
sock,
address,
&r),
address),
NS_DISPATCH_SYNC);
return r;
}

View File

@ -633,7 +633,7 @@ class TransportTestPeer : public sigslot::has_slots<> {
layers->push(dtls_);
test_utils->sts_target()->Dispatch(
WrapRunnableRet(flow_, &TransportFlow::PushLayers, layers, &res),
WrapRunnableRet(&res, flow_, &TransportFlow::PushLayers, layers),
NS_DISPATCH_SYNC);
ASSERT_EQ((nsresult)NS_OK, res);
@ -644,7 +644,7 @@ class TransportTestPeer : public sigslot::has_slots<> {
// Start gathering
test_utils->sts_target()->Dispatch(
WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res),
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
@ -684,23 +684,23 @@ class TransportTestPeer : public sigslot::has_slots<> {
// First send attributes
test_utils->sts_target()->Dispatch(
WrapRunnableRet(peer_->ice_ctx_,
WrapRunnableRet(&res, peer_->ice_ctx_,
&NrIceCtx::ParseGlobalAttributes,
ice_ctx_->GetGlobalAttributes(), &res),
ice_ctx_->GetGlobalAttributes()),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
for (size_t i=0; i<streams_.size(); ++i) {
test_utils->sts_target()->Dispatch(
WrapRunnableRet(peer_->streams_[i], &NrIceMediaStream::ParseAttributes,
candidates_[streams_[i]->name()], &res), NS_DISPATCH_SYNC);
WrapRunnableRet(&res, peer_->streams_[i], &NrIceMediaStream::ParseAttributes,
candidates_[streams_[i]->name()]), NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
// Start checks on the other peer.
test_utils->sts_target()->Dispatch(
WrapRunnableRet(peer_->ice_ctx_, &NrIceCtx::StartChecks, &res),
WrapRunnableRet(&res, peer_->ice_ctx_, &NrIceCtx::StartChecks),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
@ -708,7 +708,7 @@ class TransportTestPeer : public sigslot::has_slots<> {
TransportResult SendPacket(const unsigned char* data, size_t len) {
TransportResult ret;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(flow_, &TransportFlow::SendPacket, data, len, &ret),
WrapRunnableRet(&ret, flow_, &TransportFlow::SendPacket, data, len),
NS_DISPATCH_SYNC);
return ret;
@ -755,7 +755,7 @@ class TransportTestPeer : public sigslot::has_slots<> {
TransportLayer::State tstate;
RUN_ON_THREAD(test_utils->sts_target(),
WrapRunnableRet(flow_, &TransportFlow::state, &tstate));
WrapRunnableRet(&tstate, flow_, &TransportFlow::state));
return tstate;
}
@ -774,8 +774,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
nsresult rv;
uint16_t cipher;
RUN_ON_THREAD(test_utils->sts_target(),
WrapRunnableRet(dtls_, &TransportLayerDtls::GetCipherSuite,
&cipher, &rv));
WrapRunnableRet(&rv, dtls_, &TransportLayerDtls::GetCipherSuite,
&cipher));
if (NS_FAILED(rv)) {
return TLS_NULL_WITH_NULL_NULL; // i.e., not good
@ -787,8 +787,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
nsresult rv;
uint16_t cipher;
RUN_ON_THREAD(test_utils->sts_target(),
WrapRunnableRet(dtls_, &TransportLayerDtls::GetSrtpCipher,
&cipher, &rv));
WrapRunnableRet(&rv, dtls_, &TransportLayerDtls::GetSrtpCipher,
&cipher));
if (NS_FAILED(rv)) {
return 0; // the SRTP equivalent of TLS_NULL_WITH_NULL_NULL
}

View File

@ -277,12 +277,11 @@ WebrtcGmpVideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
int32_t ret;
mozilla::SyncRunnable::DispatchToThread(mGMPThread,
WrapRunnableRet(this,
WrapRunnableRet(&ret, this,
&WebrtcGmpVideoEncoder::Encode_g,
&aInputImage,
aCodecSpecificInfo,
aFrameTypes,
&ret));
aFrameTypes));
return ret;
}
@ -410,10 +409,9 @@ WebrtcGmpVideoEncoder::SetRates(uint32_t aNewBitRate, uint32_t aFrameRate)
int32_t ret;
MOZ_ASSERT(mGMPThread);
mozilla::SyncRunnable::DispatchToThread(mGMPThread,
WrapRunnableRet(this,
WrapRunnableRet(&ret, this,
&WebrtcGmpVideoEncoder::SetRates_g,
aNewBitRate, aFrameRate,
&ret));
aNewBitRate, aFrameRate));
return WEBRTC_VIDEO_CODEC_OK;
}
@ -681,14 +679,13 @@ WebrtcGmpVideoDecoder::Decode(const webrtc::EncodedImage& aInputImage,
int32_t ret;
MOZ_ASSERT(mGMPThread);
mozilla::SyncRunnable::DispatchToThread(mGMPThread,
WrapRunnableRet(this,
WrapRunnableRet(&ret, this,
&WebrtcGmpVideoDecoder::Decode_g,
aInputImage,
aMissingFrames,
aFragmentation,
aCodecSpecificInfo,
aRenderTimeMs,
&ret));
aRenderTimeMs));
return ret;
}

View File

@ -891,19 +891,19 @@ NewData(MediaStreamGraph* graph, TrackID tid,
return;
}
if (track_id_ != TRACK_INVALID) {
if (tid != track_id_) {
return;
}
} else if (conduit_->type() !=
(media.GetType() == MediaSegment::AUDIO ? MediaSessionConduit::AUDIO :
MediaSessionConduit::VIDEO)) {
// Ignore data in case we have a muxed stream
if (conduit_->type() !=
(media.GetType() == MediaSegment::AUDIO ? MediaSessionConduit::AUDIO :
MediaSessionConduit::VIDEO)) {
// Ignore data of wrong kind in case we have a muxed stream
return;
} else {
}
if (track_id_ == TRACK_INVALID) {
// Don't lock during normal media flow except on first sample
MutexAutoLock lock(mMutex);
track_id_ = track_id_external_ = tid;
} else if (tid != track_id_) {
return;
}
// TODO(ekr@rtfm.com): For now assume that we have only one

View File

@ -532,16 +532,14 @@ class TransportConduitTest : public ::testing::Test
//get pointer to AudioSessionConduit
int err=0;
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(
&mozilla::AudioSessionConduit::Create,
&mAudioSession));
WrapRunnableNMRet(&mAudioSession,
&mozilla::AudioSessionConduit::Create));
if( !mAudioSession )
ASSERT_NE(mAudioSession, (void*)nullptr);
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(
&mozilla::AudioSessionConduit::Create,
&mAudioSession2));
WrapRunnableNMRet(&mAudioSession2,
&mozilla::AudioSessionConduit::Create));
if( !mAudioSession2 )
ASSERT_NE(mAudioSession2, (void*)nullptr);
@ -596,17 +594,15 @@ class TransportConduitTest : public ::testing::Test
int err = 0;
//get pointer to VideoSessionConduit
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(
&mozilla::VideoSessionConduit::Create,
&mVideoSession));
WrapRunnableNMRet(&mVideoSession,
&mozilla::VideoSessionConduit::Create));
if( !mVideoSession )
ASSERT_NE(mVideoSession, (void*)nullptr);
// This session is for other one
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(
&mozilla::VideoSessionConduit::Create,
&mVideoSession2));
WrapRunnableNMRet(&mVideoSession2,
&mozilla::VideoSessionConduit::Create));
if( !mVideoSession2 )
ASSERT_NE(mVideoSession2,(void*)nullptr);
@ -694,9 +690,8 @@ class TransportConduitTest : public ::testing::Test
mozilla::RefPtr<mozilla::VideoSessionConduit> videoSession;
//get pointer to VideoSessionConduit
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(
&mozilla::VideoSessionConduit::Create,
&videoSession));
WrapRunnableNMRet(&videoSession,
&mozilla::VideoSessionConduit::Create));
if( !videoSession )
ASSERT_NE(videoSession, (void*)nullptr);
@ -805,9 +800,8 @@ class TransportConduitTest : public ::testing::Test
// Get pointer to VideoSessionConduit.
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(
&mozilla::VideoSessionConduit::Create,
&mVideoSession));
WrapRunnableNMRet(&mVideoSession,
&mozilla::VideoSessionConduit::Create));
if( !mVideoSession )
ASSERT_NE(mVideoSession, (void*)nullptr);
@ -1046,7 +1040,7 @@ int main(int argc, char **argv)
int result;
gGtestThread->Dispatch(
mozilla::WrapRunnableNMRet(gtest_main, argc, argv, &result), NS_DISPATCH_NORMAL);
mozilla::WrapRunnableNMRet(&result, gtest_main, argc, argv), NS_DISPATCH_NORMAL);
// Here we handle the event queue for dispatches to the main thread
// When the GTest thread is complete it will send one more dispatch

View File

@ -161,7 +161,7 @@ class TestAgent {
mozilla::SyncRunnable::DispatchToThread(
test_utils->sts_target(),
WrapRunnableRet(audio_->GetStream(), &Fake_MediaStream::Start, &ret));
WrapRunnableRet(&ret, audio_->GetStream(), &Fake_MediaStream::Start));
ASSERT_TRUE(NS_SUCCEEDED(ret));
}

View File

@ -662,8 +662,8 @@ class PCDispatchWrapper : public nsSupportsWeakReference
// Instead we are dispatching back to the same method for
// all of these.
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::Initialize,
aObserver, aWindow, aConfiguration, aThread, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::Initialize,
aObserver, aWindow, aConfiguration, aThread),
NS_DISPATCH_SYNC);
rv = NS_OK;
}
@ -685,8 +685,7 @@ class PCDispatchWrapper : public nsSupportsWeakReference
}
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::CreateOffer,
aOptions, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::CreateOffer, aOptions),
NS_DISPATCH_SYNC);
}
@ -700,7 +699,7 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->CreateAnswer();
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::CreateAnswer, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::CreateAnswer),
NS_DISPATCH_SYNC);
}
@ -714,8 +713,8 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->SetLocalDescription(aAction, aSDP);
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::SetLocalDescription,
aAction, aSDP, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::SetLocalDescription,
aAction, aSDP),
NS_DISPATCH_SYNC);
}
@ -729,8 +728,8 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->SetRemoteDescription(aAction, aSDP);
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::SetRemoteDescription,
aAction, aSDP, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::SetRemoteDescription,
aAction, aSDP),
NS_DISPATCH_SYNC);
}
@ -745,8 +744,8 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->AddIceCandidate(aCandidate, aMid, aLevel);
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::AddIceCandidate,
aCandidate, aMid, aLevel, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::AddIceCandidate,
aCandidate, aMid, aLevel),
NS_DISPATCH_SYNC);
}
return rv;
@ -761,8 +760,8 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->AddTrack(*aTrack, *aMediaStream);
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::AddTrack, aTrack,
aMediaStream, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::AddTrack, aTrack,
aMediaStream),
NS_DISPATCH_SYNC);
}
@ -776,7 +775,7 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->RemoveTrack(*aTrack);
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::RemoveTrack, aTrack, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::RemoveTrack, aTrack),
NS_DISPATCH_SYNC);
}
@ -790,8 +789,8 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->GetLocalDescription(aSDP);
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::GetLocalDescription,
aSDP, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::GetLocalDescription,
aSDP),
NS_DISPATCH_SYNC);
}
@ -805,8 +804,8 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->GetRemoteDescription(aSDP);
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::GetRemoteDescription,
aSDP, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::GetRemoteDescription,
aSDP),
NS_DISPATCH_SYNC);
}
@ -820,8 +819,7 @@ class PCDispatchWrapper : public nsSupportsWeakReference
result = pc_->SignalingState();
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::SignalingState,
&result),
WrapRunnableRet(&result, this, &PCDispatchWrapper::SignalingState),
NS_DISPATCH_SYNC);
}
@ -835,8 +833,7 @@ class PCDispatchWrapper : public nsSupportsWeakReference
result = pc_->IceConnectionState();
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::IceConnectionState,
&result),
WrapRunnableRet(&result, this, &PCDispatchWrapper::IceConnectionState),
NS_DISPATCH_SYNC);
}
@ -850,8 +847,7 @@ class PCDispatchWrapper : public nsSupportsWeakReference
result = pc_->IceGatheringState();
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::IceGatheringState,
&result),
WrapRunnableRet(&result, this, &PCDispatchWrapper::IceGatheringState),
NS_DISPATCH_SYNC);
}
@ -865,7 +861,7 @@ class PCDispatchWrapper : public nsSupportsWeakReference
rv = pc_->Close();
} else {
gMainThread->Dispatch(
WrapRunnableRet(this, &PCDispatchWrapper::Close, &rv),
WrapRunnableRet(&rv, this, &PCDispatchWrapper::Close),
NS_DISPATCH_SYNC);
}
@ -1067,7 +1063,7 @@ class SignalingAgent {
nsresult ret;
mozilla::SyncRunnable::DispatchToThread(
test_utils->sts_target(),
WrapRunnableRet(audio_stream, &Fake_MediaStream::Start, &ret));
WrapRunnableRet(&ret, audio_stream, &Fake_MediaStream::Start));
ASSERT_TRUE(NS_SUCCEEDED(ret));
stream = audio_stream;
@ -1127,9 +1123,9 @@ class SignalingAgent {
{
LocalSourceStreamInfo* info;
mozilla::SyncRunnable::DispatchToThread(
gMainThread, WrapRunnableRet(
gMainThread, WrapRunnableRet(&info,
pc->media(), &PeerConnectionMedia::GetLocalStreamById,
streamId, &info));
streamId));
ASSERT_TRUE(info) << "No such local stream id: " << streamId;
@ -1137,10 +1133,9 @@ class SignalingAgent {
mozilla::SyncRunnable::DispatchToThread(
gMainThread,
WrapRunnableRet(info,
WrapRunnableRet(&pipeline, info,
&SourceStreamInfo::GetPipelineByTrackId_m,
trackId,
&pipeline));
trackId));
ASSERT_TRUE(pipeline) << "No such local track id: " << trackId;
@ -1175,9 +1170,9 @@ class SignalingAgent {
{
RemoteSourceStreamInfo* info;
mozilla::SyncRunnable::DispatchToThread(
gMainThread, WrapRunnableRet(
gMainThread, WrapRunnableRet(&info,
pc->media(), &PeerConnectionMedia::GetRemoteStreamById,
streamId, &info));
streamId));
ASSERT_TRUE(info) << "No such remote stream id: " << streamId;
@ -1185,10 +1180,9 @@ class SignalingAgent {
mozilla::SyncRunnable::DispatchToThread(
gMainThread,
WrapRunnableRet(info,
WrapRunnableRet(&pipeline, info,
&SourceStreamInfo::GetPipelineByTrackId_m,
trackId,
&pipeline));
trackId));
ASSERT_TRUE(pipeline) << "No such remote track id: " << trackId;
@ -1300,7 +1294,7 @@ class SignalingAgent {
nsresult ret;
mozilla::SyncRunnable::DispatchToThread(
test_utils->sts_target(),
WrapRunnableRet(audio_stream, &Fake_MediaStream::Start, &ret));
WrapRunnableRet(&ret, audio_stream, &Fake_MediaStream::Start));
ASSERT_TRUE(NS_SUCCEEDED(ret));
@ -1509,14 +1503,14 @@ class SignalingAgent {
SourceStreamInfo* streamInfo;
if (local) {
mozilla::SyncRunnable::DispatchToThread(
gMainThread, WrapRunnableRet(
gMainThread, WrapRunnableRet(&streamInfo,
pc->media(), &PeerConnectionMedia::GetLocalStreamByIndex,
stream, &streamInfo));
stream));
} else {
mozilla::SyncRunnable::DispatchToThread(
gMainThread, WrapRunnableRet(
gMainThread, WrapRunnableRet(&streamInfo,
pc->media(), &PeerConnectionMedia::GetRemoteStreamByIndex,
stream, &streamInfo));
stream));
}
if (!streamInfo) {
@ -4729,7 +4723,7 @@ int main(int argc, char **argv) {
int result;
gGtestThread->Dispatch(
WrapRunnableNMRet(gtest_main, argc, argv, &result), NS_DISPATCH_NORMAL);
WrapRunnableNMRet(&result, gtest_main, argc, argv), NS_DISPATCH_NORMAL);
// Here we handle the event queue for dispatches to the main thread
// When the GTest thread is complete it will send one more dispatch

View File

@ -43,8 +43,8 @@ def ancestors(path):
def samepath(path1, path2):
if hasattr(os.path, 'samefile'):
return os.path.samefile(path1, path2)
return os.path.normpath(os.path.realpath(path1)) == \
os.path.normpath(os.path.realpath(path2))
return os.path.normcase(os.path.realpath(path1)) == \
os.path.normcase(os.path.realpath(path2))
class BadEnvironmentException(Exception):
"""Base class for errors raised when the build environment is not sane."""

View File

@ -66,6 +66,7 @@ MemoryStats.dump = function (testNumber,
var mrm = MemoryStats._getService("@mozilla.org/memory-reporter-manager;1",
"nsIMemoryReporterManager");
var statMessage = "";
for (var stat in MemoryStats._hasMemoryStatistics) {
var supported = MemoryStats._hasMemoryStatistics[stat];
var firstAccess = false;
@ -80,11 +81,15 @@ MemoryStats.dump = function (testNumber,
MemoryStats._hasMemoryStatistics[stat] = supported;
}
if (supported == MEM_STAT_SUPPORTED) {
info("MEMORY STAT " + stat + " after test: " + mrm[stat]);
var sizeInMB = Math.round(mrm[stat] / (1024 * 1024));
statMessage += " | " + stat + " " + sizeInMB + "MB";
} else if (firstAccess) {
info("MEMORY STAT " + stat + " not supported in this build configuration.");
}
}
if (statMessage.length > 0) {
info("MEMORY STAT" + statMessage);
}
if (dumpAboutMemory) {
var basename = "about-memory-" + testNumber + ".json.gz";

View File

@ -1,4 +1,4 @@
{
"repo": "https://hg.mozilla.org/build/mozharness",
"revision": "526075bc2e35"
"revision": "321d9dcec7b2"
}

View File

@ -311,16 +311,28 @@ GetCurTraceInfo(uint64_t* aOutSourceEventId, uint64_t* aOutParentTaskId,
void
LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId,
SourceEventType aSourceEventType)
{
LogDispatch(aTaskId, aParentTaskId, aSourceEventId, aSourceEventType, 0);
}
void
LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId,
SourceEventType aSourceEventType, int aDelayTimeMs)
{
TraceInfo* info = GetOrCreateTraceInfo();
ENSURE_TRUE_VOID(info);
// aDelayTimeMs is the expected delay time in milliseconds, thus the dispatch
// time calculated of it might be slightly off in the real world.
uint64_t time = (aDelayTimeMs <= 0) ? GetTimestamp() :
GetTimestamp() + aDelayTimeMs;
// Log format:
// [0 taskId dispatchTime sourceEventId sourceEventType parentTaskId]
nsCString* log = info->AppendLog();
if (log) {
log->AppendPrintf("%d %lld %lld %lld %d %lld",
ACTION_DISPATCH, aTaskId, GetTimestamp(), aSourceEventId,
ACTION_DISPATCH, aTaskId, time, aSourceEventId,
aSourceEventType, aParentTaskId);
}
}

View File

@ -37,10 +37,6 @@ namespace tasktracer {
enum {
FORKED_AFTER_NUWA = 1 << 0
};
void InitTaskTracer(uint32_t aFlags = 0);
void ShutdownTaskTracer();
class FakeTracedTask;
enum SourceEventType {
Unknown = 0,
@ -59,6 +55,9 @@ public:
~AutoSourceEvent();
};
void InitTaskTracer(uint32_t aFlags = 0);
void ShutdownTaskTracer();
// Add a label to the currently running task, aFormat is the message to log,
// followed by corresponding parameters.
void AddLabel(const char* aFormat, ...);
@ -78,8 +77,6 @@ Task* CreateTracedTask(Task* aTask);
already_AddRefed<nsIRunnable> CreateTracedRunnable(nsIRunnable* aRunnable);
already_AddRefed<FakeTracedTask> CreateFakeTracedTask(int* aVptr);
// Free the TraceInfo allocated on a thread's TLS. Currently we are wrapping
// tasks running on nsThreads and base::thread, so FreeTraceInfo is called at
// where nsThread and base::thread release themselves.

View File

@ -86,6 +86,10 @@ enum ActionType {
void LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId,
uint64_t aSourceEventId, SourceEventType aSourceEventType);
void LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId,
uint64_t aSourceEventId, SourceEventType aSourceEventType,
int aDelayTimeMs);
void LogBegin(uint64_t aTaskId, uint64_t aSourceEventId);
void LogEnd(uint64_t aTaskId, uint64_t aSourceEventId);

View File

@ -7,49 +7,80 @@
#include "GeckoTaskTracerImpl.h"
#include "TracedTaskCommon.h"
// NS_ENSURE_TRUE_VOID() without the warning on the debug build.
#define ENSURE_TRUE_VOID(x) \
do { \
if (MOZ_UNLIKELY(!(x))) { \
return; \
} \
} while(0)
namespace mozilla {
namespace tasktracer {
TracedTaskCommon::TracedTaskCommon()
: mSourceEventId(0)
, mSourceEventType(SourceEventType::Unknown)
: mSourceEventType(SourceEventType::Unknown)
, mSourceEventId(0)
, mParentTaskId(0)
, mTaskId(0)
, mIsTraceInfoInit(false)
{
}
TracedTaskCommon::~TracedTaskCommon()
{
Init();
}
void
TracedTaskCommon::Init()
{
TraceInfo* info = GetOrCreateTraceInfo();
NS_ENSURE_TRUE_VOID(info);
ENSURE_TRUE_VOID(info);
mTaskId = GenNewUniqueTaskId();
mSourceEventId = info->mCurTraceSourceId;
mSourceEventType = info->mCurTraceSourceType;
LogDispatch(mTaskId, info->mCurTaskId, mSourceEventId, mSourceEventType);
mParentTaskId = info->mCurTaskId;
mIsTraceInfoInit = true;
}
void
TracedTaskCommon::SetTraceInfo()
TracedTaskCommon::DispatchTask(int aDelayTimeMs)
{
TraceInfo* info = GetOrCreateTraceInfo();
if (!info) {
return;
}
info->mCurTraceSourceId = mSourceEventId;
info->mCurTraceSourceType = mSourceEventType;
info->mCurTaskId = mTaskId;
LogDispatch(mTaskId, mParentTaskId, mSourceEventId, mSourceEventType,
aDelayTimeMs);
}
void
TracedTaskCommon::ClearTraceInfo()
TracedTaskCommon::GetTLSTraceInfo()
{
TraceInfo* info = GetOrCreateTraceInfo();
if (!info) {
return;
ENSURE_TRUE_VOID(info);
mSourceEventType = info->mCurTraceSourceType;
mSourceEventId = info->mCurTraceSourceId;
mTaskId = info->mCurTaskId;
mIsTraceInfoInit = true;
}
void
TracedTaskCommon::SetTLSTraceInfo()
{
TraceInfo* info = GetOrCreateTraceInfo();
ENSURE_TRUE_VOID(info);
if (mIsTraceInfoInit) {
info->mCurTraceSourceId = mSourceEventId;
info->mCurTraceSourceType = mSourceEventType;
info->mCurTaskId = mTaskId;
}
}
void
TracedTaskCommon::ClearTLSTraceInfo()
{
TraceInfo* info = GetOrCreateTraceInfo();
ENSURE_TRUE_VOID(info);
info->mCurTraceSourceId = 0;
info->mCurTraceSourceType = SourceEventType::Unknown;
@ -63,19 +94,23 @@ TracedRunnable::TracedRunnable(nsIRunnable* aOriginalObj)
: TracedTaskCommon()
, mOriginalObj(aOriginalObj)
{
Init();
LogVirtualTablePtr(mTaskId, mSourceEventId, *(int**)(aOriginalObj));
}
TracedRunnable::~TracedRunnable()
{
}
NS_IMETHODIMP
TracedRunnable::Run()
{
SetTLSTraceInfo();
LogBegin(mTaskId, mSourceEventId);
SetTraceInfo();
nsresult rv = mOriginalObj->Run();
ClearTraceInfo();
LogEnd(mTaskId, mSourceEventId);
ClearTLSTraceInfo();
return rv;
}
@ -86,54 +121,26 @@ TracedTask::TracedTask(Task* aOriginalObj)
: TracedTaskCommon()
, mOriginalObj(aOriginalObj)
{
Init();
LogVirtualTablePtr(mTaskId, mSourceEventId, *(int**)(aOriginalObj));
}
TracedTask::~TracedTask()
{
if (mOriginalObj) {
delete mOriginalObj;
mOriginalObj = nullptr;
}
}
void
TracedTask::Run()
{
SetTLSTraceInfo();
LogBegin(mTaskId, mSourceEventId);
SetTraceInfo();
mOriginalObj->Run();
ClearTraceInfo();
LogEnd(mTaskId, mSourceEventId);
}
FakeTracedTask::FakeTracedTask(int* aVptr)
: TracedTaskCommon()
{
LogVirtualTablePtr(mTaskId, mSourceEventId, aVptr);
}
void
FakeTracedTask::BeginFakeTracedTask()
{
LogBegin(mTaskId, mSourceEventId);
SetTraceInfo();
}
void
FakeTracedTask::EndFakeTracedTask()
{
ClearTraceInfo();
LogEnd(mTaskId, mSourceEventId);
}
AutoRunFakeTracedTask::AutoRunFakeTracedTask(FakeTracedTask* aFakeTracedTask)
: mFakeTracedTask(aFakeTracedTask)
{
if (mFakeTracedTask) {
mFakeTracedTask->BeginFakeTracedTask();
}
}
AutoRunFakeTracedTask::~AutoRunFakeTracedTask()
{
if (mFakeTracedTask) {
mFakeTracedTask->EndFakeTracedTask();
}
ClearTLSTraceInfo();
}
/**
@ -158,16 +165,5 @@ CreateTracedTask(Task* aTask)
return task;
}
/**
* CreateFakeTracedTask() returns a FakeTracedTask tracking the event which is
* not dispatched from its parent task directly, such as timer events.
*/
already_AddRefed<FakeTracedTask>
CreateFakeTracedTask(int* aVptr)
{
nsRefPtr<FakeTracedTask> task(new FakeTracedTask(aVptr));
return task.forget();
}
} // namespace tasktracer
} // namespace mozilla

View File

@ -19,22 +19,25 @@ class TracedTaskCommon
{
public:
TracedTaskCommon();
virtual ~TracedTaskCommon() {}
virtual ~TracedTaskCommon();
void DispatchTask(int aDelayTimeMs = 0);
void SetTLSTraceInfo();
void GetTLSTraceInfo();
void ClearTLSTraceInfo();
protected:
void Init();
// Sets up the metadata on the current thread's TraceInfo for this task.
// After Run(), ClearTraceInfo is called to reset the metadata.
void SetTraceInfo();
void ClearTraceInfo();
// Its own task Id, an unique number base on its thread Id and a last unique
// task Id stored in its TraceInfo.
uint64_t mTaskId;
uint64_t mSourceEventId;
// TraceInfo of TLS will be set by the following parameters, including source
// event type, source event ID, parent task ID, and task ID of this traced
// task/runnable.
SourceEventType mSourceEventType;
uint64_t mSourceEventId;
uint64_t mParentTaskId;
uint64_t mTaskId;
bool mIsTraceInfoInit;
};
class TracedRunnable : public TracedTaskCommon
@ -46,7 +49,7 @@ public:
TracedRunnable(nsIRunnable* aOriginalObj);
private:
virtual ~TracedRunnable() {}
virtual ~TracedRunnable();
nsCOMPtr<nsIRunnable> mOriginalObj;
};
@ -56,13 +59,7 @@ class TracedTask : public TracedTaskCommon
{
public:
TracedTask(Task* aOriginalObj);
~TracedTask()
{
if (mOriginalObj) {
delete mOriginalObj;
mOriginalObj = nullptr;
}
}
~TracedTask();
virtual void Run();
@ -70,34 +67,6 @@ private:
Task* mOriginalObj;
};
// FakeTracedTask is for tracking events that are not directly dispatched from
// their parents, e.g. The timer events.
class FakeTracedTask : public TracedTaskCommon
{
public:
NS_INLINE_DECL_REFCOUNTING(FakeTracedTask)
FakeTracedTask(int* aVptr);
void BeginFakeTracedTask();
void EndFakeTracedTask();
private:
virtual ~FakeTracedTask() {}
// No copy allowed.
FakeTracedTask() = delete;
FakeTracedTask(const FakeTracedTask& aTask) = delete;
FakeTracedTask& operator=(const FakeTracedTask& aTask) = delete;
};
class AutoRunFakeTracedTask
{
public:
AutoRunFakeTracedTask(FakeTracedTask* aFakeTracedTask);
~AutoRunFakeTracedTask();
private:
nsRefPtr<FakeTracedTask> mFakeTracedTask;
};
} // namespace tasktracer
} // namespace mozilla

View File

@ -452,9 +452,9 @@ TimerThread::AddTimerInternal(nsTimerImpl* aTimer)
NS_ADDREF(aTimer);
#ifdef MOZ_TASK_TRACER
// Create a FakeTracedTask, and dispatch it here. This is the start point of
// the latency.
aTimer->DispatchTracedTask();
// Caller of AddTimer is the parent task of its timer event, so we store the
// TraceInfo here for later used.
aTimer->GetTLSTraceInfo();
#endif
return insertSlot - mTimers.Elements();

View File

@ -72,6 +72,7 @@
#ifdef MOZ_TASK_TRACER
#include "GeckoTaskTracer.h"
#include "TracedTaskCommon.h"
using namespace mozilla::tasktracer;
#endif
@ -540,6 +541,7 @@ nsThread::DispatchInternal(nsIRunnable* aEvent, uint32_t aFlags,
#ifdef MOZ_TASK_TRACER
nsCOMPtr<nsIRunnable> tracedRunnable = CreateTracedRunnable(aEvent);
(static_cast<TracedRunnable*>(tracedRunnable.get()))->DispatchTask();
aEvent = tracedRunnable;
#endif

View File

@ -17,6 +17,10 @@
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_TASK_TRACER
#include "GeckoTaskTracerImpl.h"
using namespace mozilla::tasktracer;
#endif
using mozilla::Atomic;
using mozilla::LogLevel;
@ -556,13 +560,6 @@ nsTimerImpl::Fire()
js::ProfileEntry::Category::OTHER);
#endif
#ifdef MOZ_TASK_TRACER
// mTracedTask is an instance of FakeTracedTask created by
// DispatchTracedTask(). AutoRunFakeTracedTask logs the begin/end time of the
// timer/FakeTracedTask instance in ctor/dtor.
mozilla::tasktracer::AutoRunFakeTracedTask runTracedTask(mTracedTask);
#endif
TimeStamp now = TimeStamp::Now();
if (MOZ_LOG_TEST(GetTimerLog(), LogLevel::Debug)) {
TimeDuration a = now - mStart; // actual delay in intervals
@ -752,6 +749,14 @@ nsTimerImpl::PostTimerEvent(already_AddRefed<nsTimerImpl> aTimerRef)
}
}
#ifdef MOZ_TASK_TRACER
// During the dispatch of TimerEvent, we overwrite the current TraceInfo
// partially with the info saved in timer earlier, and restore it back by
// AutoSaveCurTraceInfo.
AutoSaveCurTraceInfo saveCurTraceInfo;
(timer->GetTracedTask()).SetTLSTraceInfo();
#endif
nsIEventTarget* target = timer->mEventTarget;
event->SetTimer(timer.forget());
@ -795,3 +800,18 @@ nsTimerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this);
}
#ifdef MOZ_TASK_TRACER
void
nsTimerImpl::GetTLSTraceInfo()
{
mTracedTask.GetTLSTraceInfo();
}
TracedTaskCommon
nsTimerImpl::GetTracedTask()
{
return mTracedTask;
}
#endif

View File

@ -59,10 +59,8 @@ public:
}
#ifdef MOZ_TASK_TRACER
void DispatchTracedTask()
{
mTracedTask = mozilla::tasktracer::CreateFakeTracedTask(*(int**)(this));
}
void GetTLSTraceInfo();
mozilla::tasktracer::TracedTaskCommon GetTracedTask();
#endif
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
@ -150,7 +148,7 @@ private:
TimeStamp mTimeout;
#ifdef MOZ_TASK_TRACER
nsRefPtr<mozilla::tasktracer::FakeTracedTask> mTracedTask;
mozilla::tasktracer::TracedTaskCommon mTracedTask;
#endif
TimeStamp mStart, mStart2;