mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-30 05:35:31 +00:00
Merge m-c to fx-team.
This commit is contained in:
commit
f20ed7fb67
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "47d1ef9819810cecf9ce8cdcfd7f211530e43668",
|
||||
"revision": "4cdfe9307db3882da00e49361aa2f6788c9efe54",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -282,13 +282,6 @@ public:
|
||||
uint16_t ReadyState();
|
||||
|
||||
// request
|
||||
void Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv)
|
||||
{
|
||||
Open(aMethod, aUrl, true,
|
||||
mozilla::dom::Optional<nsAString>(),
|
||||
mozilla::dom::Optional<nsAString>(),
|
||||
aRv);
|
||||
}
|
||||
void Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
|
||||
const mozilla::dom::Optional<nsAString>& aUser,
|
||||
const mozilla::dom::Optional<nsAString>& aPassword,
|
||||
|
@ -27,15 +27,11 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
is(doc.doctype.internalSubset, null, "internalSubset should be null!");
|
||||
isElement(doc.documentElement, "html");
|
||||
isElement(doc.documentElement.firstChild, "head");
|
||||
if (title !== undefined) {
|
||||
is(doc.documentElement.firstChild.childNodes.length, 1);
|
||||
isElement(doc.documentElement.firstChild.firstChild, "title");
|
||||
// Doesn't always work out in WebKit.
|
||||
ok(doc.documentElement.firstChild.firstChild.firstChild, "Need a text node.");
|
||||
is(doc.documentElement.firstChild.firstChild.firstChild.data, expectedtitle);
|
||||
} else {
|
||||
is(doc.documentElement.firstChild.childNodes.length, 0);
|
||||
}
|
||||
is(doc.documentElement.firstChild.childNodes.length, 1);
|
||||
isElement(doc.documentElement.firstChild.firstChild, "title");
|
||||
// Doesn't always work out in WebKit.
|
||||
ok(doc.documentElement.firstChild.firstChild.firstChild, "Need a text node.");
|
||||
is(doc.documentElement.firstChild.firstChild.firstChild.data, expectedtitle);
|
||||
isElement(doc.documentElement.lastChild, "body");
|
||||
is(doc.documentElement.lastChild.childNodes.length, 0);
|
||||
((!title || title.indexOf("\f") === -1) ? is : todo_is)
|
||||
@ -45,7 +41,7 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
}
|
||||
checkDoc("", "", "");
|
||||
checkDoc(null, "null", "null");
|
||||
checkDoc(undefined, "", "");
|
||||
checkDoc(undefined, "undefined", "undefined");
|
||||
checkDoc("foo bar baz", "foo bar baz", "foo bar baz");
|
||||
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz");
|
||||
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz");
|
||||
|
@ -477,58 +477,6 @@ private:
|
||||
|
||||
NS_IMPL_ISUPPORTS1(DirPickerRecursiveFileEnumerator, nsISimpleEnumerator)
|
||||
|
||||
class DirPickerBuildFileListTask MOZ_FINAL
|
||||
: public nsRunnable
|
||||
{
|
||||
public:
|
||||
DirPickerBuildFileListTask(HTMLInputElement* aInput, nsIFile* aTopDir)
|
||||
: mInput(aInput)
|
||||
, mTopDir(aTopDir)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (!NS_IsMainThread()) {
|
||||
// Build up list of nsDOMFileFile 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<nsIDOMFile> domFile = do_QueryInterface(tmp);
|
||||
MOZ_ASSERT(domFile);
|
||||
mFileList.AppendElement(domFile);
|
||||
mInput->SetFileListProgress(mFileList.Length());
|
||||
}
|
||||
return NS_DispatchToMainThread(this);
|
||||
}
|
||||
|
||||
// Now back on the main thread, set the list on our HTMLInputElement:
|
||||
if (mFileList.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
// 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);
|
||||
mInput->MaybeDispatchProgressEvent(true); // last progress event
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<HTMLInputElement> mInput;
|
||||
nsCOMPtr<nsIFile> mTopDir;
|
||||
nsTArray<nsCOMPtr<nsIDOMFile> > mFileList;
|
||||
};
|
||||
|
||||
/**
|
||||
* This may return nullptr if aDomFile's implementation of
|
||||
* nsIDOMFile::mozFullPathInternal does not successfully return a non-empty
|
||||
@ -554,6 +502,113 @@ DOMFileToLocalFile(nsIDOMFile* aDomFile)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class DirPickerFileListBuilderTask MOZ_FINAL
|
||||
: public nsRunnable
|
||||
{
|
||||
public:
|
||||
DirPickerFileListBuilderTask(HTMLInputElement* aInput, nsIFile* aTopDir)
|
||||
: mPreviousFileListLength(0)
|
||||
, mInput(aInput)
|
||||
, mTopDir(aTopDir)
|
||||
, mFileListLength(0)
|
||||
, mCanceled(0)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (!NS_IsMainThread()) {
|
||||
// Build up list of nsDOMFileFile 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<nsIDOMFile> domFile = do_QueryInterface(tmp);
|
||||
MOZ_ASSERT(domFile);
|
||||
mFileList.AppendElement(domFile);
|
||||
mFileListLength = mFileList.Length();
|
||||
if (mCanceled) {
|
||||
NS_ASSERTION(!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;
|
||||
}
|
||||
|
||||
// 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 = 1; // 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<nsCOMPtr<nsIDOMFile> > 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;
|
||||
|
||||
// We'd prefer this member to be bool, but we don't support Atomic<bool>.
|
||||
mozilla::Atomic<uint32_t> mCanceled;
|
||||
};
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
||||
{
|
||||
@ -561,6 +616,8 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mInput->CancelDirectoryPickerScanIfRunning();
|
||||
|
||||
int16_t mode;
|
||||
mFilePicker->GetMode(&mode);
|
||||
|
||||
@ -590,14 +647,14 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
||||
= do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
NS_ASSERTION(target, "Must have stream transport service");
|
||||
|
||||
mInput->ResetProgressCounters();
|
||||
mInput->StartProgressEventTimer();
|
||||
|
||||
// DirPickerBuildFileListTask takes care of calling SetFiles() and
|
||||
// DirPickerFileListBuilderTask takes care of calling SetFiles() and
|
||||
// dispatching the "change" event.
|
||||
nsRefPtr<DirPickerBuildFileListTask> event =
|
||||
new DirPickerBuildFileListTask(mInput.get(), pickedDir.get());
|
||||
return target->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
mInput->mDirPickerFileListBuilderTask =
|
||||
new DirPickerFileListBuilderTask(mInput.get(), pickedDir.get());
|
||||
return target->Dispatch(mInput->mDirPickerFileListBuilderTask,
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// Collect new selected filenames
|
||||
@ -1020,8 +1077,6 @@ static nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
|
||||
HTMLInputElement::HTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
FromParser aFromParser)
|
||||
: nsGenericHTMLFormElementWithState(aNodeInfo)
|
||||
, mFileListProgress(0)
|
||||
, mLastFileListProgress(0)
|
||||
, mType(kInputDefaultType->value)
|
||||
, mDisabledChanged(false)
|
||||
, mValueChanged(false)
|
||||
@ -2463,6 +2518,20 @@ HTMLInputElement::OpenDirectoryPicker(ErrorResult& aRv)
|
||||
InitFilePicker(FILE_PICKER_DIRECTORY);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::CancelDirectoryPickerScanIfRunning()
|
||||
{
|
||||
if (!mDirPickerFileListBuilderTask) {
|
||||
return;
|
||||
}
|
||||
if (mProgressTimer) {
|
||||
mProgressTimerIsActive = false;
|
||||
mProgressTimer->Cancel();
|
||||
}
|
||||
mDirPickerFileListBuilderTask->Cancel();
|
||||
mDirPickerFileListBuilderTask = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::StartProgressEventTimer()
|
||||
{
|
||||
@ -2507,8 +2576,10 @@ HTMLInputElement::MaybeDispatchProgressEvent(bool aFinalProgress)
|
||||
mProgressTimer->Cancel();
|
||||
}
|
||||
|
||||
uint32_t fileListLength = mDirPickerFileListBuilderTask->GetFileListLength();
|
||||
|
||||
if (mProgressTimerIsActive ||
|
||||
mFileListProgress == mLastFileListProgress) {
|
||||
fileListLength == mDirPickerFileListBuilderTask->mPreviousFileListLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2516,10 +2587,11 @@ HTMLInputElement::MaybeDispatchProgressEvent(bool aFinalProgress)
|
||||
StartProgressEventTimer();
|
||||
}
|
||||
|
||||
mLastFileListProgress = mFileListProgress;
|
||||
mDirPickerFileListBuilderTask->mPreviousFileListLength = fileListLength;
|
||||
|
||||
DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR),
|
||||
false, mLastFileListProgress,
|
||||
false,
|
||||
mDirPickerFileListBuilderTask->mPreviousFileListLength,
|
||||
0);
|
||||
}
|
||||
|
||||
@ -2542,12 +2614,16 @@ HTMLInputElement::DispatchProgressEvent(const nsAString& aType,
|
||||
return;
|
||||
}
|
||||
|
||||
progress->InitProgressEvent(aType, false, false, aLengthComputable,
|
||||
progress->InitProgressEvent(aType, false, true, aLengthComputable,
|
||||
aLoaded, (aTotal == UINT64_MAX) ? 0 : aTotal);
|
||||
|
||||
event->SetTrusted(true);
|
||||
|
||||
DispatchDOMEvent(nullptr, event, nullptr, nullptr);
|
||||
bool doDefaultAction;
|
||||
rv = DispatchEvent(event, &doDefaultAction);
|
||||
if (NS_SUCCEEDED(rv) && !doDefaultAction) {
|
||||
CancelDirectoryPickerScanIfRunning();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -32,6 +32,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Date;
|
||||
class DirPickerFileListBuilderTask;
|
||||
|
||||
class UploadLastDir MOZ_FINAL : public nsIObserver, public nsSupportsWeakReference {
|
||||
public:
|
||||
@ -87,6 +88,8 @@ class HTMLInputElement MOZ_FINAL : public nsGenericHTMLFormElementWithState,
|
||||
public nsITimerCallback,
|
||||
public nsIConstraintValidation
|
||||
{
|
||||
friend class DirPickerFileListBuilderTask;
|
||||
|
||||
public:
|
||||
using nsIConstraintValidation::GetValidationMessage;
|
||||
using nsIConstraintValidation::CheckValidity;
|
||||
@ -402,12 +405,8 @@ public:
|
||||
nsDOMFileList* GetFiles();
|
||||
|
||||
void OpenDirectoryPicker(ErrorResult& aRv);
|
||||
void CancelDirectoryPickerScanIfRunning();
|
||||
|
||||
void ResetProgressCounters()
|
||||
{
|
||||
mFileListProgress = 0;
|
||||
mLastFileListProgress = 0;
|
||||
}
|
||||
void StartProgressEventTimer();
|
||||
void MaybeDispatchProgressEvent(bool aFinalProgress);
|
||||
void DispatchProgressEvent(const nsAString& aType,
|
||||
@ -677,13 +676,6 @@ public:
|
||||
|
||||
// XPCOM GetPhonetic() is OK
|
||||
|
||||
void SetFileListProgress(uint32_t mFileCount)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread(),
|
||||
"Why are we calling this on the main thread?");
|
||||
mFileListProgress = mFileCount;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual JSObject* WrapNode(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
@ -1162,6 +1154,8 @@ protected:
|
||||
|
||||
nsRefPtr<nsDOMFileList> mFileList;
|
||||
|
||||
nsRefPtr<DirPickerFileListBuilderTask> mDirPickerFileListBuilderTask;
|
||||
|
||||
nsString mStaticDocFileList;
|
||||
|
||||
/**
|
||||
@ -1202,19 +1196,6 @@ protected:
|
||||
// Float value returned by GetStep() when the step attribute is set to 'any'.
|
||||
static const Decimal kStepAny;
|
||||
|
||||
/**
|
||||
* The number of files added to the FileList being built off-main-thread when
|
||||
* mType == NS_FORM_INPUT_FILE and the user selects a directory. This is set
|
||||
* off the main thread, read on main thread.
|
||||
*/
|
||||
mozilla::Atomic<uint32_t> mFileListProgress;
|
||||
|
||||
/**
|
||||
* The number of files added to the FileList at the time the last progress
|
||||
* event was fired.
|
||||
*/
|
||||
uint32_t mLastFileListProgress;
|
||||
|
||||
/**
|
||||
* The type of this input (<input type=...>) as an integer.
|
||||
* @see nsIFormControl.h (specifically NS_FORM_INPUT_*)
|
||||
|
@ -447,6 +447,8 @@ public:
|
||||
virtual bool IsDormantNeeded() { return false; }
|
||||
// Release media resources they should be released in dormant state
|
||||
virtual void ReleaseMediaResources() {};
|
||||
// Release the decoder during shutdown
|
||||
virtual void ReleaseDecoder() {};
|
||||
|
||||
// Resets all state related to decoding, emptying all buffers etc.
|
||||
virtual nsresult ResetDecode();
|
||||
|
@ -320,7 +320,13 @@ public:
|
||||
void SetFragmentEndTime(int64_t aEndTime);
|
||||
|
||||
// Drop reference to decoder. Only called during shutdown dance.
|
||||
void ReleaseDecoder() { mDecoder = nullptr; }
|
||||
void ReleaseDecoder() {
|
||||
MOZ_ASSERT(mReader);
|
||||
if (mReader) {
|
||||
mReader->ReleaseDecoder();
|
||||
}
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
||||
// Called when a "MozAudioAvailable" event listener is added to the media
|
||||
// element. Called on the main thread.
|
||||
|
@ -69,6 +69,13 @@ void MediaOmxReader::ReleaseMediaResources()
|
||||
}
|
||||
}
|
||||
|
||||
void MediaOmxReader::ReleaseDecoder()
|
||||
{
|
||||
if (mOmxDecoder.get()) {
|
||||
mOmxDecoder->ReleaseDecoder();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
virtual bool IsDormantNeeded();
|
||||
virtual void ReleaseMediaResources();
|
||||
|
||||
virtual void ReleaseDecoder() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags);
|
||||
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
|
||||
|
@ -62,8 +62,8 @@ private:
|
||||
};
|
||||
|
||||
// When loading an MP3 stream from a file, we need to parse the file's
|
||||
// content to find its duration. Reading files of 100 Mib or more can
|
||||
// delay the player app noticably, so the file os read and decoded in
|
||||
// content to find its duration. Reading files of 100 MiB or more can
|
||||
// delay the player app noticably, so the file is read and decoded in
|
||||
// smaller chunks.
|
||||
//
|
||||
// We first read on the decode thread, but parsing must be done on the
|
||||
@ -79,7 +79,9 @@ private:
|
||||
class OmxDecoderNotifyDataArrivedRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
OmxDecoderNotifyDataArrivedRunnable(android::OmxDecoder* aOmxDecoder, const char* aBuffer, uint64_t aLength, int64_t aOffset, uint64_t aFullLength)
|
||||
OmxDecoderNotifyDataArrivedRunnable(android::OmxDecoder* aOmxDecoder,
|
||||
const char* aBuffer, uint64_t aLength,
|
||||
int64_t aOffset, uint64_t aFullLength)
|
||||
: mOmxDecoder(aOmxDecoder),
|
||||
mBuffer(aBuffer),
|
||||
mLength(aLength),
|
||||
@ -96,24 +98,7 @@ public:
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
|
||||
const char* buffer = mBuffer.get();
|
||||
|
||||
while (mLength) {
|
||||
uint32_t length = std::min<uint64_t>(mLength, UINT32_MAX);
|
||||
mOmxDecoder->NotifyDataArrived(mBuffer.get(), mLength, mOffset);
|
||||
|
||||
buffer += length;
|
||||
mLength -= length;
|
||||
mOffset += length;
|
||||
}
|
||||
|
||||
if (mOffset < mFullLength) {
|
||||
// We cannot read data in the main thread because it
|
||||
// might block for too long. Instead we post an IO task
|
||||
// to the IO thread if there is more data available.
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new OmxDecoderProcessCachedDataTask(mOmxDecoder.get(), mOffset));
|
||||
}
|
||||
|
||||
NotifyDataArrived();
|
||||
Completed();
|
||||
|
||||
return NS_OK;
|
||||
@ -130,6 +115,32 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void NotifyDataArrived()
|
||||
{
|
||||
const char* buffer = mBuffer.get();
|
||||
|
||||
while (mLength) {
|
||||
uint32_t length = std::min<uint64_t>(mLength, UINT32_MAX);
|
||||
bool success = mOmxDecoder->NotifyDataArrived(buffer, mLength,
|
||||
mOffset);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer += length;
|
||||
mLength -= length;
|
||||
mOffset += length;
|
||||
}
|
||||
|
||||
if (mOffset < mFullLength) {
|
||||
// We cannot read data in the main thread because it
|
||||
// might block for too long. Instead we post an IO task
|
||||
// to the IO thread if there is more data available.
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new OmxDecoderProcessCachedDataTask(mOmxDecoder.get(), mOffset));
|
||||
}
|
||||
}
|
||||
|
||||
// Call this function at the end of Run() to notify waiting
|
||||
// threads.
|
||||
void Completed()
|
||||
@ -400,7 +411,7 @@ bool OmxDecoder::TryLoad() {
|
||||
const char* audioMime;
|
||||
sp<MetaData> meta = mAudioTrack->getFormat();
|
||||
|
||||
if (meta->findCString(kKeyMIMEType, &audioMime) && !strcasecmp(audioMime, AUDIO_MP3)) {
|
||||
if (mIsMp3) {
|
||||
// Feed MP3 parser with cached data. Local files will be fully
|
||||
// cached already, network streams will update with sucessive
|
||||
// calls to NotifyDataArrived.
|
||||
@ -628,10 +639,15 @@ bool OmxDecoder::SetAudioFormat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void OmxDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
|
||||
void OmxDecoder::ReleaseDecoder()
|
||||
{
|
||||
if (!mAudioTrack.get() || !mIsMp3 || !mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
||||
bool OmxDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
|
||||
{
|
||||
if (!mAudioTrack.get() || !mIsMp3 || !mMP3FrameParser.IsMP3() || !mDecoder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
|
||||
@ -645,6 +661,8 @@ void OmxDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mDecoder->UpdateEstimatedMediaDuration(mDurationUs);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OmxDecoder::ReleaseVideoBuffer() {
|
||||
|
@ -181,7 +181,9 @@ public:
|
||||
bool SetVideoFormat();
|
||||
bool SetAudioFormat();
|
||||
|
||||
void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
|
||||
void ReleaseDecoder();
|
||||
|
||||
bool NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
|
||||
|
||||
void GetDuration(int64_t *durationUs) {
|
||||
*durationUs = mDurationUs;
|
||||
|
@ -998,34 +998,8 @@ nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
|
||||
previousHandler = handler;
|
||||
} while (1);
|
||||
|
||||
if (mBinding) {
|
||||
while (true) {
|
||||
XBLBindingSerializeDetails type;
|
||||
rv = aStream->Read8(&type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (type != XBLBinding_Serialize_Attribute) {
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t attrNamespace;
|
||||
rv = ReadNamespace(aStream, attrNamespace);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString attrName, attrValue;
|
||||
rv = aStream->ReadString(attrName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->ReadString(attrValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAtom> atomName = do_GetAtom(attrName);
|
||||
mBinding->SetAttr(attrNamespace, atomName, attrValue, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, read in the resources.
|
||||
while (true) {
|
||||
do {
|
||||
XBLBindingSerializeDetails type;
|
||||
rv = aStream->Read8(&type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -1042,7 +1016,7 @@ nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
|
||||
|
||||
AddResource(type == XBLBinding_Serialize_Stylesheet ? nsGkAtoms::stylesheet :
|
||||
nsGkAtoms::image, src);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
if (isFirstBinding) {
|
||||
aDocInfo->SetFirstPrototypeBinding(this);
|
||||
@ -1152,30 +1126,6 @@ nsXBLPrototypeBinding::Write(nsIObjectOutputStream* aStream)
|
||||
aStream->Write8(XBLBinding_Serialize_NoMoreItems);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mBinding) {
|
||||
uint32_t attributes = mBinding->GetAttrCount();
|
||||
nsAutoString attrValue;
|
||||
for (uint32_t i = 0; i < attributes; ++i) {
|
||||
const nsAttrName* attr = mBinding->GetAttrNameAt(i);
|
||||
nsDependentAtomString attrName = attr->Atom();
|
||||
mBinding->GetAttr(attr->NamespaceID(), attr->Atom(), attrValue);
|
||||
rv = aStream->Write8(XBLBinding_Serialize_Attribute);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = WriteNamespace(aStream, attr->NamespaceID());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->WriteWStringZ(attrName.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->WriteWStringZ(attrValue.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
aStream->Write8(XBLBinding_Serialize_NoMoreItems);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Write out the resources
|
||||
if (mResources) {
|
||||
rv = mResources->Write(aStream);
|
||||
|
@ -15,7 +15,7 @@ typedef uint8_t XBLBindingSerializeDetails;
|
||||
|
||||
// A version number to ensure we don't load cached data in a different
|
||||
// file format.
|
||||
#define XBLBinding_Serialize_Version 0x00000003
|
||||
#define XBLBinding_Serialize_Version 0x00000002
|
||||
|
||||
// Set for the first binding in a document
|
||||
#define XBLBinding_Serialize_IsFirstBinding 1
|
||||
@ -45,7 +45,6 @@ typedef uint8_t XBLBindingSerializeDetails;
|
||||
#define XBLBinding_Serialize_Handler 8
|
||||
#define XBLBinding_Serialize_Image 9
|
||||
#define XBLBinding_Serialize_Stylesheet 10
|
||||
#define XBLBinding_Serialize_Attribute 0xA
|
||||
#define XBLBinding_Serialize_Mask 0x0F
|
||||
#define XBLBinding_Serialize_ReadOnly 0x80
|
||||
|
||||
|
@ -703,8 +703,13 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const PR
|
||||
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_ALARM, index);
|
||||
} else if (keyStr.EqualsLiteral("audio.volume.telephony")) {
|
||||
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_TELEPHONY, index);
|
||||
} else {
|
||||
MOZ_ASSUME_UNREACHABLE("unexpected audio channel for volume control");
|
||||
} else if (!keyStr.EqualsLiteral("audio.volume.bt_sco")) {
|
||||
// bt_sco is not a valid audio channel so we manipulate it in
|
||||
// AudioManager.cpp. And the others should not be used.
|
||||
// We didn't use MOZ_ASSUME_UNREACHABLE here because any web content who
|
||||
// has permission of mozSettings can set any names then it can be easy to
|
||||
// crash the B2G.
|
||||
NS_WARNING("unexpected audio channel for volume control");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -2703,7 +2703,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
# A helper function for wrapping up the template body for
|
||||
# possibly-nullable objecty stuff
|
||||
def wrapObjectTemplate(templateBody, type, codeToSetNull, failureCode=None):
|
||||
if isNullOrUndefined and type.nullable():
|
||||
if isNullOrUndefined:
|
||||
assert type.nullable()
|
||||
# Just ignore templateBody and set ourselves to null.
|
||||
# Note that we don't have to worry about default values
|
||||
# here either, since we already examined this value.
|
||||
@ -3320,6 +3321,9 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||
"Default": "eStringify",
|
||||
"EmptyString": "eEmpty",
|
||||
"Null": "eNull",
|
||||
# For Missing it doesn't matter what we use here, since we'll never
|
||||
# call ConvertJSValueToString on undefined in that case.
|
||||
"Missing": "eStringify"
|
||||
}
|
||||
if type.nullable():
|
||||
# For nullable strings null becomes a null string.
|
||||
@ -3839,8 +3843,11 @@ class CGArgumentConverter(CGThing):
|
||||
"args[${index}]"
|
||||
).substitute(replacer)
|
||||
self.replacementVariables["mutableVal"] = self.replacementVariables["val"]
|
||||
haveValueCheck = string.Template(
|
||||
"args.hasDefined(${index})").substitute(replacer)
|
||||
if argument.treatUndefinedAs == "Missing":
|
||||
haveValueCheck = "args.hasDefined(${index})"
|
||||
else:
|
||||
haveValueCheck = "${index} < args.length()"
|
||||
haveValueCheck = string.Template(haveValueCheck).substitute(replacer)
|
||||
self.replacementVariables["haveValue"] = haveValueCheck
|
||||
self.descriptorProvider = descriptorProvider
|
||||
if self.argument.optional and not self.argument.defaultValue:
|
||||
@ -4981,6 +4988,15 @@ class CGMethodCall(CGThing):
|
||||
CGWrapper(CGIndenter(CGGeneric(code)), pre="\n", post="\n"))
|
||||
return
|
||||
|
||||
# We don't handle [TreatUndefinedAs=Missing] arguments in overload
|
||||
# resolution yet.
|
||||
for (_, sigArgs) in signatures:
|
||||
for arg in sigArgs:
|
||||
if arg.treatUndefinedAs == "Missing":
|
||||
raise TypeError("No support for [TreatUndefinedAs=Missing] "
|
||||
"handling in overload resolution yet: %s" %
|
||||
arg.location)
|
||||
|
||||
# Need to find the right overload
|
||||
maxArgCount = method.maxArgCount
|
||||
allowedArgCounts = method.allowedArgCounts
|
||||
@ -5070,30 +5086,22 @@ class CGMethodCall(CGThing):
|
||||
else:
|
||||
failureCode = None
|
||||
type = distinguishingType(signature)
|
||||
# The argument at index distinguishingIndex can't possibly be
|
||||
# unset here, because we've already checked that argc is large
|
||||
# enough that we can examine this argument. But note that we
|
||||
# still want to claim that optional arguments are optional, in
|
||||
# case undefined was passed in.
|
||||
argIsOptional = (distinguishingArgument(signature).optional and
|
||||
not distinguishingArgument(signature).defaultValue)
|
||||
# The argument at index distinguishingIndex can't possibly
|
||||
# be unset here, because we've already checked that argc is
|
||||
# large enough that we can examine this argument.
|
||||
testCode = instantiateJSToNativeConversion(
|
||||
getJSToNativeConversionInfo(type, descriptor,
|
||||
failureCode=failureCode,
|
||||
isDefinitelyObject=isDefinitelyObject,
|
||||
isNullOrUndefined=isNullOrUndefined,
|
||||
isOptional=argIsOptional,
|
||||
sourceDescription=(argDesc % (distinguishingIndex + 1))),
|
||||
{
|
||||
"declName" : "arg%d" % distinguishingIndex,
|
||||
"holderName" : ("arg%d" % distinguishingIndex) + "_holder",
|
||||
"val" : distinguishingArg,
|
||||
"mutableVal" : distinguishingArg,
|
||||
"obj" : "obj",
|
||||
"haveValue": "args.hasDefined(%d)" % distinguishingIndex
|
||||
},
|
||||
checkForValue=argIsOptional
|
||||
)
|
||||
"obj" : "obj"
|
||||
})
|
||||
caseBody.append(CGIndenter(testCode, indent));
|
||||
# If we got this far, we know we unwrapped to the right
|
||||
# C++ type, so just do the call. Start conversion with
|
||||
@ -5103,76 +5111,24 @@ class CGMethodCall(CGThing):
|
||||
getPerSignatureCall(signature, distinguishingIndex + 1),
|
||||
indent))
|
||||
|
||||
def hasConditionalConversion(type):
|
||||
"""
|
||||
Return whether the argument conversion for this type will be
|
||||
conditional on the type of incoming JS value. For example, for
|
||||
interface types the conversion is conditional on the incoming
|
||||
value being isObject().
|
||||
|
||||
For the types for which this returns false, we do not have to
|
||||
output extra isUndefined() or isNullOrUndefined() cases, because
|
||||
null/undefined values will just fall through into our
|
||||
unconditional conversion.
|
||||
"""
|
||||
if type.isString() or type.isEnum():
|
||||
return False
|
||||
if type.isBoolean():
|
||||
distinguishingTypes = (distinguishingType(s) for s in
|
||||
possibleSignatures)
|
||||
return any(t.isString() or t.isEnum() or t.isNumeric()
|
||||
for t in distinguishingTypes)
|
||||
if type.isNumeric():
|
||||
distinguishingTypes = (distinguishingType(s) for s in
|
||||
possibleSignatures)
|
||||
return any(t.isString() or t.isEnum()
|
||||
for t in distinguishingTypes)
|
||||
return True
|
||||
|
||||
def needsNullOrUndefinedCase(type):
|
||||
"""
|
||||
Return true if the type needs a special isNullOrUndefined() case
|
||||
"""
|
||||
return ((type.nullable() and
|
||||
hasConditionalConversion(type)) or
|
||||
type.isDictionary())
|
||||
|
||||
# First check for undefined and optional distinguishing arguments
|
||||
# and output a special branch for that case. Note that we don't
|
||||
# use distinguishingArgument here because we actualy want to
|
||||
# exclude variadic arguments. Also note that we skip this check if
|
||||
# we plan to output a isNullOrUndefined() special case for this
|
||||
# argument anyway, since that will subsume our isUndefined() check.
|
||||
# This is safe, because there can be at most one nullable
|
||||
# distinguishing argument, so if we're it we'll definitely get
|
||||
# picked up by the nullable handling. Also, we can skip this check
|
||||
# if the argument has an unconditional conversion later on.
|
||||
undefSigs = [s for s in possibleSignatures if
|
||||
distinguishingIndex < len(s[1]) and
|
||||
s[1][distinguishingIndex].optional and
|
||||
hasConditionalConversion(s[1][distinguishingIndex].type) and
|
||||
not needsNullOrUndefinedCase(s[1][distinguishingIndex].type)]
|
||||
# Can't have multiple signatures with an optional argument at the
|
||||
# same index.
|
||||
assert len(undefSigs) < 2
|
||||
if len(undefSigs) > 0:
|
||||
caseBody.append(CGGeneric("if (%s.isUndefined()) {" %
|
||||
distinguishingArg))
|
||||
tryCall(undefSigs[0], 2, isNullOrUndefined=True)
|
||||
caseBody.append(CGGeneric("}"))
|
||||
|
||||
# Next, check for null or undefined. That means looking for
|
||||
# First check for null or undefined. That means looking for
|
||||
# nullable arguments at the distinguishing index and outputting a
|
||||
# separate branch for them. But if the nullable argument has an
|
||||
# unconditional conversion, we don't need to do that. The reason
|
||||
# separate branch for them. But if the nullable argument is a
|
||||
# primitive, string, or enum, we don't need to do that. The reason
|
||||
# for that is that at most one argument at the distinguishing index
|
||||
# is nullable (since two nullable arguments are not
|
||||
# distinguishable), and null/undefined values will always fall
|
||||
# through to the unconditional conversion we have, if any, since
|
||||
# they will fail whatever the conditions on the input value are for
|
||||
# our other conversions.
|
||||
# distinguishable), and all the argument types other than
|
||||
# primitive/string/enum end up inside isObject() checks. So if our
|
||||
# nullable is a primitive/string/enum it's safe to not output the
|
||||
# extra branch: we'll fall through to conversion for those types,
|
||||
# which correctly handles null as needed, because isObject() will be
|
||||
# false for null and undefined.
|
||||
nullOrUndefSigs = [s for s in possibleSignatures
|
||||
if needsNullOrUndefinedCase(distinguishingType(s))]
|
||||
if ((distinguishingType(s).nullable() and not
|
||||
distinguishingType(s).isString() and not
|
||||
distinguishingType(s).isEnum() and not
|
||||
distinguishingType(s).isPrimitive()) or
|
||||
distinguishingType(s).isDictionary())]
|
||||
# Can't have multiple nullable types here
|
||||
assert len(nullOrUndefSigs) < 2
|
||||
if len(nullOrUndefSigs) > 0:
|
||||
|
@ -81,6 +81,11 @@ public:
|
||||
return !Equals(aOtherNullable);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return !mIsNull;
|
||||
}
|
||||
|
||||
// Make it possible to use a const Nullable of an array type with other
|
||||
// array types.
|
||||
template<typename U>
|
||||
|
@ -401,7 +401,12 @@ class IDLObjectWithIdentifier(IDLObject):
|
||||
if isDictionaryMember:
|
||||
raise WebIDLError("[TreatUndefinedAs] is not allowed for "
|
||||
"dictionary members", [self.location])
|
||||
if value == 'Null':
|
||||
if value == 'Missing':
|
||||
if not isOptional:
|
||||
raise WebIDLError("[TreatUndefinedAs=Missing] is only "
|
||||
"allowed on optional arguments",
|
||||
[self.location])
|
||||
elif value == 'Null':
|
||||
if not self.type.isDOMString():
|
||||
raise WebIDLError("[TreatUndefinedAs=Null] is only "
|
||||
"allowed on arguments or "
|
||||
@ -421,8 +426,8 @@ class IDLObjectWithIdentifier(IDLObject):
|
||||
[self.location])
|
||||
else:
|
||||
raise WebIDLError("[TreatUndefinedAs] must take the "
|
||||
"identifiers EmptyString or Null",
|
||||
[self.location])
|
||||
"identifiers EmptyString or Null or "
|
||||
"Missing", [self.location])
|
||||
self.treatUndefinedAs = value
|
||||
else:
|
||||
unhandledAttrs.append(attr)
|
||||
@ -3138,12 +3143,15 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
|
||||
def finish(self, scope):
|
||||
for overload in self._overloads:
|
||||
inOptionalArguments = False
|
||||
variadicArgument = None
|
||||
|
||||
arguments = overload.arguments
|
||||
for (idx, argument) in enumerate(arguments):
|
||||
if not argument.isComplete():
|
||||
argument.complete(scope)
|
||||
if argument.isComplete():
|
||||
continue
|
||||
|
||||
argument.complete(scope)
|
||||
assert argument.type.isComplete()
|
||||
|
||||
if (argument.type.isDictionary() or
|
||||
@ -3153,7 +3161,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
# end of the list or followed by optional arguments must be
|
||||
# optional.
|
||||
if (not argument.optional and
|
||||
all(arg.optional for arg in arguments[idx+1:])):
|
||||
(idx == len(arguments) - 1 or arguments[idx+1].optional)):
|
||||
raise WebIDLError("Dictionary argument or union "
|
||||
"argument containing a dictionary "
|
||||
"not followed by a required argument "
|
||||
@ -3171,6 +3179,13 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
if variadicArgument:
|
||||
raise WebIDLError("Variadic argument is not last argument",
|
||||
[variadicArgument.location])
|
||||
# Once we see an optional argument, there can't be any non-optional
|
||||
# arguments.
|
||||
if inOptionalArguments and not argument.optional:
|
||||
raise WebIDLError("Non-optional argument after optional "
|
||||
"arguments",
|
||||
[argument.location])
|
||||
inOptionalArguments = argument.optional
|
||||
if argument.variadic:
|
||||
variadicArgument = argument
|
||||
|
||||
@ -3215,7 +3230,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
return [overload for overload in self._overloads if
|
||||
len(overload.arguments) == argc or
|
||||
(len(overload.arguments) > argc and
|
||||
all(arg.optional for arg in overload.arguments[argc:])) or
|
||||
overload.arguments[argc].optional) or
|
||||
(len(overload.arguments) < argc and
|
||||
len(overload.arguments) > 0 and
|
||||
overload.arguments[-1].variadic)]
|
||||
@ -4045,6 +4060,21 @@ class Parser(Tokenizer):
|
||||
raise WebIDLError("stringifier must have DOMString return type",
|
||||
[self.getLocation(p, 2)])
|
||||
|
||||
inOptionalArguments = False
|
||||
variadicArgument = False
|
||||
for argument in arguments:
|
||||
# Only the last argument can be variadic
|
||||
if variadicArgument:
|
||||
raise WebIDLError("Only the last argument can be variadic",
|
||||
[variadicArgument.location])
|
||||
# Once we see an optional argument, there can't be any non-optional
|
||||
# arguments.
|
||||
if inOptionalArguments and not argument.optional:
|
||||
raise WebIDLError("Cannot have a non-optional argument following an optional argument",
|
||||
[argument.location])
|
||||
inOptionalArguments = argument.optional
|
||||
variadicArgument = argument if argument.variadic else None
|
||||
|
||||
# identifier might be None. This is only permitted for special methods.
|
||||
if not identifier:
|
||||
if not getter and not setter and not creator and \
|
||||
|
@ -171,23 +171,6 @@ def WebIDLTest(parser, harness):
|
||||
|
||||
harness.ok(threw, "Dictionary arg followed by optional arg must be optional")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
void doFoo(A arg1, optional long arg2, long arg3);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(not threw,
|
||||
"Dictionary arg followed by non-optional arg doesn't have to be optional")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
|
@ -11,9 +11,9 @@ def WebIDLTest(parser, harness):
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(not threw,
|
||||
"Should not have thrown on non-optional argument following "
|
||||
"optional argument.")
|
||||
harness.ok(threw,
|
||||
"Should have thrown on non-optional argument following optional "
|
||||
"argument.")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse("""
|
||||
|
@ -11,8 +11,6 @@ def WebIDLTest(parser, harness):
|
||||
void withVariadics(long... numbers);
|
||||
void withVariadics(TestOverloads iface);
|
||||
void withVariadics(long num, TestOverloads iface);
|
||||
void optionalTest();
|
||||
void optionalTest(optional long num1, long num2);
|
||||
};
|
||||
""")
|
||||
|
||||
@ -25,7 +23,7 @@ def WebIDLTest(parser, harness):
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name")
|
||||
harness.check(len(iface.members), 4, "Expect %s members" % 4)
|
||||
harness.check(len(iface.members), 3, "Expect %s members" % 3)
|
||||
|
||||
member = iface.members[0]
|
||||
harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName")
|
||||
@ -50,11 +48,3 @@ def WebIDLTest(parser, harness):
|
||||
harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName")
|
||||
harness.check(argument.identifier.name, "arg1", "Argument has the right name")
|
||||
harness.check(str(argument.type), "Long", "Argument has the right type")
|
||||
|
||||
member = iface.members[3]
|
||||
harness.check(len(member.overloadsForArgCount(0)), 1,
|
||||
"Only one overload for no args")
|
||||
harness.check(len(member.overloadsForArgCount(1)), 0,
|
||||
"No overloads for one arg")
|
||||
harness.check(len(member.overloadsForArgCount(2)), 1,
|
||||
"Only one overload for two args")
|
||||
|
@ -1,62 +1,51 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
results = parser.parse("""
|
||||
interface VariadicConstraints1 {
|
||||
void foo(byte... arg1, byte arg2);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw,
|
||||
"Should have thrown on variadic argument followed by required "
|
||||
"argument.")
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
results = parser.parse("""
|
||||
interface VariadicConstraints2 {
|
||||
void foo(byte... arg1, optional byte arg2);
|
||||
};
|
||||
""")
|
||||
results = parser.finish();
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw,
|
||||
"Should have thrown on variadic argument followed by optional "
|
||||
"argument.")
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
results = parser.parse("""
|
||||
interface VariadicConstraints3 {
|
||||
void foo(optional byte... arg1);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw,
|
||||
"Should have thrown on variadic argument explicitly flagged as "
|
||||
"optional.")
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
results = parser.parse("""
|
||||
interface VariadicConstraints4 {
|
||||
void foo(byte... arg1 = 0);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
|
@ -161,9 +161,9 @@ public:
|
||||
void PassByte(int8_t);
|
||||
int8_t ReceiveByte();
|
||||
void PassOptionalByte(const Optional<int8_t>&);
|
||||
void PassOptionalByteBeforeRequired(const Optional<int8_t>&, int8_t);
|
||||
void PassOptionalUndefinedMissingByte(const Optional<int8_t>&);
|
||||
void PassOptionalByteWithDefault(int8_t);
|
||||
void PassOptionalByteWithDefaultBeforeRequired(int8_t, int8_t);
|
||||
void PassOptionalUndefinedMissingByteWithDefault(int8_t);
|
||||
void PassNullableByte(const Nullable<int8_t>&);
|
||||
void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&);
|
||||
void PassVariadicByte(const Sequence<int8_t>&);
|
||||
@ -410,7 +410,9 @@ public:
|
||||
void PassString(const nsAString&);
|
||||
void PassNullableString(const nsAString&);
|
||||
void PassOptionalString(const Optional<nsAString>&);
|
||||
void PassOptionalUndefinedMissingString(const Optional<nsAString>&);
|
||||
void PassOptionalStringWithDefaultValue(const nsAString&);
|
||||
void PassOptionalUndefinedMissingStringWithDefaultValue(const nsAString&);
|
||||
void PassOptionalNullableString(const Optional<nsAString>&);
|
||||
void PassOptionalNullableStringWithDefaultValue(const nsAString&);
|
||||
void PassVariadicString(const Sequence<nsString>&);
|
||||
@ -629,22 +631,6 @@ public:
|
||||
void Overload7(const nsCString&);
|
||||
void Overload8(int32_t);
|
||||
void Overload8(TestInterface&);
|
||||
void Overload9(const Nullable<int32_t>&);
|
||||
void Overload9(const nsAString&);
|
||||
void Overload10(const Nullable<int32_t>&);
|
||||
void Overload10(JSContext*, JS::Handle<JSObject*>);
|
||||
void Overload11(int32_t);
|
||||
void Overload11(const nsAString&);
|
||||
void Overload12(int32_t);
|
||||
void Overload12(const Nullable<bool>&);
|
||||
void Overload13(const Nullable<int32_t>&);
|
||||
void Overload13(bool);
|
||||
void Overload14(const Optional<int32_t>&);
|
||||
void Overload14(TestInterface&);
|
||||
void Overload15(int32_t);
|
||||
void Overload15(const Optional<NonNull<TestInterface> >&);
|
||||
void Overload16(int32_t);
|
||||
void Overload16(const Optional<TestInterface*>&);
|
||||
|
||||
// Variadic handling
|
||||
void PassVariadicThirdArg(const nsAString&, int32_t,
|
||||
|
@ -118,9 +118,9 @@ interface TestInterface {
|
||||
void passByte(byte arg);
|
||||
byte receiveByte();
|
||||
void passOptionalByte(optional byte arg);
|
||||
void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
|
||||
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
|
||||
void passOptionalByteWithDefault(optional byte arg = 0);
|
||||
void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
|
||||
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
|
||||
void passNullableByte(byte? arg);
|
||||
void passOptionalNullableByte(optional byte? arg);
|
||||
void passVariadicByte(byte... arg);
|
||||
@ -365,7 +365,9 @@ interface TestInterface {
|
||||
void passString(DOMString arg);
|
||||
void passNullableString(DOMString? arg);
|
||||
void passOptionalString(optional DOMString arg);
|
||||
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
|
||||
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
|
||||
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
|
||||
void passOptionalNullableString(optional DOMString? arg);
|
||||
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
|
||||
void passVariadicString(DOMString... arg);
|
||||
@ -579,22 +581,6 @@ interface TestInterface {
|
||||
void overload7(ByteString arg);
|
||||
void overload8(long arg);
|
||||
void overload8(TestInterface arg);
|
||||
void overload9(long? arg);
|
||||
void overload9(DOMString arg);
|
||||
void overload10(long? arg);
|
||||
void overload10(object arg);
|
||||
void overload11(long arg);
|
||||
void overload11(DOMString? arg);
|
||||
void overload12(long arg);
|
||||
void overload12(boolean? arg);
|
||||
void overload13(long? arg);
|
||||
void overload13(boolean arg);
|
||||
void overload14(optional long arg);
|
||||
void overload14(TestInterface arg);
|
||||
void overload15(long arg);
|
||||
void overload15(optional TestInterface arg);
|
||||
void overload16(long arg);
|
||||
void overload16(optional TestInterface? arg);
|
||||
|
||||
// Variadic handling
|
||||
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
|
||||
|
@ -23,9 +23,9 @@ interface TestExampleInterface {
|
||||
void passByte(byte arg);
|
||||
byte receiveByte();
|
||||
void passOptionalByte(optional byte arg);
|
||||
void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
|
||||
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
|
||||
void passOptionalByteWithDefault(optional byte arg = 0);
|
||||
void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
|
||||
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
|
||||
void passNullableByte(byte? arg);
|
||||
void passOptionalNullableByte(optional byte? arg);
|
||||
void passVariadicByte(byte... arg);
|
||||
@ -263,7 +263,9 @@ interface TestExampleInterface {
|
||||
void passString(DOMString arg);
|
||||
void passNullableString(DOMString? arg);
|
||||
void passOptionalString(optional DOMString arg);
|
||||
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
|
||||
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
|
||||
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
|
||||
void passOptionalNullableString(optional DOMString? arg);
|
||||
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
|
||||
void passVariadicString(DOMString... arg);
|
||||
@ -476,22 +478,6 @@ interface TestExampleInterface {
|
||||
void overload7(ByteString arg);
|
||||
void overload8(long arg);
|
||||
void overload8(TestInterface arg);
|
||||
void overload9(long? arg);
|
||||
void overload9(DOMString arg);
|
||||
void overload10(long? arg);
|
||||
void overload10(object arg);
|
||||
void overload11(long arg);
|
||||
void overload11(DOMString? arg);
|
||||
void overload12(long arg);
|
||||
void overload12(boolean? arg);
|
||||
void overload13(long? arg);
|
||||
void overload13(boolean arg);
|
||||
void overload14(optional long arg);
|
||||
void overload14(TestInterface arg);
|
||||
void overload15(long arg);
|
||||
void overload15(optional TestInterface arg);
|
||||
void overload16(long arg);
|
||||
void overload16(optional TestInterface? arg);
|
||||
|
||||
// Variadic handling
|
||||
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
|
||||
|
@ -35,9 +35,9 @@ interface TestJSImplInterface {
|
||||
void passByte(byte arg);
|
||||
byte receiveByte();
|
||||
void passOptionalByte(optional byte arg);
|
||||
void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
|
||||
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
|
||||
void passOptionalByteWithDefault(optional byte arg = 0);
|
||||
void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
|
||||
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
|
||||
void passNullableByte(byte? arg);
|
||||
void passOptionalNullableByte(optional byte? arg);
|
||||
void passVariadicByte(byte... arg);
|
||||
@ -285,7 +285,9 @@ interface TestJSImplInterface {
|
||||
void passString(DOMString arg);
|
||||
void passNullableString(DOMString? arg);
|
||||
void passOptionalString(optional DOMString arg);
|
||||
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
|
||||
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
|
||||
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
|
||||
void passOptionalNullableString(optional DOMString? arg);
|
||||
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
|
||||
void passVariadicString(DOMString... arg);
|
||||
@ -504,22 +506,6 @@ interface TestJSImplInterface {
|
||||
void overload7(ByteString arg);
|
||||
void overload8(long arg);
|
||||
void overload8(TestJSImplInterface arg);
|
||||
void overload9(long? arg);
|
||||
void overload9(DOMString arg);
|
||||
void overload10(long? arg);
|
||||
void overload10(object arg);
|
||||
void overload11(long arg);
|
||||
void overload11(DOMString? arg);
|
||||
void overload12(long arg);
|
||||
void overload12(boolean? arg);
|
||||
void overload13(long? arg);
|
||||
void overload13(boolean arg);
|
||||
void overload14(optional long arg);
|
||||
void overload14(TestInterface arg);
|
||||
void overload15(long arg);
|
||||
void overload15(optional TestInterface arg);
|
||||
void overload16(long arg);
|
||||
void overload16(optional TestInterface? arg);
|
||||
|
||||
// Variadic handling
|
||||
void passVariadicThirdArg(DOMString arg1, long arg2, TestJSImplInterface... arg3);
|
||||
|
@ -989,18 +989,11 @@ BluetoothHfpManager::Connect(const nsAString& aDeviceAddress,
|
||||
return;
|
||||
}
|
||||
|
||||
mNeedsUpdatingSdpRecords = true;
|
||||
mIsHandsfree = !IS_HEADSET(aController->GetCod());
|
||||
|
||||
nsString uuid;
|
||||
if (mIsHandsfree) {
|
||||
BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid);
|
||||
} else {
|
||||
BluetoothUuidHelper::GetString(BluetoothServiceClass::HEADSET, uuid);
|
||||
}
|
||||
BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid);
|
||||
|
||||
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
|
||||
aController->OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
|
||||
aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1509,25 +1502,9 @@ BluetoothHfpManager::OnSocketDisconnect(BluetoothSocket* aSocket)
|
||||
void
|
||||
BluetoothHfpManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
|
||||
MOZ_ASSERT(mRunnable);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
nsString uuid;
|
||||
if (mIsHandsfree) {
|
||||
BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid);
|
||||
} else {
|
||||
BluetoothUuidHelper::GetString(BluetoothServiceClass::HEADSET, uuid);
|
||||
}
|
||||
|
||||
// Since we have updated SDP records of the target device, we should
|
||||
// try to get the channel of target service again.
|
||||
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
|
||||
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
|
||||
}
|
||||
// UpdateSdpRecord() is not called so this callback function should not
|
||||
// be invoked.
|
||||
MOZ_ASSUME_UNREACHABLE("UpdateSdpRecords() should be called somewhere");
|
||||
}
|
||||
|
||||
void
|
||||
@ -1541,14 +1518,17 @@ BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
BluetoothValue v;
|
||||
|
||||
if (aChannel < 0) {
|
||||
if (mNeedsUpdatingSdpRecords) {
|
||||
mNeedsUpdatingSdpRecords = false;
|
||||
bs->UpdateSdpRecords(aDeviceAddress, this);
|
||||
} else {
|
||||
// If we can't find Handsfree server channel number on the remote device,
|
||||
// try to create HSP connection instead.
|
||||
nsString hspUuid;
|
||||
BluetoothUuidHelper::GetString(BluetoothServiceClass::HEADSET, hspUuid);
|
||||
|
||||
if (aServiceUuid.Equals(hspUuid)) {
|
||||
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
|
||||
} else if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress,
|
||||
hspUuid, this))) {
|
||||
OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -147,8 +147,6 @@ private:
|
||||
int mNetworkSelectionMode;
|
||||
bool mReceiveVgsFlag;
|
||||
bool mDialingRequestProcessed;
|
||||
bool mIsHandsfree;
|
||||
bool mNeedsUpdatingSdpRecords;
|
||||
nsString mDeviceAddress;
|
||||
nsString mMsisdn;
|
||||
nsString mOperatorName;
|
||||
|
@ -46,11 +46,6 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
// Major device class = 0xA, Peripheral
|
||||
#define IS_PERIPHERAL(cod) (GET_MAJOR_DEVICE_CLASS(cod) == 0xa)
|
||||
|
||||
// Major device class = 0x4, Audio/Video
|
||||
// Minor device class = 0x1, Wearable Headset device
|
||||
#define IS_HEADSET(cod) ((GET_MAJOR_DEVICE_CLASS(cod) == 0x4) && \
|
||||
(GET_MINOR_DEVICE_CLASS(cod) == 0x1))
|
||||
|
||||
class BluetoothProfileManagerBase;
|
||||
class BluetoothReplyRunnable;
|
||||
typedef void (*BluetoothProfileControllerCallback)();
|
||||
|
@ -18,21 +18,17 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
assert_equals(doc.doctype.systemId, "")
|
||||
assert_equals(doc.documentElement.localName, "html")
|
||||
assert_equals(doc.documentElement.firstChild.localName, "head")
|
||||
if (title !== undefined) {
|
||||
assert_equals(doc.documentElement.firstChild.childNodes.length, 1)
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.localName, "title")
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.firstChild.data,
|
||||
expectedtitle)
|
||||
} else {
|
||||
assert_equals(doc.documentElement.firstChild.childNodes.length, 0)
|
||||
}
|
||||
assert_equals(doc.documentElement.firstChild.childNodes.length, 1)
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.localName, "title")
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.firstChild.data,
|
||||
expectedtitle)
|
||||
assert_equals(doc.documentElement.lastChild.localName, "body")
|
||||
assert_equals(doc.documentElement.lastChild.childNodes.length, 0)
|
||||
})
|
||||
}
|
||||
checkDoc("", "", "")
|
||||
checkDoc(null, "null", "null")
|
||||
checkDoc(undefined, "", "")
|
||||
checkDoc(undefined, "undefined", "undefined")
|
||||
checkDoc("foo bar baz", "foo bar baz", "foo bar baz")
|
||||
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz")
|
||||
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz")
|
||||
|
@ -12,7 +12,7 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
}
|
||||
checkDoc("", "", "")
|
||||
checkDoc(null, "null", "null")
|
||||
checkDoc(undefined, "", "")
|
||||
checkDoc(undefined, "undefined", "undefined")
|
||||
checkDoc("foo bar baz", "foo bar baz", "foo bar baz")
|
||||
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz")
|
||||
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz")
|
||||
|
@ -2802,7 +2802,7 @@ QuotaManager::FindSynchronizedOp(const nsACString& aPattern,
|
||||
for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
const nsAutoPtr<SynchronizedOp>& currentOp = mSynchronizedOps[index];
|
||||
if (PatternMatchesOrigin(aPattern, currentOp->mOriginOrPattern) &&
|
||||
(currentOp->mPersistenceType.IsNull() ||
|
||||
(!currentOp->mPersistenceType ||
|
||||
currentOp->mPersistenceType == aPersistenceType) &&
|
||||
(!currentOp->mId || currentOp->mId == aId)) {
|
||||
return currentOp;
|
||||
@ -3067,7 +3067,7 @@ QuotaManager::CollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
|
||||
uint32_t index;
|
||||
for (index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
|
||||
if (op->mPersistenceType.IsNull() ||
|
||||
if (!op->mPersistenceType ||
|
||||
op->mPersistenceType.Value() == PERSISTENCE_TYPE_TEMPORARY) {
|
||||
if (op->mOriginOrPattern.IsPattern() &&
|
||||
!originCollection.ContainsPattern(op->mOriginOrPattern)) {
|
||||
@ -3078,7 +3078,7 @@ QuotaManager::CollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
|
||||
|
||||
for (index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
|
||||
if (op->mPersistenceType.IsNull() ||
|
||||
if (!op->mPersistenceType ||
|
||||
op->mPersistenceType.Value() == PERSISTENCE_TYPE_TEMPORARY) {
|
||||
if (op->mOriginOrPattern.IsOrigin() &&
|
||||
!originCollection.ContainsOrigin(op->mOriginOrPattern)) {
|
||||
|
@ -138,7 +138,8 @@ public:
|
||||
static_cast<AudioManager *>(audioManager.get())->SetStreamVolumeIndex(
|
||||
AUDIO_STREAM_BLUETOOTH_SCO, volIndex);
|
||||
} else {
|
||||
MOZ_ASSUME_UNREACHABLE("unexpected audio channel for volume control");
|
||||
MOZ_ASSUME_UNREACHABLE("unexpected audio channel for initializing "
|
||||
"volume control");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -314,7 +315,7 @@ AudioManager::Observe(nsISupports* aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
nsDependentJSString keyStr;
|
||||
if (!keyStr.init(cx, jsKey) || keyStr.EqualsLiteral("audio.volume.bt_sco")) {
|
||||
if (!keyStr.init(cx, jsKey) || !keyStr.EqualsLiteral("audio.volume.bt_sco")) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "AudioManager.h"
|
||||
#endif
|
||||
#include "mozilla/ipc/Ril.h"
|
||||
#include "mozilla/ipc/KeyStore.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
@ -341,6 +342,8 @@ SystemWorkerManager::Init()
|
||||
return rv;
|
||||
}
|
||||
|
||||
InitKeyStore(cx);
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
InitAutoMounter();
|
||||
InitializeTimeZoneSettingObserver();
|
||||
@ -545,6 +548,13 @@ SystemWorkerManager::InitWifi(JSContext *cx)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SystemWorkerManager::InitKeyStore(JSContext *cx)
|
||||
{
|
||||
mKeyStore = new KeyStore();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(SystemWorkerManager,
|
||||
nsIObserver,
|
||||
nsIInterfaceRequestor,
|
||||
|
@ -35,6 +35,7 @@ namespace mozilla {
|
||||
namespace ipc {
|
||||
class RilConsumer;
|
||||
class UnixSocketRawData;
|
||||
class KeyStore;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
@ -70,6 +71,7 @@ private:
|
||||
nsresult InitNetd(JSContext *cx);
|
||||
#endif
|
||||
nsresult InitWifi(JSContext *cx);
|
||||
nsresult InitKeyStore(JSContext *cx);
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsCOMPtr<nsIWorkerHolder> mNetdWorker;
|
||||
@ -77,6 +79,7 @@ private:
|
||||
nsCOMPtr<nsIWorkerHolder> mWifiWorker;
|
||||
|
||||
nsTArray<nsRefPtr<ipc::RilConsumer> > mRilConsumers;
|
||||
nsRefPtr<ipc::KeyStore> mKeyStore;
|
||||
|
||||
bool mShutdown;
|
||||
};
|
||||
|
@ -7,3 +7,4 @@ qemu = true
|
||||
disabled = Bug 808783
|
||||
[test_fakevolume.js]
|
||||
[test_ril_code_quality.py]
|
||||
[test_screen_state.js]
|
||||
|
@ -74,7 +74,7 @@ interface CanvasRenderingContext2D {
|
||||
|
||||
// path API (see also CanvasPathMethods)
|
||||
void beginPath();
|
||||
void fill(optional CanvasWindingRule winding = "nonzero");
|
||||
void fill([TreatUndefinedAs=Missing] optional CanvasWindingRule winding = "nonzero");
|
||||
// NOT IMPLEMENTED void fill(Path path);
|
||||
void stroke();
|
||||
// NOT IMPLEMENTED void stroke(Path path);
|
||||
@ -84,10 +84,10 @@ interface CanvasRenderingContext2D {
|
||||
// NOT IMPLEMENTED boolean drawCustomFocusRing(Path path, Element element);
|
||||
// NOT IMPLEMENTED void scrollPathIntoView();
|
||||
// NOT IMPLEMENTED void scrollPathIntoView(Path path);
|
||||
void clip(optional CanvasWindingRule winding = "nonzero");
|
||||
void clip([TreatUndefinedAs=Missing] optional CanvasWindingRule winding = "nonzero");
|
||||
// NOT IMPLEMENTED void clip(Path path);
|
||||
// NOT IMPLEMENTED void resetClip();
|
||||
boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasWindingRule winding = "nonzero");
|
||||
boolean isPointInPath(unrestricted double x, unrestricted double y, [TreatUndefinedAs=Missing] optional CanvasWindingRule winding = "nonzero");
|
||||
// NOT IMPLEMENTED boolean isPointInPath(Path path, unrestricted double x, unrestricted double y);
|
||||
boolean isPointInStroke(double x, double y);
|
||||
|
||||
|
@ -28,9 +28,9 @@ interface Promise {
|
||||
static Promise reject(any value);
|
||||
|
||||
[Creator]
|
||||
Promise then(optional AnyCallback fulfillCallback,
|
||||
optional AnyCallback rejectCallback);
|
||||
Promise then([TreatUndefinedAs=Missing] optional AnyCallback fulfillCallback,
|
||||
[TreatUndefinedAs=Missing] optional AnyCallback rejectCallback);
|
||||
|
||||
[Creator]
|
||||
Promise catch(optional AnyCallback rejectCallback);
|
||||
Promise catch([TreatUndefinedAs=Missing] optional AnyCallback rejectCallback);
|
||||
};
|
||||
|
@ -71,9 +71,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
|
||||
|
||||
// request
|
||||
[Throws]
|
||||
void open(ByteString method, DOMString url);
|
||||
[Throws]
|
||||
void open(ByteString method, DOMString url, boolean async,
|
||||
void open(ByteString method, DOMString url, optional boolean async = true,
|
||||
optional DOMString? user, optional DOMString? password);
|
||||
[Throws]
|
||||
void setRequestHeader(ByteString header, ByteString value);
|
||||
|
@ -121,11 +121,6 @@ public:
|
||||
return mStateData.mReadyState;
|
||||
}
|
||||
|
||||
void Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv)
|
||||
{
|
||||
Open(aMethod, aUrl, true, Optional<nsAString>(),
|
||||
Optional<nsAString>(), aRv);
|
||||
}
|
||||
void
|
||||
Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
|
||||
const Optional<nsAString>& aUser, const Optional<nsAString>& aPassword,
|
||||
|
381
ipc/keystore/KeyStore.cpp
Normal file
381
ipc/keystore/KeyStore.cpp
Normal file
@ -0,0 +1,381 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et ft=cpp: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#undef LOG
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
|
||||
#else
|
||||
#define LOG(args...) printf(args);
|
||||
#endif
|
||||
|
||||
#include "KeyStore.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "MainThreadUtils.h" // For NS_IsMainThread.
|
||||
|
||||
#include "plbase64.h"
|
||||
#include "certdb.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
static const char* KEYSTORE_SOCKET_NAME = "keystore";
|
||||
static const char* KEYSTORE_SOCKET_PATH = "/dev/socket/keystore";
|
||||
|
||||
int
|
||||
KeyStoreConnector::Create()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
int fd;
|
||||
|
||||
unlink(KEYSTORE_SOCKET_PATH);
|
||||
|
||||
fd = socket(AF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
if (fd < 0) {
|
||||
NS_WARNING("Could not open keystore socket!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allow access of wpa_supplicant(different user, differnt group)
|
||||
chmod(KEYSTORE_SOCKET_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyStoreConnector::CreateAddr(bool aIsServer,
|
||||
socklen_t& aAddrSize,
|
||||
sockaddr_any& aAddr,
|
||||
const char* aAddress)
|
||||
{
|
||||
// Keystore socket must be server
|
||||
MOZ_ASSERT(aIsServer);
|
||||
|
||||
aAddr.un.sun_family = AF_LOCAL;
|
||||
if(strlen(KEYSTORE_SOCKET_PATH) > sizeof(aAddr.un.sun_path)) {
|
||||
NS_WARNING("Address too long for socket struct!");
|
||||
return false;
|
||||
}
|
||||
strcpy((char*)&aAddr.un.sun_path, KEYSTORE_SOCKET_PATH);
|
||||
aAddrSize = strlen(KEYSTORE_SOCKET_PATH) + offsetof(struct sockaddr_un, sun_path) + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyStoreConnector::SetUp(int aFd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
KeyStoreConnector::GetSocketAddr(const sockaddr_any& aAddr,
|
||||
nsAString& aAddrStr)
|
||||
{
|
||||
// Unused.
|
||||
MOZ_CRASH("This should never be called!");
|
||||
}
|
||||
|
||||
static char *
|
||||
get_cert_db_filename(void *arg, int vers)
|
||||
{
|
||||
static char keystoreDbPath[] = "/data/misc/wifi/keystore";
|
||||
return keystoreDbPath;
|
||||
}
|
||||
|
||||
KeyStore::KeyStore()
|
||||
{
|
||||
// Initial NSS
|
||||
certdb = CERT_GetDefaultCertDB();
|
||||
|
||||
Listen();
|
||||
}
|
||||
|
||||
void
|
||||
KeyStore::Shutdown()
|
||||
{
|
||||
mShutdown = true;
|
||||
CloseSocket();
|
||||
}
|
||||
|
||||
void
|
||||
KeyStore::Listen()
|
||||
{
|
||||
ListenSocket(new KeyStoreConnector());
|
||||
|
||||
ResetHandlerInfo();
|
||||
}
|
||||
|
||||
void
|
||||
KeyStore::ResetHandlerInfo()
|
||||
{
|
||||
mHandlerInfo.state = STATE_IDLE;
|
||||
mHandlerInfo.command = 0;
|
||||
mHandlerInfo.paramCount = 0;
|
||||
mHandlerInfo.commandPattern = NULL;
|
||||
for (int i = 0; i < MAX_PARAM; i++) {
|
||||
mHandlerInfo.param[i].length = 0;
|
||||
memset(mHandlerInfo.param[i].data, 0, VALUE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
KeyStore::CheckSize(UnixSocketRawData *aMessage, size_t aExpectSize)
|
||||
{
|
||||
return (aMessage->mSize - aMessage->mCurrentWriteOffset >= aExpectSize) ?
|
||||
true : false;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyStore::ReadCommand(UnixSocketRawData *aMessage)
|
||||
{
|
||||
if (mHandlerInfo.state != STATE_IDLE) {
|
||||
NS_WARNING("Wrong state in ReadCommand()!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckSize(aMessage, 1)) {
|
||||
NS_WARNING("Data size error in ReadCommand()!");
|
||||
return false;
|
||||
}
|
||||
|
||||
mHandlerInfo.command = aMessage->mData[aMessage->mCurrentWriteOffset];
|
||||
aMessage->mCurrentWriteOffset++;
|
||||
|
||||
// Find corrsponding command pattern
|
||||
const struct ProtocolCommand *command = commands;
|
||||
while (command->command && command->command != mHandlerInfo.command) {
|
||||
command++;
|
||||
}
|
||||
|
||||
if (!command->command) {
|
||||
NS_WARNING("Unsupported command!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get command pattern.
|
||||
mHandlerInfo.commandPattern = command;
|
||||
if (command->paramNum) {
|
||||
// Read command parameter if needed.
|
||||
mHandlerInfo.state = STATE_READ_PARAM_LEN;
|
||||
} else {
|
||||
mHandlerInfo.state = STATE_PROCESSING;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyStore::ReadLength(UnixSocketRawData *aMessage)
|
||||
{
|
||||
if (mHandlerInfo.state != STATE_READ_PARAM_LEN) {
|
||||
NS_WARNING("Wrong state in ReadLength()!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckSize(aMessage, 2)) {
|
||||
NS_WARNING("Data size error in ReadLength()!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read length of command parameter.
|
||||
unsigned short dataLength;
|
||||
memcpy(&dataLength, &aMessage->mData[aMessage->mCurrentWriteOffset], 2);
|
||||
aMessage->mCurrentWriteOffset += 2;
|
||||
mHandlerInfo.param[mHandlerInfo.paramCount].length = ntohs(dataLength);
|
||||
|
||||
mHandlerInfo.state = STATE_READ_PARAM_DATA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyStore::ReadData(UnixSocketRawData *aMessage)
|
||||
{
|
||||
if (mHandlerInfo.state != STATE_READ_PARAM_DATA) {
|
||||
NS_WARNING("Wrong state in ReadData()!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckSize(aMessage, mHandlerInfo.param[mHandlerInfo.paramCount].length)) {
|
||||
NS_WARNING("Data size error in ReadData()!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read command parameter.
|
||||
memcpy(mHandlerInfo.param[mHandlerInfo.paramCount].data,
|
||||
&aMessage->mData[aMessage->mCurrentWriteOffset],
|
||||
mHandlerInfo.param[mHandlerInfo.paramCount].length);
|
||||
aMessage->mCurrentWriteOffset += mHandlerInfo.param[mHandlerInfo.paramCount].length;
|
||||
mHandlerInfo.paramCount++;
|
||||
|
||||
if (mHandlerInfo.paramCount == mHandlerInfo.commandPattern->paramNum) {
|
||||
mHandlerInfo.state = STATE_PROCESSING;
|
||||
} else {
|
||||
mHandlerInfo.state = STATE_READ_PARAM_LEN;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Transform base64 certification data into DER format
|
||||
void
|
||||
KeyStore::FormatCaData(const uint8_t *aCaData, int aCaDataLength,
|
||||
const char *aName, const uint8_t **aFormatData,
|
||||
int &aFormatDataLength)
|
||||
{
|
||||
int bufSize = strlen(CA_BEGIN) + strlen(CA_END) + strlen(CA_TAILER) * 2 +
|
||||
strlen(aName) * 2 + aCaDataLength + aCaDataLength/CA_LINE_SIZE + 2;
|
||||
char *buf = (char *)malloc(bufSize);
|
||||
|
||||
aFormatDataLength = bufSize;
|
||||
*aFormatData = (const uint8_t *)buf;
|
||||
|
||||
char *ptr = buf;
|
||||
int len;
|
||||
|
||||
// Create DER header.
|
||||
len = snprintf(ptr, bufSize, "%s%s%s", CA_BEGIN, aName, CA_TAILER);
|
||||
ptr += len;
|
||||
bufSize -= len;
|
||||
|
||||
// Split base64 data in lines.
|
||||
int copySize;
|
||||
while (aCaDataLength > 0) {
|
||||
copySize = (aCaDataLength > CA_LINE_SIZE) ? CA_LINE_SIZE : aCaDataLength;
|
||||
|
||||
memcpy(ptr, aCaData, copySize);
|
||||
ptr += copySize;
|
||||
aCaData += copySize;
|
||||
aCaDataLength -= copySize;
|
||||
bufSize -= copySize;
|
||||
|
||||
*ptr = '\n';
|
||||
ptr++;
|
||||
bufSize--;
|
||||
}
|
||||
|
||||
// Create DEA tailer.
|
||||
snprintf(ptr, bufSize, "%s%s%s", CA_END, aName, CA_TAILER);
|
||||
}
|
||||
|
||||
// Status response
|
||||
void
|
||||
KeyStore::SendResponse(ResponseCode aResponse)
|
||||
{
|
||||
if (aResponse == NO_RESPONSE)
|
||||
return;
|
||||
|
||||
uint8_t response = (uint8_t)aResponse;
|
||||
UnixSocketRawData* data = new UnixSocketRawData((const void *)&response, 1);
|
||||
SendSocketData(data);
|
||||
}
|
||||
|
||||
// Data response
|
||||
void
|
||||
KeyStore::SendData(const uint8_t *aData, int aLength)
|
||||
{
|
||||
unsigned short dataLength = htons(aLength);
|
||||
|
||||
UnixSocketRawData* length = new UnixSocketRawData((const void *)&dataLength, 2);
|
||||
SendSocketData(length);
|
||||
|
||||
UnixSocketRawData* data = new UnixSocketRawData((const void *)aData, aLength);
|
||||
SendSocketData(data);
|
||||
}
|
||||
|
||||
void
|
||||
KeyStore::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
bool success = true;
|
||||
while (aMessage->mCurrentWriteOffset < aMessage->mSize ||
|
||||
mHandlerInfo.state == STATE_PROCESSING) {
|
||||
switch (mHandlerInfo.state) {
|
||||
case STATE_IDLE:
|
||||
success = ReadCommand(aMessage);
|
||||
break;
|
||||
case STATE_READ_PARAM_LEN:
|
||||
success = ReadLength(aMessage);
|
||||
break;
|
||||
case STATE_READ_PARAM_DATA:
|
||||
success = ReadData(aMessage);
|
||||
break;
|
||||
case STATE_PROCESSING:
|
||||
success = false;
|
||||
if (mHandlerInfo.command == 'g') {
|
||||
// Get CA
|
||||
const uint8_t *certData;
|
||||
int certDataLength;
|
||||
const char *certName = (const char *)mHandlerInfo.param[0].data;
|
||||
|
||||
// Get cert from NSS by name
|
||||
CERTCertificate *cert = CERT_FindCertByNickname(certdb, certName);
|
||||
if (!cert) {
|
||||
break;
|
||||
}
|
||||
|
||||
char *certDER = PL_Base64Encode((const char *)cert->derCert.data,
|
||||
cert->derCert.len, nullptr);
|
||||
if (!certDER) {
|
||||
break;
|
||||
}
|
||||
|
||||
FormatCaData((const uint8_t *)certDER, strlen(certDER), "CERTIFICATE",
|
||||
&certData, certDataLength);
|
||||
PL_strfree(certDER);
|
||||
|
||||
SendResponse(SUCCESS);
|
||||
SendData(certData, certDataLength);
|
||||
success = true;
|
||||
|
||||
free((void *)certData);
|
||||
}
|
||||
|
||||
ResetHandlerInfo();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
SendResponse(PROTOCOL_ERROR);
|
||||
ResetHandlerInfo();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyStore::OnConnectSuccess()
|
||||
{
|
||||
mShutdown = false;
|
||||
}
|
||||
|
||||
void
|
||||
KeyStore::OnConnectError()
|
||||
{
|
||||
if (!mShutdown) {
|
||||
Listen();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyStore::OnDisconnect()
|
||||
{
|
||||
if (!mShutdown) {
|
||||
Listen();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
131
ipc/keystore/KeyStore.h
Normal file
131
ipc/keystore/KeyStore.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_ipc_KeyStore_h
|
||||
#define mozilla_ipc_KeyStore_h 1
|
||||
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "cert.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
enum ResponseCode {
|
||||
SUCCESS = 1,
|
||||
LOCKED = 2,
|
||||
UNINITIALIZED = 3,
|
||||
SYSTEM_ERROR = 4,
|
||||
PROTOCOL_ERROR = 5,
|
||||
PERMISSION_DENIED = 6,
|
||||
KEY_NOT_FOUND = 7,
|
||||
VALUE_CORRUPTED = 8,
|
||||
UNDEFINED_ACTION = 9,
|
||||
WRONG_PASSWORD_0 = 10,
|
||||
WRONG_PASSWORD_1 = 11,
|
||||
WRONG_PASSWORD_2 = 12,
|
||||
WRONG_PASSWORD_3 = 13, // MAX_RETRY = 4
|
||||
NO_RESPONSE
|
||||
};
|
||||
|
||||
static const int MAX_PARAM = 2;
|
||||
static const int KEY_SIZE = ((NAME_MAX - 15) / 2);
|
||||
static const int VALUE_SIZE = 32768;
|
||||
static const int PASSWORD_SIZE = VALUE_SIZE;
|
||||
|
||||
static const char *CA_BEGIN = "-----BEGIN ",
|
||||
*CA_END = "-----END ",
|
||||
*CA_TAILER = "-----\n";
|
||||
static const int CA_LINE_SIZE = 64;
|
||||
|
||||
struct ProtocolCommand {
|
||||
int8_t command;
|
||||
int paramNum;
|
||||
};
|
||||
|
||||
static const struct ProtocolCommand commands[] = {
|
||||
{'g', 1}, // Get CA, command "g CERT_NAME"
|
||||
{ 0, 0}
|
||||
};
|
||||
|
||||
struct ProtocolParam{
|
||||
uint length;
|
||||
int8_t data[VALUE_SIZE];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
STATE_IDLE,
|
||||
STATE_READ_PARAM_LEN,
|
||||
STATE_READ_PARAM_DATA,
|
||||
STATE_PROCESSING
|
||||
} ProtocolHandlerState;
|
||||
|
||||
class KeyStoreConnector : public mozilla::ipc::UnixSocketConnector
|
||||
{
|
||||
public:
|
||||
KeyStoreConnector()
|
||||
{}
|
||||
|
||||
virtual ~KeyStoreConnector()
|
||||
{}
|
||||
|
||||
virtual int Create();
|
||||
virtual bool CreateAddr(bool aIsServer,
|
||||
socklen_t& aAddrSize,
|
||||
sockaddr_any& aAddr,
|
||||
const char* aAddress);
|
||||
virtual bool SetUp(int aFd);
|
||||
virtual void GetSocketAddr(const sockaddr_any& aAddr,
|
||||
nsAString& aAddrStr);
|
||||
};
|
||||
|
||||
class KeyStore : public mozilla::ipc::UnixSocketConsumer
|
||||
{
|
||||
public:
|
||||
KeyStore();
|
||||
virtual ~KeyStore() {}
|
||||
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
virtual void ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage);
|
||||
|
||||
virtual void OnConnectSuccess();
|
||||
virtual void OnConnectError();
|
||||
virtual void OnDisconnect();
|
||||
|
||||
private:
|
||||
struct {
|
||||
ProtocolHandlerState state;
|
||||
uint8_t command;
|
||||
struct ProtocolParam param[MAX_PARAM];
|
||||
int paramCount;
|
||||
const struct ProtocolCommand *commandPattern;
|
||||
} mHandlerInfo;
|
||||
void ResetHandlerInfo();
|
||||
void Listen();
|
||||
|
||||
void FormatCaData(const uint8_t *caData, int caDataLength, const char *name,
|
||||
const uint8_t **formatData, int &formatDataLength);
|
||||
|
||||
bool CheckSize(UnixSocketRawData *aMessage, size_t aExpectSize);
|
||||
bool ReadCommand(UnixSocketRawData *aMessage);
|
||||
bool ReadLength(UnixSocketRawData *aMessage);
|
||||
bool ReadData(UnixSocketRawData *aMessage);
|
||||
void SendResponse(ResponseCode response);
|
||||
void SendData(const uint8_t *data, int length);
|
||||
|
||||
bool mShutdown;
|
||||
|
||||
CERTCertDBHandle *certdb;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_KeyStore_h
|
7
ipc/keystore/Makefile.in
Normal file
7
ipc/keystore/Makefile.in
Normal file
@ -0,0 +1,7 @@
|
||||
# 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/.
|
||||
|
||||
EXPORT_LIBRARY = 1
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
21
ipc/keystore/moz.build
Normal file
21
ipc/keystore/moz.build
Normal file
@ -0,0 +1,21 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MODULE = 'ipc'
|
||||
|
||||
EXPORTS.mozilla.ipc += [
|
||||
'KeyStore.h'
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'KeyStore.cpp'
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
LIBXUL_LIBRARY = True
|
||||
|
||||
LIBRARY_NAME = 'mozkeystore_s'
|
@ -18,7 +18,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
DIRS += ['dbus']
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT']:
|
||||
DIRS += ['unixsocket']
|
||||
DIRS += ['unixsocket', 'keystore']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
DIRS += ['netd']
|
||||
|
@ -289,7 +289,7 @@ ExposeGCThingToActiveJS(void *thing, JSGCTraceKind kind)
|
||||
* All live objects in the nursery are moved to tenured at the beginning of
|
||||
* each GC slice, so the gray marker never sees nursery things.
|
||||
*/
|
||||
if (uintptr_t(thing) >= rt->gcNurseryStart_ && uintptr_t(thing) < rt->gcNurseryEnd_)
|
||||
if (js::gc::IsInsideNursery(rt, thing))
|
||||
return;
|
||||
#endif
|
||||
if (IsIncrementalBarrierNeededOnGCThing(rt, thing, kind))
|
||||
|
@ -149,6 +149,16 @@ GetGCThingArena(void *thing)
|
||||
return reinterpret_cast<JS::shadow::ArenaHeader *>(addr);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE bool
|
||||
IsInsideNursery(const JS::shadow::Runtime *runtime, const void *p)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
return uintptr_t(p) >= runtime->gcNurseryStart_ && uintptr_t(p) < runtime->gcNurseryEnd_;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
} /* namespace js */
|
||||
@ -178,7 +188,7 @@ GCThingIsMarkedGray(void *thing)
|
||||
* each GC slice, so the gray marker never sees nursery things.
|
||||
*/
|
||||
JS::shadow::Runtime *rt = js::gc::GetGCThingRuntime(thing);
|
||||
if (uintptr_t(thing) >= rt->gcNurseryStart_ && uintptr_t(thing) < rt->gcNurseryEnd_)
|
||||
if (js::gc::IsInsideNursery(rt, thing))
|
||||
return false;
|
||||
#endif
|
||||
uintptr_t *word, mask;
|
||||
|
@ -38,6 +38,16 @@ template <typename T> class AutoVectorRooter;
|
||||
template<typename K, typename V> class AutoHashMapRooter;
|
||||
template<typename T> class AutoHashSetRooter;
|
||||
|
||||
class JS_PUBLIC_API(ContextOptions);
|
||||
class JS_PUBLIC_API(AutoSaveContextOptions);
|
||||
|
||||
JS_PUBLIC_API(ContextOptions &) ContextOptionsRef(JSContext *cx);
|
||||
|
||||
class ContextOptions;
|
||||
class AutoSaveContextOptions;
|
||||
|
||||
ContextOptions &ContextOptionsRef(JSContext *cx);
|
||||
|
||||
}
|
||||
|
||||
// Do the importing.
|
||||
@ -112,6 +122,10 @@ using JS::MutableHandleValue;
|
||||
|
||||
using JS::Zone;
|
||||
|
||||
using JS::ContextOptions;
|
||||
using JS::ContextOptionsRef;
|
||||
using JS::AutoSaveContextOptions;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* NamespaceImports_h */
|
||||
|
@ -1049,7 +1049,7 @@ Cell::isTenured() const
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS::shadow::Runtime *rt = js::gc::GetGCThingRuntime(this);
|
||||
return uintptr_t(this) < rt->gcNurseryStart_ || uintptr_t(this) >= rt->gcNurseryEnd_;
|
||||
return !IsInsideNursery(rt, this);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class Nursery
|
||||
|
||||
template <typename T>
|
||||
JS_ALWAYS_INLINE bool isInside(const T *p) const {
|
||||
return uintptr_t(p) >= start() && uintptr_t(p) < heapEnd();
|
||||
return gc::IsInsideNursery((JS::shadow::Runtime *)runtime_, p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
25
js/src/jit-test/tests/ion/bug925067-1.js
Normal file
25
js/src/jit-test/tests/ion/bug925067-1.js
Normal file
@ -0,0 +1,25 @@
|
||||
var c = 0;
|
||||
function g(o) {
|
||||
try {
|
||||
for(;;)
|
||||
o.next();
|
||||
} catch(e) {
|
||||
c += e;
|
||||
}
|
||||
return o.x;
|
||||
}
|
||||
function f() {
|
||||
var o = {x: 0, next: function() {
|
||||
if (this.x++ > 100)
|
||||
throw 3;
|
||||
}};
|
||||
|
||||
g(o);
|
||||
assertEq(o.x, 102);
|
||||
|
||||
o.x = 0;
|
||||
g(o);
|
||||
assertEq(o.x, 102);
|
||||
}
|
||||
f();
|
||||
assertEq(c, 6);
|
16
js/src/jit-test/tests/ion/bug925067-2.js
Normal file
16
js/src/jit-test/tests/ion/bug925067-2.js
Normal file
@ -0,0 +1,16 @@
|
||||
// |jit-test| error: 4
|
||||
function g(o) {
|
||||
if (o.x >= 0) {
|
||||
for(;;)
|
||||
o.next();
|
||||
}
|
||||
return o.x;
|
||||
}
|
||||
function f() {
|
||||
var o = {x: 0, next: function() {
|
||||
if (this.x++ > 100)
|
||||
throw 4;
|
||||
}};
|
||||
g(o);
|
||||
}
|
||||
f();
|
20
js/src/jit-test/tests/ion/bug925067-3.js
Normal file
20
js/src/jit-test/tests/ion/bug925067-3.js
Normal file
@ -0,0 +1,20 @@
|
||||
// |jit-test| error: 4
|
||||
function h(o) {
|
||||
o.next();
|
||||
}
|
||||
function g(o) {
|
||||
for (var i=0; i<5; i++) {};
|
||||
if (o.x >= 0) {
|
||||
for(;;)
|
||||
h(o);
|
||||
}
|
||||
return o.x;
|
||||
}
|
||||
function f() {
|
||||
var o = {x: 0, next: function() {
|
||||
if (this.x++ > 100)
|
||||
throw 4;
|
||||
}};
|
||||
g(o);
|
||||
}
|
||||
f();
|
@ -73,9 +73,13 @@ BlockMightReach(MBasicBlock *src, MBasicBlock *dest)
|
||||
switch (src->numSuccessors()) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
src = src->getSuccessor(0);
|
||||
case 1: {
|
||||
MBasicBlock *successor = src->getSuccessor(0);
|
||||
if (successor->id() <= src->id())
|
||||
return true; // Don't iloop.
|
||||
src = successor;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
@ -6540,7 +6540,7 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
|
||||
bool available = JSC::MacroAssembler::supportsFloatingPoint() &&
|
||||
cx->gcSystemPageSize() == AsmJSPageSize &&
|
||||
!cx->compartment()->debugMode() &&
|
||||
cx->hasOption(JSOPTION_ASMJS);
|
||||
cx->options().asmJS();
|
||||
|
||||
args.rval().set(BooleanValue(available));
|
||||
return true;
|
||||
|
@ -274,7 +274,7 @@ struct BaselineScript
|
||||
inline bool
|
||||
IsBaselineEnabled(JSContext *cx)
|
||||
{
|
||||
return cx->hasOption(JSOPTION_BASELINE);
|
||||
return cx->options().baseline();
|
||||
}
|
||||
|
||||
MethodStatus
|
||||
|
@ -363,8 +363,8 @@ void FinishOffThreadBuilder(IonBuilder *builder);
|
||||
static inline bool
|
||||
IsIonEnabled(JSContext *cx)
|
||||
{
|
||||
return cx->hasOption(JSOPTION_ION) &&
|
||||
cx->hasOption(JSOPTION_BASELINE) &&
|
||||
return cx->options().ion() &&
|
||||
cx->options().baseline() &&
|
||||
cx->typeInferenceEnabled();
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,10 @@ virtual
|
||||
JSContext *createContext()
|
||||
{
|
||||
JSContext *cx = JSAPITest::createContext();
|
||||
if (cx)
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_BASELINE | JSOPTION_ION);
|
||||
if (!cx)
|
||||
return NULL;
|
||||
ContextOptionsRef(cx).setBaseline(true)
|
||||
.setIon(true);
|
||||
return cx;
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,7 @@ BEGIN_TEST(testJSEvaluateScript)
|
||||
JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, nullptr, global));
|
||||
CHECK(obj);
|
||||
|
||||
uint32_t options = JS_GetOptions(cx);
|
||||
CHECK(options & JSOPTION_VAROBJFIX);
|
||||
CHECK(ContextOptionsRef(cx).varObjFix());
|
||||
|
||||
static const char src[] = "var x = 5;";
|
||||
|
||||
@ -27,7 +26,7 @@ BEGIN_TEST(testJSEvaluateScript)
|
||||
CHECK(hasProp);
|
||||
|
||||
// Now do the same thing, but without JSOPTION_VAROBJFIX
|
||||
JS_SetOptions(cx, options & ~JSOPTION_VAROBJFIX);
|
||||
ContextOptionsRef(cx).setVarObjFix(false);
|
||||
|
||||
static const char src2[] = "var y = 5;";
|
||||
|
||||
|
@ -141,7 +141,8 @@ END_TEST(testProfileStrings_isCalledWithInterpreter)
|
||||
BEGIN_TEST(testProfileStrings_isCalledWithJIT)
|
||||
{
|
||||
CHECK(initialize(cx));
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_BASELINE | JSOPTION_ION);
|
||||
ContextOptionsRef(cx).setBaseline(true)
|
||||
.setIon(true);
|
||||
|
||||
EXEC("function g() { var p = new Prof(); p.test_fn(); }");
|
||||
EXEC("function f() { g(); }");
|
||||
@ -189,12 +190,13 @@ END_TEST(testProfileStrings_isCalledWithJIT)
|
||||
BEGIN_TEST(testProfileStrings_isCalledWhenError)
|
||||
{
|
||||
CHECK(initialize(cx));
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_BASELINE | JSOPTION_ION);
|
||||
ContextOptionsRef(cx).setBaseline(true)
|
||||
.setIon(true);
|
||||
|
||||
EXEC("function check2() { throw 'a'; }");
|
||||
|
||||
reset(cx);
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
ContextOptionsRef(cx).setDontReportUncaught(true);
|
||||
{
|
||||
JS::RootedValue rval(cx);
|
||||
/* Make sure the stack resets and we have an entry for each stack */
|
||||
@ -212,7 +214,8 @@ END_TEST(testProfileStrings_isCalledWhenError)
|
||||
BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
|
||||
{
|
||||
CHECK(initialize(cx));
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_BASELINE | JSOPTION_ION);
|
||||
ContextOptionsRef(cx).setBaseline(true)
|
||||
.setIon(true);
|
||||
|
||||
EXEC("function b(p) { p.test_fn(); }");
|
||||
EXEC("function a() { var p = new Prof(); p.enable(); b(p); }");
|
||||
|
@ -300,7 +300,7 @@ class JSAPITest
|
||||
JSContext *cx = JS_NewContext(rt, 8192);
|
||||
if (!cx)
|
||||
return nullptr;
|
||||
JS_SetOptions(cx, JSOPTION_VAROBJFIX);
|
||||
ContextOptionsRef(cx).setVarObjFix(true);
|
||||
JS_SetErrorReporter(cx, &reportError);
|
||||
return cx;
|
||||
}
|
||||
|
@ -964,6 +964,48 @@ JS_StringToVersion(const char *string)
|
||||
return JSVERSION_UNKNOWN;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
GetOptionsCommon(JSContext *cx)
|
||||
{
|
||||
return (cx->options().extraWarnings() ? JSOPTION_EXTRA_WARNINGS : 0)
|
||||
| (cx->options().werror() ? JSOPTION_WERROR : 0)
|
||||
| (cx->options().varObjFix() ? JSOPTION_VAROBJFIX : 0)
|
||||
| (cx->options().privateIsNSISupports() ? JSOPTION_PRIVATE_IS_NSISUPPORTS : 0)
|
||||
| (cx->options().compileAndGo() ? JSOPTION_COMPILE_N_GO : 0)
|
||||
| (cx->options().dontReportUncaught() ? JSOPTION_DONT_REPORT_UNCAUGHT : 0)
|
||||
| (cx->options().noDefaultCompartmentObject() ? JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT : 0)
|
||||
| (cx->options().noScriptRval() ? JSOPTION_NO_SCRIPT_RVAL : 0)
|
||||
| (cx->options().baseline() ? JSOPTION_BASELINE : 0)
|
||||
| (cx->options().typeInference() ? JSOPTION_TYPE_INFERENCE : 0)
|
||||
| (cx->options().strictMode() ? JSOPTION_STRICT_MODE : 0)
|
||||
| (cx->options().ion() ? JSOPTION_ION : 0)
|
||||
| (cx->options().asmJS() ? JSOPTION_ASMJS : 0);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
SetOptionsCommon(JSContext *cx, unsigned newopts)
|
||||
{
|
||||
JS_ASSERT((newopts & JSOPTION_MASK) == newopts);
|
||||
unsigned oldopts = GetOptionsCommon(cx);
|
||||
|
||||
cx->options().setExtraWarnings(newopts & JSOPTION_EXTRA_WARNINGS);
|
||||
cx->options().setWerror(newopts & JSOPTION_WERROR);
|
||||
cx->options().setVarObjFix(newopts & JSOPTION_VAROBJFIX);
|
||||
cx->options().setPrivateIsNSISupports(newopts & JSOPTION_PRIVATE_IS_NSISUPPORTS);
|
||||
cx->options().setCompileAndGo(newopts & JSOPTION_COMPILE_N_GO);
|
||||
cx->options().setDontReportUncaught(newopts & JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
cx->options().setNoDefaultCompartmentObject(newopts & JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT);
|
||||
cx->options().setNoScriptRval(newopts & JSOPTION_NO_SCRIPT_RVAL);
|
||||
cx->options().setBaseline(newopts & JSOPTION_BASELINE);
|
||||
cx->options().setTypeInference(newopts & JSOPTION_TYPE_INFERENCE);
|
||||
cx->options().setStrictMode(newopts & JSOPTION_STRICT_MODE);
|
||||
cx->options().setIon(newopts & JSOPTION_ION);
|
||||
cx->options().setAsmJS(newopts & JSOPTION_ASMJS);
|
||||
|
||||
cx->updateJITEnabled();
|
||||
return oldopts;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uint32_t)
|
||||
JS_GetOptions(JSContext *cx)
|
||||
{
|
||||
@ -972,18 +1014,7 @@ JS_GetOptions(JSContext *cx)
|
||||
* We may have been synchronized with a script version that was formerly on
|
||||
* the stack, but has now been popped.
|
||||
*/
|
||||
return cx->options();
|
||||
}
|
||||
|
||||
static unsigned
|
||||
SetOptionsCommon(JSContext *cx, unsigned options)
|
||||
{
|
||||
JS_ASSERT((options & JSOPTION_MASK) == options);
|
||||
unsigned oldopts = cx->options();
|
||||
unsigned newopts = options & JSOPTION_MASK;
|
||||
cx->setOptions(newopts);
|
||||
cx->updateJITEnabled();
|
||||
return oldopts;
|
||||
return GetOptionsCommon(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uint32_t)
|
||||
@ -995,11 +1026,17 @@ JS_SetOptions(JSContext *cx, uint32_t options)
|
||||
JS_PUBLIC_API(uint32_t)
|
||||
JS_ToggleOptions(JSContext *cx, uint32_t options)
|
||||
{
|
||||
unsigned oldopts = cx->options();
|
||||
unsigned oldopts = GetOptionsCommon(cx);
|
||||
unsigned newopts = oldopts ^ options;
|
||||
return SetOptionsCommon(cx, newopts);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::ContextOptions &)
|
||||
JS::ContextOptionsRef(JSContext *cx)
|
||||
{
|
||||
return cx->options();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetJitHardening(JSRuntime *rt, bool enabled)
|
||||
{
|
||||
@ -4383,7 +4420,7 @@ struct AutoLastFrameCheck
|
||||
~AutoLastFrameCheck() {
|
||||
if (cx->isExceptionPending() &&
|
||||
!JS_IsRunning(cx) &&
|
||||
!cx->hasOption(JSOPTION_DONT_REPORT_UNCAUGHT)) {
|
||||
!cx->options().dontReportUncaught()) {
|
||||
js_ReportUncaughtException(cx);
|
||||
}
|
||||
}
|
||||
@ -4489,15 +4526,15 @@ JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version)
|
||||
lineno(1),
|
||||
column(0),
|
||||
element(NullPtr()),
|
||||
compileAndGo(cx->hasOption(JSOPTION_COMPILE_N_GO)),
|
||||
compileAndGo(cx->options().compileAndGo()),
|
||||
forEval(false),
|
||||
noScriptRval(cx->hasOption(JSOPTION_NO_SCRIPT_RVAL)),
|
||||
noScriptRval(cx->options().noScriptRval()),
|
||||
selfHostingMode(false),
|
||||
canLazilyParse(true),
|
||||
strictOption(cx->hasOption(JSOPTION_STRICT_MODE)),
|
||||
extraWarningsOption(cx->hasExtraWarningsOption()),
|
||||
werrorOption(cx->hasWErrorOption()),
|
||||
asmJSOption(cx->hasOption(JSOPTION_ASMJS)),
|
||||
strictOption(cx->options().strictMode()),
|
||||
extraWarningsOption(cx->options().extraWarnings()),
|
||||
werrorOption(cx->options().werror()),
|
||||
asmJSOption(cx->options().asmJS()),
|
||||
sourcePolicy(SAVE_SOURCE)
|
||||
{
|
||||
}
|
||||
|
190
js/src/jsapi.h
190
js/src/jsapi.h
@ -1542,6 +1542,196 @@ JS_SetOptions(JSContext *cx, uint32_t options);
|
||||
extern JS_PUBLIC_API(uint32_t)
|
||||
JS_ToggleOptions(JSContext *cx, uint32_t options);
|
||||
|
||||
namespace JS {
|
||||
|
||||
class JS_PUBLIC_API(ContextOptions) {
|
||||
public:
|
||||
ContextOptions()
|
||||
: extraWarnings_(false),
|
||||
werror_(false),
|
||||
varObjFix_(false),
|
||||
privateIsNSISupports_(false),
|
||||
compileAndGo_(false),
|
||||
dontReportUncaught_(false),
|
||||
noDefaultCompartmentObject_(false),
|
||||
noScriptRval_(false),
|
||||
baseline_(false),
|
||||
typeInference_(false),
|
||||
strictMode_(false),
|
||||
ion_(false),
|
||||
asmJS_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool extraWarnings() const { return extraWarnings_; }
|
||||
ContextOptions &setExtraWarnings(bool flag) {
|
||||
extraWarnings_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleExtraWarnings() {
|
||||
extraWarnings_ = !extraWarnings_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool werror() const { return werror_; }
|
||||
ContextOptions &setWerror(bool flag) {
|
||||
werror_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleWerror() {
|
||||
werror_ = !werror_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool varObjFix() const { return varObjFix_; }
|
||||
ContextOptions &setVarObjFix(bool flag) {
|
||||
varObjFix_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleVarObjFix() {
|
||||
varObjFix_ = !varObjFix_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool privateIsNSISupports() const { return privateIsNSISupports_; }
|
||||
ContextOptions &setPrivateIsNSISupports(bool flag) {
|
||||
privateIsNSISupports_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &togglePrivateIsNSISupports() {
|
||||
privateIsNSISupports_ = !privateIsNSISupports_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool compileAndGo() const { return compileAndGo_; }
|
||||
ContextOptions &setCompileAndGo(bool flag) {
|
||||
compileAndGo_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleCompileAndGo() {
|
||||
compileAndGo_ = !compileAndGo_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool dontReportUncaught() const { return dontReportUncaught_; }
|
||||
ContextOptions &setDontReportUncaught(bool flag) {
|
||||
dontReportUncaught_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleDontReportUncaught() {
|
||||
dontReportUncaught_ = !dontReportUncaught_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool noDefaultCompartmentObject() const { return noDefaultCompartmentObject_; }
|
||||
ContextOptions &setNoDefaultCompartmentObject(bool flag) {
|
||||
noDefaultCompartmentObject_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleNoDefaultCompartmentObject() {
|
||||
noDefaultCompartmentObject_ = !noDefaultCompartmentObject_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool noScriptRval() const { return noScriptRval_; }
|
||||
ContextOptions &setNoScriptRval(bool flag) {
|
||||
noScriptRval_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleNoScriptRval() {
|
||||
noScriptRval_ = !noScriptRval_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool baseline() const { return baseline_; }
|
||||
ContextOptions &setBaseline(bool flag) {
|
||||
baseline_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleBaseline() {
|
||||
baseline_ = !baseline_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool typeInference() const { return typeInference_; }
|
||||
ContextOptions &setTypeInference(bool flag) {
|
||||
typeInference_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleTypeInference() {
|
||||
typeInference_ = !typeInference_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool strictMode() const { return strictMode_; }
|
||||
ContextOptions &setStrictMode(bool flag) {
|
||||
strictMode_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleStrictMode() {
|
||||
strictMode_ = !strictMode_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ion() const { return ion_; }
|
||||
ContextOptions &setIon(bool flag) {
|
||||
ion_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleIon() {
|
||||
ion_ = !ion_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool asmJS() const { return asmJS_; }
|
||||
ContextOptions &setAsmJS(bool flag) {
|
||||
asmJS_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions &toggleAsmJS() {
|
||||
asmJS_ = !asmJS_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
bool extraWarnings_ : 1;
|
||||
bool werror_ : 1;
|
||||
bool varObjFix_ : 1;
|
||||
bool privateIsNSISupports_ : 1;
|
||||
bool compileAndGo_ : 1;
|
||||
bool dontReportUncaught_ : 1;
|
||||
bool noDefaultCompartmentObject_ : 1;
|
||||
bool noScriptRval_ : 1;
|
||||
bool baseline_ : 1;
|
||||
bool typeInference_ : 1;
|
||||
bool strictMode_ : 1;
|
||||
bool ion_ : 1;
|
||||
bool asmJS_ : 1;
|
||||
};
|
||||
|
||||
JS_PUBLIC_API(ContextOptions &)
|
||||
ContextOptionsRef(JSContext *cx);
|
||||
|
||||
class JS_PUBLIC_API(AutoSaveContextOptions) {
|
||||
public:
|
||||
AutoSaveContextOptions(JSContext *cx)
|
||||
: cx_(cx),
|
||||
oldOptions_(ContextOptionsRef(cx_))
|
||||
{
|
||||
}
|
||||
|
||||
~AutoSaveContextOptions()
|
||||
{
|
||||
ContextOptionsRef(cx_) = oldOptions_;
|
||||
}
|
||||
|
||||
private:
|
||||
JSContext *cx_;
|
||||
JS::ContextOptions oldOptions_;
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetJitHardening(JSRuntime *rt, bool enabled);
|
||||
|
||||
|
@ -769,7 +769,7 @@ js::WouldDefinePastNonwritableLength(ThreadSafeContext *cx,
|
||||
|
||||
JSContext *ncx = cx->asJSContext();
|
||||
|
||||
if (!strict && !ncx->hasExtraWarningsOption())
|
||||
if (!strict && !ncx->options().extraWarnings())
|
||||
return true;
|
||||
|
||||
// XXX include the index and maybe array length in the error message
|
||||
|
@ -457,18 +457,18 @@ checkReportFlags(JSContext *cx, unsigned *flags)
|
||||
JSScript *script = cx->currentScript();
|
||||
if (script && script->strict)
|
||||
*flags &= ~JSREPORT_WARNING;
|
||||
else if (cx->hasExtraWarningsOption())
|
||||
else if (cx->options().extraWarnings())
|
||||
*flags |= JSREPORT_WARNING;
|
||||
else
|
||||
return true;
|
||||
} else if (JSREPORT_IS_STRICT(*flags)) {
|
||||
/* Warning/error only when JSOPTION_STRICT is set. */
|
||||
if (!cx->hasExtraWarningsOption())
|
||||
if (!cx->options().extraWarnings())
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Warnings become errors when JSOPTION_WERROR is set. */
|
||||
if (JSREPORT_IS_WARNING(*flags) && cx->hasWErrorOption())
|
||||
if (JSREPORT_IS_WARNING(*flags) && cx->options().werror())
|
||||
*flags &= ~JSREPORT_WARNING;
|
||||
|
||||
return false;
|
||||
@ -1057,7 +1057,7 @@ JSContext::JSContext(JSRuntime *rt)
|
||||
: ExclusiveContext(rt, &rt->mainThread, Context_JS),
|
||||
throwing(false),
|
||||
exception(UndefinedValue()),
|
||||
options_(0),
|
||||
options_(),
|
||||
reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
|
||||
resolvingList(nullptr),
|
||||
generatingError(false),
|
||||
|
@ -428,7 +428,7 @@ struct JSContext : public js::ExclusiveContext,
|
||||
js::Value exception; /* most-recently-thrown exception */
|
||||
|
||||
/* Per-context options. */
|
||||
unsigned options_; /* see jsapi.h for JSOPTION_* */
|
||||
JS::ContextOptions options_;
|
||||
|
||||
public:
|
||||
int32_t reportGranularity; /* see vm/Probes.h */
|
||||
@ -463,7 +463,7 @@ struct JSContext : public js::ExclusiveContext,
|
||||
inline void setDefaultCompartmentObject(JSObject *obj);
|
||||
inline void setDefaultCompartmentObjectIfUnset(JSObject *obj);
|
||||
JSObject *maybeDefaultCompartmentObject() const {
|
||||
JS_ASSERT(!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT));
|
||||
JS_ASSERT(!options().noDefaultCompartmentObject());
|
||||
return defaultCompartmentObject_;
|
||||
}
|
||||
|
||||
@ -492,21 +492,14 @@ struct JSContext : public js::ExclusiveContext,
|
||||
*/
|
||||
JSVersion findVersion() const;
|
||||
|
||||
void setOptions(unsigned opts) {
|
||||
JS_ASSERT((opts & JSOPTION_MASK) == opts);
|
||||
options_ = opts;
|
||||
const JS::ContextOptions &options() const {
|
||||
return options_;
|
||||
}
|
||||
|
||||
unsigned options() const { return options_; }
|
||||
|
||||
bool hasOption(unsigned opt) const {
|
||||
JS_ASSERT((opt & JSOPTION_MASK) == opt);
|
||||
return !!(options_ & opt);
|
||||
JS::ContextOptions &options() {
|
||||
return options_;
|
||||
}
|
||||
|
||||
bool hasExtraWarningsOption() const { return hasOption(JSOPTION_EXTRA_WARNINGS); }
|
||||
bool hasWErrorOption() const { return hasOption(JSOPTION_WERROR); }
|
||||
|
||||
js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; }
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
@ -433,14 +433,14 @@ JSContext::setPendingException(js::Value v) {
|
||||
inline void
|
||||
JSContext::setDefaultCompartmentObject(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT));
|
||||
JS_ASSERT(!options().noDefaultCompartmentObject());
|
||||
defaultCompartmentObject_ = obj;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSContext::setDefaultCompartmentObjectIfUnset(JSObject *obj)
|
||||
{
|
||||
if (!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT) &&
|
||||
if (!options().noDefaultCompartmentObject() &&
|
||||
!defaultCompartmentObject_)
|
||||
{
|
||||
setDefaultCompartmentObject(obj);
|
||||
|
@ -91,15 +91,6 @@ ShouldNurseryAllocate(const Nursery &nursery, AllocKind kind, InitialHeap heap)
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
IsInsideNursery(JSRuntime *rt, const void *thing)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
return rt->gcNursery.isInside(thing);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
inline JSGCTraceKind
|
||||
GetGCThingTraceKind(const void *thing)
|
||||
{
|
||||
|
@ -1471,7 +1471,7 @@ void
|
||||
TypeZone::init(JSContext *cx)
|
||||
{
|
||||
if (!cx ||
|
||||
!cx->hasOption(JSOPTION_TYPE_INFERENCE) ||
|
||||
!cx->options().typeInference() ||
|
||||
!cx->runtime()->jitSupportsFloatingPoint)
|
||||
{
|
||||
return;
|
||||
|
@ -4252,7 +4252,7 @@ GetPropertyHelperInline(JSContext *cx,
|
||||
}
|
||||
|
||||
/* Don't warn if extra warnings not enabled or for random getprop operations. */
|
||||
if (!cx->hasExtraWarningsOption() || (op != JSOP_GETPROP && op != JSOP_GETELEM))
|
||||
if (!cx->options().extraWarnings() || (op != JSOP_GETPROP && op != JSOP_GETELEM))
|
||||
return true;
|
||||
|
||||
/* Don't warn repeatedly for the same script. */
|
||||
@ -4518,7 +4518,7 @@ MaybeReportUndeclaredVarAssignment(JSContext *cx, JSString *propname)
|
||||
|
||||
// If the code is not strict and extra warnings aren't enabled, then no
|
||||
// check is needed.
|
||||
if (!script->strict && !cx->hasExtraWarningsOption())
|
||||
if (!script->strict && !cx->options().extraWarnings())
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4542,7 +4542,7 @@ js::ReportIfUndeclaredVarAssignment(JSContext *cx, HandleString propname)
|
||||
|
||||
// If the code is not strict and extra warnings aren't enabled, then no
|
||||
// check is needed.
|
||||
if (!script->strict && !cx->hasExtraWarningsOption())
|
||||
if (!script->strict && !cx->options().extraWarnings())
|
||||
return true;
|
||||
|
||||
/*
|
||||
@ -4682,7 +4682,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
|
||||
if (pd.isReadonly()) {
|
||||
if (strict)
|
||||
return JSObject::reportReadOnly(cx, id, JSREPORT_ERROR);
|
||||
if (cx->hasExtraWarningsOption())
|
||||
if (cx->options().extraWarnings())
|
||||
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
|
||||
return true;
|
||||
}
|
||||
@ -4744,7 +4744,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
|
||||
JSContext *cx = cxArg->asJSContext();
|
||||
if (strict)
|
||||
return JSObject::reportReadOnly(cx, id, JSREPORT_ERROR);
|
||||
if (cx->hasExtraWarningsOption())
|
||||
if (cx->options().extraWarnings())
|
||||
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
|
||||
return true;
|
||||
}
|
||||
@ -4840,7 +4840,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
|
||||
/* Error in strict mode code, warn with extra warnings option, otherwise do nothing. */
|
||||
if (strict)
|
||||
return obj->reportNotExtensible(cxArg);
|
||||
if (mode == SequentialExecution && cxArg->asJSContext()->hasExtraWarningsOption())
|
||||
if (mode == SequentialExecution && cxArg->asJSContext()->options().extraWarnings())
|
||||
return obj->reportNotExtensible(cxArg, JSREPORT_STRICT | JSREPORT_WARNING);
|
||||
return true;
|
||||
}
|
||||
|
@ -411,23 +411,26 @@ RunFile(JSContext *cx, Handle<JSObject*> obj, const char *filename, FILE *file,
|
||||
ungetc(ch, file);
|
||||
|
||||
int64_t t1 = PRMJ_Now();
|
||||
uint32_t oldopts = JS_GetOptions(cx);
|
||||
gGotError = false;
|
||||
JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
|
||||
CompileOptions options(cx);
|
||||
options.setUTF8(true)
|
||||
.setFileAndLine(filename, 1);
|
||||
|
||||
RootedScript script(cx);
|
||||
script = JS::Compile(cx, obj, options, file);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (dumpEntrainedVariables)
|
||||
AnalyzeEntrainedVariables(cx, script);
|
||||
#endif
|
||||
{
|
||||
AutoSaveContextOptions asco(cx);
|
||||
ContextOptionsRef(cx).setCompileAndGo(true)
|
||||
.setNoScriptRval(true);
|
||||
|
||||
JS_SetOptions(cx, oldopts);
|
||||
JS_ASSERT_IF(!script, gGotError);
|
||||
CompileOptions options(cx);
|
||||
options.setUTF8(true)
|
||||
.setFileAndLine(filename, 1);
|
||||
|
||||
gGotError = false;
|
||||
script = JS::Compile(cx, obj, options, file);
|
||||
JS_ASSERT_IF(!script, gGotError);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (dumpEntrainedVariables)
|
||||
AnalyzeEntrainedVariables(cx, script);
|
||||
#endif
|
||||
if (script && !compileOnly) {
|
||||
if (!JS_ExecuteScript(cx, obj, script, nullptr)) {
|
||||
if (!gQuitting && !gTimedOut)
|
||||
@ -570,50 +573,6 @@ Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* JSContext option name to flag map. The option names are in alphabetical
|
||||
* order for better reporting.
|
||||
*/
|
||||
static const struct JSOption {
|
||||
const char *name;
|
||||
uint32_t flag;
|
||||
} js_options[] = {
|
||||
{"strict", JSOPTION_EXTRA_WARNINGS},
|
||||
{"typeinfer", JSOPTION_TYPE_INFERENCE},
|
||||
{"werror", JSOPTION_WERROR},
|
||||
{"strict_mode", JSOPTION_STRICT_MODE},
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
MapContextOptionNameToFlag(JSContext* cx, const char* name)
|
||||
{
|
||||
for (size_t i = 0; i < ArrayLength(js_options); ++i) {
|
||||
if (strcmp(name, js_options[i].name) == 0)
|
||||
return js_options[i].flag;
|
||||
}
|
||||
|
||||
char* msg = JS_sprintf_append(nullptr,
|
||||
"unknown option name '%s'."
|
||||
" The valid names are ", name);
|
||||
for (size_t i = 0; i < ArrayLength(js_options); ++i) {
|
||||
if (!msg)
|
||||
break;
|
||||
msg = JS_sprintf_append(msg, "%s%s", js_options[i].name,
|
||||
(i + 2 < ArrayLength(js_options)
|
||||
? ", "
|
||||
: i + 2 == ArrayLength(js_options)
|
||||
? " and "
|
||||
: "."));
|
||||
}
|
||||
if (!msg) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
} else {
|
||||
JS_ReportError(cx, msg);
|
||||
free(msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
Version(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
@ -722,45 +681,66 @@ Options(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
uint32_t flag;
|
||||
JSString *str;
|
||||
char *names;
|
||||
bool found;
|
||||
|
||||
uint32_t optset = 0;
|
||||
ContextOptions oldOptions = ContextOptionsRef(cx);
|
||||
for (unsigned i = 0; i < args.length(); i++) {
|
||||
str = JS_ValueToString(cx, args[i]);
|
||||
JSString *str = JS_ValueToString(cx, args[i]);
|
||||
if (!str)
|
||||
return false;
|
||||
args[i].setString(str);
|
||||
|
||||
JSAutoByteString opt(cx, str);
|
||||
if (!opt)
|
||||
return false;
|
||||
flag = MapContextOptionNameToFlag(cx, opt.ptr());
|
||||
if (!flag)
|
||||
return false;
|
||||
optset |= flag;
|
||||
}
|
||||
optset = JS_ToggleOptions(cx, optset);
|
||||
|
||||
names = nullptr;
|
||||
found = false;
|
||||
for (size_t i = 0; i < ArrayLength(js_options); i++) {
|
||||
if (js_options[i].flag & optset) {
|
||||
found = true;
|
||||
names = JS_sprintf_append(names, "%s%s",
|
||||
names ? "," : "", js_options[i].name);
|
||||
if (!names)
|
||||
break;
|
||||
if (strcmp(opt.ptr(), "strict") == 0)
|
||||
ContextOptionsRef(cx).toggleExtraWarnings();
|
||||
else if (strcmp(opt.ptr(), "typeinfer") == 0)
|
||||
ContextOptionsRef(cx).toggleTypeInference();
|
||||
else if (strcmp(opt.ptr(), "werror") == 0)
|
||||
ContextOptionsRef(cx).toggleWerror();
|
||||
else if (strcmp(opt.ptr(), "strict_mode") == 0)
|
||||
ContextOptionsRef(cx).toggleStrictMode();
|
||||
else {
|
||||
char* msg = JS_sprintf_append(NULL,
|
||||
"unknown option name '%s'."
|
||||
" The valid names are strict,"
|
||||
" typeinfer, werror, and strict_mode.",
|
||||
opt.ptr());
|
||||
if (!msg) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ReportError(cx, msg);
|
||||
free(msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
names = strdup("");
|
||||
|
||||
char *names = strdup("");
|
||||
bool found = false;
|
||||
if (!names && oldOptions.extraWarnings()) {
|
||||
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict");
|
||||
found = true;
|
||||
}
|
||||
if (!names && oldOptions.typeInference()) {
|
||||
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "typeinfer");
|
||||
found = true;
|
||||
}
|
||||
if (!names && oldOptions.werror()) {
|
||||
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "werror");
|
||||
found = true;
|
||||
}
|
||||
if (!names && oldOptions.strictMode()) {
|
||||
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict_mode");
|
||||
found = true;
|
||||
}
|
||||
if (!names) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
str = JS_NewStringCopyZ(cx, names);
|
||||
|
||||
JSString *str = JS_NewStringCopyZ(cx, names);
|
||||
free(names);
|
||||
if (!str)
|
||||
return false;
|
||||
@ -836,7 +816,7 @@ class AutoNewContext
|
||||
newcx = NewContext(JS_GetRuntime(cx));
|
||||
if (!newcx)
|
||||
return false;
|
||||
JS_SetOptions(newcx, JS_GetOptions(newcx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
ContextOptionsRef(newcx).setDontReportUncaught(true);
|
||||
js::SetDefaultObjectForContext(newcx, JS::CurrentGlobalOrNull(cx));
|
||||
|
||||
newRequest.construct(newcx);
|
||||
@ -1071,22 +1051,22 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return false;
|
||||
|
||||
JSAutoCompartment ac(cx, global);
|
||||
uint32_t oldopts = JS_GetOptions(cx);
|
||||
uint32_t opts = oldopts & ~(JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
|
||||
if (compileAndGo)
|
||||
opts |= JSOPTION_COMPILE_N_GO;
|
||||
if (noScriptRval)
|
||||
opts |= JSOPTION_NO_SCRIPT_RVAL;
|
||||
RootedScript script(cx);
|
||||
|
||||
JS_SetOptions(cx, opts);
|
||||
CompileOptions options(cx);
|
||||
options.setFileAndLine(fileName, lineNumber);
|
||||
options.setElement(element);
|
||||
options.setSourcePolicy(sourcePolicy);
|
||||
RootedScript script(cx, JS::Compile(cx, global, options, codeChars, codeLength));
|
||||
JS_SetOptions(cx, oldopts);
|
||||
if (!script)
|
||||
return false;
|
||||
{
|
||||
AutoSaveContextOptions asco(cx);
|
||||
ContextOptionsRef(cx).setCompileAndGo(compileAndGo)
|
||||
.setNoScriptRval(noScriptRval);
|
||||
|
||||
CompileOptions options(cx);
|
||||
options.setFileAndLine(fileName, lineNumber)
|
||||
.setElement(element)
|
||||
.setSourcePolicy(sourcePolicy);
|
||||
|
||||
script = JS::Compile(cx, global, options, codeChars, codeLength);
|
||||
if (!script)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sourceURL && !script->scriptSource()->hasSourceURL()) {
|
||||
const jschar *surl = JS_GetStringCharsZ(cx, sourceURL);
|
||||
@ -1233,16 +1213,24 @@ Run(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return false;
|
||||
|
||||
JS::Anchor<JSString *> a_str(str);
|
||||
uint32_t oldopts = JS_GetOptions(cx);
|
||||
JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
|
||||
|
||||
RootedScript script(cx);
|
||||
int64_t startClock = PRMJ_Now();
|
||||
RootedScript script(cx, JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1));
|
||||
JS_SetOptions(cx, oldopts);
|
||||
if (!script || !JS_ExecuteScript(cx, thisobj, script, nullptr))
|
||||
{
|
||||
AutoSaveContextOptions asco(cx);
|
||||
ContextOptionsRef(cx).setCompileAndGo(true)
|
||||
.setNoScriptRval(true);
|
||||
|
||||
script = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1);
|
||||
if (!script)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS_ExecuteScript(cx, thisobj, script, NULL))
|
||||
return false;
|
||||
|
||||
int64_t endClock = PRMJ_Now();
|
||||
|
||||
args.rval().setDouble((endClock - startClock) / double(PRMJ_USEC_PER_MSEC));
|
||||
return true;
|
||||
}
|
||||
@ -2063,16 +2051,21 @@ DisassFile(JSContext *cx, unsigned argc, jsval *vp)
|
||||
JSAutoByteString filename(cx, str);
|
||||
if (!filename)
|
||||
return false;
|
||||
RootedScript script(cx);
|
||||
|
||||
uint32_t oldopts = JS_GetOptions(cx);
|
||||
JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
|
||||
CompileOptions options(cx);
|
||||
options.setUTF8(true)
|
||||
.setFileAndLine(filename.ptr(), 1);
|
||||
RootedScript script (cx, JS::Compile(cx, thisobj, options, filename.ptr()));
|
||||
JS_SetOptions(cx, oldopts);
|
||||
if (!script)
|
||||
return false;
|
||||
{
|
||||
AutoSaveContextOptions asco(cx);
|
||||
ContextOptionsRef(cx).setCompileAndGo(true)
|
||||
.setNoScriptRval(true);
|
||||
|
||||
CompileOptions options(cx);
|
||||
options.setUTF8(true)
|
||||
.setFileAndLine(filename.ptr(), 1);
|
||||
|
||||
script = JS::Compile(cx, thisobj, options, filename.ptr());
|
||||
if (!script)
|
||||
return false;
|
||||
}
|
||||
|
||||
Sprinter sprinter(cx);
|
||||
if (!sprinter.init())
|
||||
@ -3177,12 +3170,11 @@ Compile(JSContext *cx, unsigned argc, jsval *vp)
|
||||
|
||||
RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
|
||||
JSString *scriptContents = JSVAL_TO_STRING(arg0);
|
||||
unsigned oldopts = JS_GetOptions(cx);
|
||||
JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
|
||||
AutoSaveContextOptions asco(cx);
|
||||
ContextOptionsRef(cx).setCompileAndGo(true)
|
||||
.setNoScriptRval(true);
|
||||
bool ok = JS_CompileUCScript(cx, global, JS_GetStringCharsZ(cx, scriptContents),
|
||||
JS_GetStringLength(scriptContents), "<string>", 1);
|
||||
JS_SetOptions(cx, oldopts);
|
||||
|
||||
JS_SET_RVAL(cx, vp, UndefinedValue());
|
||||
return ok;
|
||||
}
|
||||
@ -4940,13 +4932,13 @@ NewContext(JSRuntime *rt)
|
||||
JS_SetContextPrivate(cx, data);
|
||||
JS_SetErrorReporter(cx, my_ErrorReporter);
|
||||
if (enableTypeInference)
|
||||
JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
|
||||
ContextOptionsRef(cx).toggleTypeInference();
|
||||
if (enableIon)
|
||||
JS_ToggleOptions(cx, JSOPTION_ION);
|
||||
ContextOptionsRef(cx).toggleIon();
|
||||
if (enableBaseline)
|
||||
JS_ToggleOptions(cx, JSOPTION_BASELINE);
|
||||
ContextOptionsRef(cx).toggleBaseline();
|
||||
if (enableAsmJS)
|
||||
JS_ToggleOptions(cx, JSOPTION_ASMJS);
|
||||
ContextOptionsRef(cx).toggleAsmJS();
|
||||
return cx;
|
||||
}
|
||||
|
||||
@ -5070,7 +5062,7 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
|
||||
reportWarnings = false;
|
||||
|
||||
if (op->getBoolOption('s'))
|
||||
JS_ToggleOptions(cx, JSOPTION_EXTRA_WARNINGS);
|
||||
ContextOptionsRef(cx).toggleExtraWarnings();
|
||||
|
||||
if (op->getBoolOption('d')) {
|
||||
JS_SetRuntimeDebugMode(JS_GetRuntime(cx), true);
|
||||
@ -5094,16 +5086,16 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
|
||||
#if defined(JS_ION)
|
||||
if (op->getBoolOption("no-ion")) {
|
||||
enableIon = false;
|
||||
JS_ToggleOptions(cx, JSOPTION_ION);
|
||||
ContextOptionsRef(cx).toggleIon();
|
||||
}
|
||||
if (op->getBoolOption("no-asmjs")) {
|
||||
enableAsmJS = false;
|
||||
JS_ToggleOptions(cx, JSOPTION_ASMJS);
|
||||
ContextOptionsRef(cx).toggleAsmJS();
|
||||
}
|
||||
|
||||
if (op->getBoolOption("no-baseline")) {
|
||||
enableBaseline = false;
|
||||
JS_ToggleOptions(cx, JSOPTION_BASELINE);
|
||||
ContextOptionsRef(cx).toggleBaseline();
|
||||
}
|
||||
|
||||
if (const char *str = op->getStringOption("ion-gvn")) {
|
||||
@ -5283,7 +5275,7 @@ Shell(JSContext *cx, OptionParser *op, char **envp)
|
||||
*/
|
||||
if (op->getBoolOption("no-ti")) {
|
||||
enableTypeInference = false;
|
||||
JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
|
||||
ContextOptionsRef(cx).toggleTypeInference();
|
||||
}
|
||||
|
||||
if (op->getBoolOption("fuzzing-safe"))
|
||||
|
@ -633,7 +633,7 @@ js::Execute(JSContext *cx, HandleScript script, JSObject &scopeChainArg, Value *
|
||||
#endif
|
||||
|
||||
/* The VAROBJFIX option makes varObj == globalObj in global code. */
|
||||
if (!cx->hasOption(JSOPTION_VAROBJFIX)) {
|
||||
if (!cx->options().varObjFix()) {
|
||||
if (!scopeChain->setVarObj(cx))
|
||||
return false;
|
||||
}
|
||||
|
@ -593,7 +593,7 @@ JSRuntime::initSelfHosting(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!selfHostingGlobal_);
|
||||
|
||||
bool receivesDefaultObject = !cx->hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT);
|
||||
bool receivesDefaultObject = !cx->options().noDefaultCompartmentObject();
|
||||
RootedObject savedGlobal(cx, receivesDefaultObject
|
||||
? js::DefaultObjectForContextOrNull(cx)
|
||||
: nullptr);
|
||||
|
@ -172,7 +172,7 @@ File(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
|
||||
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
||||
JSObject* glob = JS::CurrentGlobalOrNull(cx);
|
||||
JSObject* glob = CurrentGlobalOrNull(cx);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->WrapNativeToJSVal(cx, glob, native, nullptr,
|
||||
@ -207,7 +207,7 @@ Blob(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
|
||||
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
||||
JSObject* glob = JS::CurrentGlobalOrNull(cx);
|
||||
JSObject* glob = CurrentGlobalOrNull(cx);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->WrapNativeToJSVal(cx, glob, native, nullptr,
|
||||
@ -526,7 +526,7 @@ mozJSComponentLoader::LoadModule(FileLocation &aFile)
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::FindTargetObject(JSContext* aCx,
|
||||
JS::MutableHandleObject aTargetObject)
|
||||
MutableHandleObject aTargetObject)
|
||||
{
|
||||
aTargetObject.set(nullptr);
|
||||
|
||||
@ -632,8 +632,8 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx,
|
||||
rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.setZone(JS::SystemZone)
|
||||
CompartmentOptions options;
|
||||
options.setZone(SystemZone)
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(aCx,
|
||||
static_cast<nsIGlobalObject *>(backstagePass),
|
||||
@ -695,7 +695,7 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx,
|
||||
NS_ENSURE_TRUE(locationObj, nullptr);
|
||||
|
||||
if (!JS_DefineProperty(aCx, obj, "__LOCATION__",
|
||||
JS::ObjectValue(*locationObj),
|
||||
ObjectValue(*locationObj),
|
||||
nullptr, nullptr, 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -723,7 +723,7 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
JSObject **aObject,
|
||||
char **aLocation,
|
||||
bool aPropagateExceptions,
|
||||
JS::MutableHandleValue aException)
|
||||
MutableHandleValue aException)
|
||||
{
|
||||
JSCLContextHelper cx(mContext);
|
||||
|
||||
@ -781,39 +781,36 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
// If aPropagateExceptions is true, then our caller wants us to propagate
|
||||
// any exceptions out to our caller. Ensure that the engine doesn't
|
||||
// eagerly report the exception.
|
||||
uint32_t oldopts = JS_GetOptions(cx);
|
||||
AutoSaveContextOptions asco(cx);
|
||||
if (aPropagateExceptions)
|
||||
JS_SetOptions(cx, oldopts | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
ContextOptionsRef(cx).setDontReportUncaught(true);
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
CompileOptions options(cx);
|
||||
options.setPrincipals(nsJSPrincipals::get(mSystemPrincipal))
|
||||
.setNoScriptRval(mReuseLoaderGlobal ? false : true)
|
||||
.setVersion(JSVERSION_LATEST)
|
||||
.setFileAndLine(nativePath.get(), 1)
|
||||
.setSourcePolicy(mReuseLoaderGlobal ?
|
||||
JS::CompileOptions::NO_SOURCE :
|
||||
JS::CompileOptions::LAZY_SOURCE);
|
||||
CompileOptions::NO_SOURCE :
|
||||
CompileOptions::LAZY_SOURCE);
|
||||
|
||||
if (realFile) {
|
||||
#ifdef HAVE_PR_MEMMAP
|
||||
int64_t fileSize;
|
||||
rv = aComponentFile->GetFileSize(&fileSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int64_t maxSize = UINT32_MAX;
|
||||
if (fileSize > maxSize) {
|
||||
NS_ERROR("file too large");
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRFileDesc *fileHandle;
|
||||
rv = aComponentFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
@ -824,7 +821,6 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
PR_PROT_READONLY);
|
||||
if (!map) {
|
||||
NS_ERROR("Failed to create file map");
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -836,15 +832,14 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
char *buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32));
|
||||
if (!buf) {
|
||||
NS_WARNING("Failed to map file");
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mReuseLoaderGlobal) {
|
||||
script = JS::Compile(cx, obj, options, buf,
|
||||
script = Compile(cx, obj, options, buf,
|
||||
fileSize32);
|
||||
} else {
|
||||
function = JS::CompileFunction(cx, obj, options,
|
||||
function = CompileFunction(cx, obj, options,
|
||||
nullptr, 0, nullptr,
|
||||
buf, fileSize32);
|
||||
}
|
||||
@ -861,7 +856,6 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
FILE *fileHandle;
|
||||
rv = aComponentFile->OpenANSIFileDesc("r", &fileHandle);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
@ -872,31 +866,28 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
rv = aComponentFile->GetFileSize(&len);
|
||||
if (NS_FAILED(rv) || len < 0) {
|
||||
NS_WARNING("Failed to get file size");
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
char *buf = (char *) malloc(len * sizeof(char));
|
||||
if (!buf) {
|
||||
JS_SetOptions(cx, oldopts);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
size_t rlen = fread(buf, 1, len, fileHandle);
|
||||
if (rlen != (uint64_t)len) {
|
||||
free(buf);
|
||||
JS_SetOptions(cx, oldopts);
|
||||
NS_WARNING("Failed to read file");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mReuseLoaderGlobal) {
|
||||
script = JS::Compile(cx, obj, options, buf,
|
||||
script = Compile(cx, obj, options, buf,
|
||||
fileSize32);
|
||||
} else {
|
||||
function = JS::CompileFunction(cx, obj, options,
|
||||
nullptr, 0, nullptr,
|
||||
buf, fileSize32);
|
||||
function = CompileFunction(cx, obj, options,
|
||||
nullptr, 0, nullptr,
|
||||
buf, fileSize32);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
@ -937,16 +928,15 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
buf[len] = '\0';
|
||||
|
||||
if (!mReuseLoaderGlobal) {
|
||||
script = JS::Compile(cx, obj, options, buf, bytesRead);
|
||||
script = Compile(cx, obj, options, buf, bytesRead);
|
||||
} else {
|
||||
function = JS::CompileFunction(cx, obj, options,
|
||||
function = CompileFunction(cx, obj, options,
|
||||
nullptr, 0, nullptr,
|
||||
buf, bytesRead);
|
||||
}
|
||||
}
|
||||
// Propagate the exception, if one exists. Also, don't leave the stale
|
||||
// exception on this context.
|
||||
JS_SetOptions(cx, oldopts);
|
||||
if (!script && !function && aPropagateExceptions) {
|
||||
JS_GetPendingException(cx, aException);
|
||||
JS_ClearPendingException(cx);
|
||||
@ -987,17 +977,19 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
|
||||
}
|
||||
|
||||
mThisObjects.Put(tableScript, obj);
|
||||
|
||||
uint32_t oldopts = JS_GetOptions(cx);
|
||||
JS_SetOptions(cx, oldopts | (aPropagateExceptions ? JSOPTION_DONT_REPORT_UNCAUGHT : 0));
|
||||
bool ok = false;
|
||||
if (script) {
|
||||
ok = JS_ExecuteScriptVersion(cx, obj, script, nullptr, JSVERSION_LATEST);
|
||||
} else {
|
||||
jsval rval;
|
||||
ok = JS_CallFunction(cx, obj, function, 0, nullptr, &rval);
|
||||
}
|
||||
JS_SetOptions(cx, oldopts);
|
||||
|
||||
{
|
||||
AutoSaveContextOptions asco(cx);
|
||||
if (aPropagateExceptions)
|
||||
ContextOptionsRef(cx).setDontReportUncaught(true);
|
||||
if (script) {
|
||||
ok = JS_ExecuteScriptVersion(cx, obj, script, NULL, JSVERSION_LATEST);
|
||||
} else {
|
||||
jsval rval;
|
||||
ok = JS_CallFunction(cx, obj, function, 0, nullptr, &rval);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
if (aPropagateExceptions) {
|
||||
@ -1063,10 +1055,10 @@ mozJSComponentLoader::UnloadModules()
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::Import(const nsACString& registryLocation,
|
||||
const JS::Value& targetValArg,
|
||||
const Value& targetValArg,
|
||||
JSContext* cx,
|
||||
uint8_t optionalArgc,
|
||||
JS::Value* retval)
|
||||
Value* retval)
|
||||
{
|
||||
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
@ -1112,7 +1104,7 @@ mozJSComponentLoader::Import(const nsACString& registryLocation,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*retval = JS::ObjectValue(*global);
|
||||
*retval = ObjectValue(*global);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -1139,9 +1131,9 @@ mozJSComponentLoader::ImportInto(const nsACString & aLocation,
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::ImportInto(const nsACString &aLocation,
|
||||
JS::HandleObject targetObj,
|
||||
HandleObject targetObj,
|
||||
JSContext *callercx,
|
||||
JS::MutableHandleObject vp)
|
||||
MutableHandleObject vp)
|
||||
{
|
||||
vp.set(nullptr);
|
||||
|
||||
|
@ -1511,10 +1511,8 @@ ContextHolder::ContextHolder(JSContext *aOuterCx,
|
||||
IsSystemPrincipal(mPrincipal, &isChrome);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
JS_SetOptions(mJSContext,
|
||||
JS_GetOptions(mJSContext) |
|
||||
JSOPTION_DONT_REPORT_UNCAUGHT |
|
||||
JSOPTION_PRIVATE_IS_NSISUPPORTS);
|
||||
JS::ContextOptionsRef(mJSContext).setDontReportUncaught(true)
|
||||
.setPrivateIsNSISupports(true);
|
||||
js::SetDefaultObjectForContext(mJSContext, aSandbox);
|
||||
JS_SetContextPrivate(mJSContext, this);
|
||||
}
|
||||
|
@ -2624,7 +2624,7 @@ nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox **aSandbox)
|
||||
|
||||
/* void reportError (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ReportError(const JS::Value &errorArg, JSContext *cx)
|
||||
nsXPCComponents_Utils::ReportError(const Value &errorArg, JSContext *cx)
|
||||
{
|
||||
RootedValue error(cx, errorArg);
|
||||
|
||||
@ -2697,13 +2697,13 @@ nsXPCComponents_Utils::ReportError(const JS::Value &errorArg, JSContext *cx)
|
||||
/* void evalInSandbox(in AString source, in nativeobj sandbox); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
|
||||
const JS::Value& sandboxValArg,
|
||||
const JS::Value& version,
|
||||
const JS::Value& filenameVal,
|
||||
const Value& sandboxValArg,
|
||||
const Value& version,
|
||||
const Value& filenameVal,
|
||||
int32_t lineNumber,
|
||||
JSContext *cx,
|
||||
uint8_t optionalArgc,
|
||||
JS::Value *retval)
|
||||
Value *retval)
|
||||
{
|
||||
RootedValue sandboxVal(cx, sandboxValArg);
|
||||
RootedObject sandbox(cx);
|
||||
@ -2768,8 +2768,8 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::GetSandboxMetadata(const JS::Value &sandboxVal,
|
||||
JSContext *cx, JS::Value *rval)
|
||||
nsXPCComponents_Utils::GetSandboxMetadata(const Value &sandboxVal,
|
||||
JSContext *cx, Value *rval)
|
||||
{
|
||||
if (!sandboxVal.isObject())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@ -2788,8 +2788,8 @@ nsXPCComponents_Utils::GetSandboxMetadata(const JS::Value &sandboxVal,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::SetSandboxMetadata(const JS::Value &sandboxVal,
|
||||
const JS::Value &metadataVal,
|
||||
nsXPCComponents_Utils::SetSandboxMetadata(const Value &sandboxVal,
|
||||
const Value &metadataVal,
|
||||
JSContext *cx)
|
||||
{
|
||||
if (!sandboxVal.isObject())
|
||||
@ -2812,10 +2812,10 @@ nsXPCComponents_Utils::SetSandboxMetadata(const JS::Value &sandboxVal,
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::Import(const nsACString& registryLocation,
|
||||
const JS::Value& targetObj,
|
||||
const Value& targetObj,
|
||||
JSContext* cx,
|
||||
uint8_t optionalArgc,
|
||||
JS::Value* retval)
|
||||
Value* retval)
|
||||
{
|
||||
nsCOMPtr<xpcIJSModuleLoader> moduleloader =
|
||||
do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
|
||||
@ -2860,7 +2860,7 @@ nsXPCComponents_Utils::ImportGlobalProperties(const JS::Value& aPropertyList,
|
||||
|
||||
/* xpcIJSWeakReference getWeakReference (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::GetWeakReference(const JS::Value &object, JSContext *cx,
|
||||
nsXPCComponents_Utils::GetWeakReference(const Value &object, JSContext *cx,
|
||||
xpcIJSWeakReference **_retval)
|
||||
{
|
||||
nsRefPtr<xpcJSWeakReference> ref = new xpcJSWeakReference();
|
||||
@ -2875,8 +2875,8 @@ NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceGC()
|
||||
{
|
||||
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::GCForReason(rt, JS::gcreason::COMPONENT_UTILS);
|
||||
PrepareForFullGC(rt);
|
||||
GCForReason(rt, gcreason::COMPONENT_UTILS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2893,8 +2893,8 @@ NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceShrinkingGC()
|
||||
{
|
||||
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::ShrinkingGC(rt, JS::gcreason::COMPONENT_UTILS);
|
||||
PrepareForFullGC(rt);
|
||||
ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2916,11 +2916,11 @@ class PreciseGCRunnable : public nsRunnable
|
||||
}
|
||||
}
|
||||
|
||||
JS::PrepareForFullGC(rt);
|
||||
PrepareForFullGC(rt);
|
||||
if (mShrinking)
|
||||
JS::ShrinkingGC(rt, JS::gcreason::COMPONENT_UTILS);
|
||||
ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
|
||||
else
|
||||
JS::GCForReason(rt, JS::gcreason::COMPONENT_UTILS);
|
||||
GCForReason(rt, gcreason::COMPONENT_UTILS);
|
||||
|
||||
mCallback->Callback();
|
||||
return NS_OK;
|
||||
@ -2949,9 +2949,9 @@ nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback
|
||||
|
||||
/* [implicit_jscontext] jsval nondeterministicGetWeakMapKeys(in jsval aMap); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(const JS::Value &aMap,
|
||||
nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(const Value &aMap,
|
||||
JSContext *aCx,
|
||||
JS::Value *aKeys)
|
||||
Value *aKeys)
|
||||
{
|
||||
if (!aMap.isObject()) {
|
||||
aKeys->setUndefined();
|
||||
@ -2967,7 +2967,7 @@ nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(const JS::Value &aMap,
|
||||
/* void getDebugObject(); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx,
|
||||
JS::Value *retval)
|
||||
Value *retval)
|
||||
{
|
||||
JSObject *obj = js::GetTestingFunctions(cx);
|
||||
if (!obj)
|
||||
@ -2978,9 +2978,9 @@ nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx,
|
||||
|
||||
/* void getGlobalForObject(); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::GetGlobalForObject(const JS::Value& object,
|
||||
nsXPCComponents_Utils::GetGlobalForObject(const Value& object,
|
||||
JSContext *cx,
|
||||
JS::Value *retval)
|
||||
Value *retval)
|
||||
{
|
||||
// First argument must be an object.
|
||||
if (JSVAL_IS_PRIMITIVE(object))
|
||||
@ -2991,7 +2991,7 @@ nsXPCComponents_Utils::GetGlobalForObject(const JS::Value& object,
|
||||
// a wrapper for the foreign global. So we need to unwrap before getting the
|
||||
// parent, enter the compartment for the duration of the call, and wrap the
|
||||
// result.
|
||||
JS::Rooted<JSObject*> obj(cx, JSVAL_TO_OBJECT(object));
|
||||
Rooted<JSObject*> obj(cx, JSVAL_TO_OBJECT(object));
|
||||
obj = js::UncheckedUnwrap(obj);
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
@ -3100,7 +3100,7 @@ nsXPCComponents_Utils::MakeObjectPropsNormal(const Value &vobj, JSContext *cx)
|
||||
|
||||
RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
JS::AutoIdArray ida(cx, JS_Enumerate(cx, obj));
|
||||
AutoIdArray ida(cx, JS_Enumerate(cx, obj));
|
||||
if (!ida)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@ -3261,42 +3261,24 @@ nsXPCComponents_Utils::CanSetProperty(const nsIID * iid, const PRUnichar *proper
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetBoolOption(JSContext* cx, uint32_t aOption, bool* aValue)
|
||||
{
|
||||
*aValue = !!(JS_GetOptions(cx) & aOption);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
SetBoolOption(JSContext* cx, uint32_t aOption, bool aValue)
|
||||
{
|
||||
uint32_t options = JS_GetOptions(cx);
|
||||
if (aValue) {
|
||||
options |= aOption;
|
||||
} else {
|
||||
options &= ~aOption;
|
||||
}
|
||||
JS_SetOptions(cx, options & JSOPTION_MASK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#define GENERATE_JSOPTION_GETTER_SETTER(_attr, _flag) \
|
||||
NS_IMETHODIMP \
|
||||
nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
|
||||
{ \
|
||||
return GetBoolOption(cx, _flag, aValue); \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
|
||||
{ \
|
||||
return SetBoolOption(cx, _flag, aValue); \
|
||||
#define GENERATE_JSOPTION_GETTER_SETTER(_attr, _getter, _setter) \
|
||||
NS_IMETHODIMP \
|
||||
nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
|
||||
{ \
|
||||
*aValue = ContextOptionsRef(cx)._getter(); \
|
||||
return NS_OK; \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
|
||||
{ \
|
||||
ContextOptionsRef(cx)._setter(aValue); \
|
||||
return NS_OK; \
|
||||
}
|
||||
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Strict, JSOPTION_EXTRA_WARNINGS)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Werror, JSOPTION_WERROR)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Strict_mode, JSOPTION_STRICT_MODE)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Ion, JSOPTION_ION)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Werror, werror, setWerror)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
|
||||
GENERATE_JSOPTION_GETTER_SETTER(Ion, ion, setIon)
|
||||
|
||||
#undef GENERATE_JSOPTION_GETTER_SETTER
|
||||
|
||||
@ -3310,7 +3292,7 @@ nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::NukeSandbox(const JS::Value &obj, JSContext *cx)
|
||||
nsXPCComponents_Utils::NukeSandbox(const Value &obj, JSContext *cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG);
|
||||
JSObject *wrapper = &obj.toObject();
|
||||
@ -3324,7 +3306,7 @@ nsXPCComponents_Utils::NukeSandbox(const JS::Value &obj, JSContext *cx)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::IsXrayWrapper(const JS::Value &obj, bool* aRetval)
|
||||
nsXPCComponents_Utils::IsXrayWrapper(const Value &obj, bool* aRetval)
|
||||
{
|
||||
*aRetval =
|
||||
obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
|
||||
@ -3332,7 +3314,7 @@ nsXPCComponents_Utils::IsXrayWrapper(const JS::Value &obj, bool* aRetval)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::WaiveXrays(const JS::Value &aVal, JSContext *aCx, jsval *aRetval)
|
||||
nsXPCComponents_Utils::WaiveXrays(const Value &aVal, JSContext *aCx, jsval *aRetval)
|
||||
{
|
||||
*aRetval = aVal;
|
||||
if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, aRetval))
|
||||
@ -3341,7 +3323,7 @@ nsXPCComponents_Utils::WaiveXrays(const JS::Value &aVal, JSContext *aCx, jsval *
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::UnwaiveXrays(const JS::Value &aVal, JSContext *aCx, jsval *aRetval)
|
||||
nsXPCComponents_Utils::UnwaiveXrays(const Value &aVal, JSContext *aCx, jsval *aRetval)
|
||||
{
|
||||
if (!aVal.isObject()) {
|
||||
*aRetval = aVal;
|
||||
@ -3355,7 +3337,7 @@ nsXPCComponents_Utils::UnwaiveXrays(const JS::Value &aVal, JSContext *aCx, jsval
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::GetClassName(const JS::Value &aObj, bool aUnwrap, JSContext *aCx, char **aRv)
|
||||
nsXPCComponents_Utils::GetClassName(const Value &aObj, bool aUnwrap, JSContext *aCx, char **aRv)
|
||||
{
|
||||
if (!aObj.isObject())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@ -3701,12 +3683,12 @@ nsXPCComponents::AttachComponentsObject(JSContext* aCx,
|
||||
MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx));
|
||||
|
||||
RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
|
||||
return JS_DefinePropertyById(aCx, global, id, JS::ObjectValue(*components),
|
||||
return JS_DefinePropertyById(aCx, global, id, ObjectValue(*components),
|
||||
nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
}
|
||||
|
||||
/* void reportError (); */
|
||||
NS_IMETHODIMP nsXPCComponents::ReportError(const JS::Value &error, JSContext *cx)
|
||||
NS_IMETHODIMP nsXPCComponents::ReportError(const Value &error, JSContext *cx)
|
||||
{
|
||||
NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
|
||||
|
||||
|
@ -244,13 +244,12 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
|
||||
// is not an exception that is ever worth reporting, but we don't want
|
||||
// to eat all exceptions either.
|
||||
|
||||
uint32_t oldOpts =
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
|
||||
jsval args[1] = {OBJECT_TO_JSVAL(id)};
|
||||
success = JS_CallFunctionValue(cx, jsobj, fun, 1, args, retval.address());
|
||||
|
||||
JS_SetOptions(cx, oldOpts);
|
||||
{
|
||||
AutoSaveContextOptions asco(cx);
|
||||
ContextOptionsRef(cx).setDontReportUncaught(true);
|
||||
jsval args[1] = {OBJECT_TO_JSVAL(id)};
|
||||
success = JS_CallFunctionValue(cx, jsobj, fun, 1, args, retval.address());
|
||||
}
|
||||
|
||||
if (!success && JS_IsExceptionPending(cx)) {
|
||||
RootedValue jsexception(cx, NullValue());
|
||||
@ -285,7 +284,7 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
|
||||
}
|
||||
|
||||
// Don't report if reporting was disabled by someone else.
|
||||
if (!(oldOpts & JSOPTION_DONT_REPORT_UNCAUGHT))
|
||||
if (!ContextOptionsRef(cx).dontReportUncaught())
|
||||
JS_ReportPendingException(cx);
|
||||
} else if (!success) {
|
||||
NS_WARNING("QI hook ran OOMed - this is probably a bug!");
|
||||
@ -1418,12 +1417,10 @@ pre_call_clean_up:
|
||||
success = JS_SetProperty(cx, obj, name, rval);
|
||||
} else {
|
||||
if (!JSVAL_IS_PRIMITIVE(fval)) {
|
||||
uint32_t oldOpts = JS_GetOptions(cx);
|
||||
JS_SetOptions(cx, oldOpts | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
AutoSaveContextOptions asco(cx);
|
||||
ContextOptionsRef(cx).setDontReportUncaught(true);
|
||||
|
||||
success = JS_CallFunctionValue(cx, thisObj, fval, argc, argv, rval.address());
|
||||
|
||||
JS_SetOptions(cx, oldOpts);
|
||||
} else {
|
||||
// The property was not an object so can't be a function.
|
||||
// Let's build and 'throw' an exception.
|
||||
|
@ -428,7 +428,7 @@ CheckTypeInference(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal)
|
||||
return;
|
||||
|
||||
// Finally, do the damn assert.
|
||||
MOZ_ASSERT(JS_GetOptions(cx) & JSOPTION_TYPE_INFERENCE);
|
||||
MOZ_ASSERT(ContextOptionsRef(cx).typeInference());
|
||||
}
|
||||
#else
|
||||
#define CheckTypeInference(cx, clasp, principal) {}
|
||||
|
@ -52,7 +52,7 @@ function run_test()
|
||||
// Test sync XHR sending
|
||||
cu.evalInSandbox('var createXHR = ' + createXHR.toString(), sb);
|
||||
var res = cu.evalInSandbox('var sync = createXHR("4444/simple"); sync.send(null); sync', sb);
|
||||
do_check_true(checkResults(res));
|
||||
checkResults(res);
|
||||
|
||||
// negative test sync XHR sending (to ensure that the xhr do not have chrome caps, see bug 779821)
|
||||
try {
|
||||
|
@ -20,6 +20,7 @@ import android.widget.TextView;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class is an extension of BaseTest that helps with interaction with about:home
|
||||
@ -97,6 +98,10 @@ abstract class AboutHomeTest extends BaseTest {
|
||||
// @return the View associated with bookmark for the provided url or null if the link is not bookmarked
|
||||
protected View getDisplayedBookmark(String url) {
|
||||
openAboutHomeTab(AboutHomeTabs.BOOKMARKS);
|
||||
if (!mDevice.type.equals("tablet")) {
|
||||
toggleVKB(); // dismiss the keyboard to make sure this works on small screen devices
|
||||
}
|
||||
getInstrumentation().waitForIdleSync();
|
||||
ListView bookmarksTabList = findListViewWithTag("bookmarks");
|
||||
waitForNonEmptyListToLoad(bookmarksTabList);
|
||||
ListAdapter adapter = bookmarksTabList.getAdapter();
|
||||
@ -177,59 +182,30 @@ abstract class AboutHomeTest extends BaseTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test
|
||||
* This method will edit the bookmark with index = bookmarkIndex from the list of bookmarks
|
||||
* For the field index:
|
||||
* fieldIndex = 1 - the Bookmark name
|
||||
* fieldIndex = 2 - the Bookmark url
|
||||
* fieldIndex = 3 - the Bookmark keyword
|
||||
* @param1 a String with the original url
|
||||
* @param2 a String array with the new values for all fields
|
||||
*/
|
||||
protected void editBookmark(int bookmarkIndex, int fieldIndex, String addedText, ListView list) {
|
||||
|
||||
// Open the Edit Bookmark context menu
|
||||
View child;
|
||||
mSolo.clickOnText("Bookmarks");
|
||||
child = list.getChildAt(bookmarkIndex);
|
||||
mAsserter.ok(child != null, "edit item can be retrieved", child != null ? child.toString() : "null!");
|
||||
waitForText("Switch to tab");
|
||||
mSolo.clickLongOnView(child);
|
||||
waitForText("Share");
|
||||
protected void editBookmark(String originalUrl, String[] newValues) {
|
||||
openBookmarkContextMenu(originalUrl);
|
||||
mSolo.clickOnText("Edit");
|
||||
waitForText("Edit Bookmark");
|
||||
|
||||
// Clear the Field
|
||||
mSolo.clearEditText(fieldIndex);
|
||||
|
||||
// Enter the new text
|
||||
mSolo.clickOnEditText(fieldIndex);
|
||||
mActions.sendKeys(addedText);
|
||||
mSolo.clickOnText("OK");
|
||||
for (String value:newValues) {
|
||||
mSolo.clearEditText(Arrays.asList(newValues).indexOf(value));
|
||||
mSolo.clickOnEditText(Arrays.asList(newValues).indexOf(value));
|
||||
mActions.sendKeys(value);
|
||||
}
|
||||
mSolo.clickOnButton("OK");
|
||||
waitForText("Bookmark updated");
|
||||
}
|
||||
|
||||
// FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test
|
||||
protected boolean checkBookmarkEdit(int bookmarkIndex, String addedText, ListView list) {
|
||||
// Open the Edit Bookmark context menu
|
||||
View child;
|
||||
mSolo.clickOnText("Bookmarks");
|
||||
child = list.getChildAt(bookmarkIndex);
|
||||
mAsserter.ok(child != null, "check item can be retrieved", child != null ? child.toString() : "null!");
|
||||
waitForText("Switch to tab");
|
||||
mSolo.clickLongOnView(child);
|
||||
waitForText("Share");
|
||||
protected void checkBookmarkEdit(String bookmarkUrl, String[] values) {
|
||||
openBookmarkContextMenu(bookmarkUrl);
|
||||
mSolo.clickOnText("Edit");
|
||||
waitForText("Edit Bookmark");
|
||||
|
||||
// Check if the new text was added
|
||||
if (mSolo.searchText(addedText)) {
|
||||
clickOnButton("Cancel");
|
||||
waitForText("about:home");
|
||||
return true;
|
||||
} else {
|
||||
clickOnButton("Cancel");
|
||||
waitForText("about:home");
|
||||
return false;
|
||||
for (String value:values) {
|
||||
mAsserter.ok(mSolo.searchText(value), "Checking that the value is correct", "The value = " + value + " is correct");
|
||||
}
|
||||
clickOnButton("Cancel");
|
||||
waitForText("BOOKMARKS");
|
||||
}
|
||||
|
||||
// A wait in order for the about:home tab to be rendered after drag/tab selection
|
||||
|
@ -45,6 +45,8 @@ class StringHelper {
|
||||
"Add to Home Screen"
|
||||
};
|
||||
|
||||
public static final String[] BOOKMARK_CONTEXT_MENU_ITEMS = {"Open in New Tab", "Open in Private Tab", "Share", "Edit", "Remove", "Add to Home Screen"};
|
||||
|
||||
// Robocop page urls
|
||||
// Note: please use getAbsoluteUrl(String url) on each robocop url to get the correct url
|
||||
public static final String ROBOCOP_BIG_LINK_URL = "/robocop/robocop_big_link.html";
|
||||
|
@ -1,6 +1,7 @@
|
||||
[testAwesomebar]
|
||||
# [testAwesomebarSwipes] # disabled on fig - bug 880060
|
||||
[testBookmark]
|
||||
[testBookmarksPage]
|
||||
# [testBookmarklets] # see bug 915350
|
||||
# [testBookmarkKeyword] # see bug 915350
|
||||
[testBrowserSearchVisibility]
|
||||
|
223
mobile/android/base/tests/testBookmarksPage.java.in
Normal file
223
mobile/android/base/tests/testBookmarksPage.java.in
Normal file
@ -0,0 +1,223 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
|
||||
import com.jayway.android.robotium.solo.Condition;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.ContentUris;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class testBookmarksPage extends AboutHomeTest {
|
||||
private static String BOOKMARK_URL;
|
||||
private static String DESKTOP_BOOKMARK_URL;
|
||||
|
||||
@Override
|
||||
protected int getTestType() {
|
||||
return TEST_MOCHITEST;
|
||||
}
|
||||
|
||||
public void testBookmarksPage() {
|
||||
BOOKMARK_URL = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_01_URL);
|
||||
DESKTOP_BOOKMARK_URL = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_02_URL);
|
||||
|
||||
setUpDesktopBookmarks();
|
||||
checkBookmarkList();
|
||||
checkBookmarkContextMenu();
|
||||
}
|
||||
|
||||
private void checkBookmarkList() {
|
||||
// Check that the default bookmarks are displayed
|
||||
for (String url:StringHelper.DEFAULT_BOOKMARKS_URLS) {
|
||||
mAsserter.ok(isBookmarkDisplayed(url), "Checking that default bookmark: " + url + " is displayed in the bookmarks list", url + " is displayed as a bookmark");
|
||||
}
|
||||
mAsserter.ok(isBookmarkDisplayed(BOOKMARK_URL), "Checking that added bookmark: " + BOOKMARK_URL + " is displayed in the bookmarks list", BOOKMARK_URL + " is displayed as a bookmark");
|
||||
|
||||
waitForText(StringHelper.DESKTOP_FOLDER_LABEL);
|
||||
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
|
||||
waitForText(StringHelper.TOOLBAR_FOLDER_LABEL);
|
||||
|
||||
// Verify the number of folders displayed in the Desktop Bookmarks folder is correct
|
||||
ListView desktopFolderContent = findListViewWithTag("bookmarks");
|
||||
ListAdapter adapter = desktopFolderContent.getAdapter();
|
||||
if (mDevice.type.equals("tablet")) { // On tablets it's 4 folders and 1 view for top padding
|
||||
mAsserter.is(adapter.getCount(), 5, "Checking that the correct number of folders is displayed in the Desktop Bookmarks folder");
|
||||
} else { // On phones it's just the 4 folders
|
||||
mAsserter.is(adapter.getCount(), 4, "Checking that the correct number of folders is displayed in the Desktop Bookmarks folder");
|
||||
}
|
||||
|
||||
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
|
||||
|
||||
// Go up in the bookmark folder hierarchy
|
||||
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
|
||||
mAsserter.ok(waitForText(StringHelper.BOOKMARKS_MENU_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the Desktop Bookmarks folder");
|
||||
|
||||
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
|
||||
mAsserter.ok(waitForText(StringHelper.DESKTOP_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the main Bookmarks List View");
|
||||
|
||||
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
|
||||
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
|
||||
mAsserter.ok(isBookmarkDisplayed(DESKTOP_BOOKMARK_URL), "Checking that added bookmark: " + DESKTOP_BOOKMARK_URL + " is displayed in the bookmarks list", DESKTOP_BOOKMARK_URL + " is displayed as a bookmark");
|
||||
|
||||
// Open the bookmark from a bookmark folder hierarchy
|
||||
loadBookmark(DESKTOP_BOOKMARK_URL);
|
||||
waitForText(StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE);
|
||||
verifyPageTitle(StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE);
|
||||
openAboutHomeTab(AboutHomeTabs.BOOKMARKS);
|
||||
|
||||
// Check that folders don't have a context menu
|
||||
boolean success = waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
View desktopFolder = getBookmarkFolderView(StringHelper.DESKTOP_FOLDER_LABEL);
|
||||
if (desktopFolder != null) {
|
||||
mSolo.clickLongOnView(desktopFolder);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, MAX_WAIT_MS);
|
||||
mAsserter.ok(success, "Trying to long click on the Desktop Bookmarks","Desktop Bookmarks folder could not be long clicked");
|
||||
mAsserter.ok(!waitForText("Share"), "Folders do not have context menus", "The context menu was not opened");
|
||||
|
||||
// Even if no context menu is opened long clicking a folder still opens it. We need to close it.
|
||||
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
|
||||
}
|
||||
|
||||
private void checkBookmarkContextMenu() {
|
||||
// Open default bookmarks in a new tab and a new private tab since the url is substituted with "Switch to tab" after opening the link
|
||||
openBookmarkContextMenu(StringHelper.DEFAULT_BOOKMARKS_URLS[1]);
|
||||
|
||||
// Test that the options are all displayed
|
||||
for (String contextMenuOption:StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS) {
|
||||
mAsserter.ok(mSolo.searchText(contextMenuOption), "Checking that the context menu option is present", contextMenuOption + " is present");
|
||||
}
|
||||
|
||||
// Test that "Open in New Tab" works
|
||||
final Element tabCount = mDriver.findElement(getActivity(), "tabs_counter");
|
||||
final int tabCountInt = Integer.parseInt(tabCount.getText());
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[0]);
|
||||
tabEventExpecter.blockForEvent();
|
||||
tabEventExpecter.unregisterListener();
|
||||
|
||||
// Test that "Open in Private Tab" works
|
||||
openBookmarkContextMenu(StringHelper.DEFAULT_BOOKMARKS_URLS[2]);
|
||||
tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[1]);
|
||||
tabEventExpecter.blockForEvent();
|
||||
tabEventExpecter.unregisterListener();
|
||||
|
||||
// Test that "Share" works
|
||||
openBookmarkContextMenu(BOOKMARK_URL);
|
||||
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[2]);
|
||||
mAsserter.ok(waitForText("Share via"), "Checking to see if the share menu has been opened","The share menu has been opened");
|
||||
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
|
||||
waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE);
|
||||
|
||||
// Test that "Edit" works
|
||||
String[] editedBookmarkValues = {"New bookmark title", "www.NewBookmark.url", "newBookmarkKeyword"};
|
||||
editBookmark(BOOKMARK_URL,editedBookmarkValues);
|
||||
checkBookmarkEdit(editedBookmarkValues[1],editedBookmarkValues);
|
||||
|
||||
// Test that "Remove" works
|
||||
openBookmarkContextMenu(editedBookmarkValues[1]);
|
||||
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[4]);
|
||||
waitForText("Bookmark removed");
|
||||
mAsserter.ok(!mDatabaseHelper.isBookmark(editedBookmarkValues[1]), "Checking that the bookmark was removed", "The bookmark was removed");
|
||||
}
|
||||
|
||||
private void clickOnBookmarkFolder(final String folderName) {
|
||||
boolean success = waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
View bookmarksFolder = getBookmarkFolderView(folderName);
|
||||
if (bookmarksFolder != null) {
|
||||
mSolo.clickOnView(bookmarksFolder);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, MAX_WAIT_MS);
|
||||
mAsserter.ok(success, "Trying to click on the " + folderName + " folder","The " + folderName + " folder was clicked");
|
||||
}
|
||||
|
||||
private View getBookmarkFolderView(String folderName) {
|
||||
ListView bookmarksTabList = findListViewWithTag("bookmarks");
|
||||
ListAdapter adapter = bookmarksTabList.getAdapter();
|
||||
if (adapter != null) {
|
||||
for (int i = 0; i < adapter.getCount(); i++ ) {
|
||||
View bookmarkView = bookmarksTabList.getChildAt(i);
|
||||
if (bookmarkView instanceof TextView) {
|
||||
TextView folderTextView = (TextView) bookmarkView;
|
||||
if (folderTextView.getText().equals(folderName)) {
|
||||
return bookmarkView;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add a bookmark in the Desktop folder so we can check the folder navigation in the bookmarks page
|
||||
private void setUpDesktopBookmarks() {
|
||||
// Get the folder id of the StringHelper.DESKTOP_FOLDER_LABEL folder
|
||||
Long desktopFolderId = mDatabaseHelper.getFolderIdFromGuid("toolbar");
|
||||
|
||||
// Generate a Guid for the bookmark
|
||||
String generatedGuid = null;
|
||||
try {
|
||||
ClassLoader classLoader = getActivity().getClassLoader();
|
||||
Class syncUtilityClass = classLoader.loadClass("org.mozilla.gecko.sync.Utils");
|
||||
Method generateGuid = syncUtilityClass.getMethod("generateGuid", (Class[]) null);
|
||||
generatedGuid = (String)generateGuid.invoke(null);
|
||||
} catch (Exception e) {
|
||||
mAsserter.dumpLog("Exception in setUpDesktopBookmarks" + e);
|
||||
}
|
||||
mAsserter.ok((generatedGuid != null), "Generating a random Guid for the bookmark", "We could not generate a Guid for the bookmark");
|
||||
|
||||
// Insert the bookmark
|
||||
ContentResolver resolver = getActivity().getContentResolver();
|
||||
Uri bookmarksUri = mDatabaseHelper.buildUri(DatabaseHelper.BrowserDataType.BOOKMARKS);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("title", StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE);
|
||||
values.put("url", DESKTOP_BOOKMARK_URL);
|
||||
values.put("parent", desktopFolderId);
|
||||
long now = System.currentTimeMillis();
|
||||
values.put("modified", now);
|
||||
values.put("type", 1);
|
||||
values.put("guid", generatedGuid);
|
||||
values.put("position", 10);
|
||||
values.put("created", now);
|
||||
int updated = resolver.update(bookmarksUri,
|
||||
values,
|
||||
"url = ?",
|
||||
new String[] { DESKTOP_BOOKMARK_URL });
|
||||
if (updated == 0) {
|
||||
Uri uri = resolver.insert(bookmarksUri, values);
|
||||
mAsserter.ok(true, "Inserted at: ", uri.toString());
|
||||
} else {
|
||||
mAsserter.ok(false, "Failed to insert the Desktop bookmark", "Something went wrong");
|
||||
}
|
||||
|
||||
// Add a mobile bookmark
|
||||
mDatabaseHelper.addOrUpdateMobileBookmark(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
mDatabaseHelper.deleteBookmark(DESKTOP_BOOKMARK_URL);
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
@ -54,7 +54,7 @@
|
||||
}
|
||||
},
|
||||
"mobile-suites": {
|
||||
"remote-ts": {
|
||||
"remote-tspaint": {
|
||||
"tests": ["ts_paint"]
|
||||
},
|
||||
"remote-tsvgx": {
|
||||
|
@ -18,7 +18,7 @@ this.FormAutoCompleteResult =
|
||||
labels,
|
||||
comments,
|
||||
prevResult) {
|
||||
this._searchString = searchString;
|
||||
this.searchString = searchString;
|
||||
this._searchResult = searchResult;
|
||||
this._defaultIndex = defaultIndex;
|
||||
this._errorDescription = errorDescription;
|
||||
@ -37,7 +37,7 @@ this.FormAutoCompleteResult =
|
||||
FormAutoCompleteResult.prototype = {
|
||||
|
||||
// The user's query string
|
||||
_searchString: "",
|
||||
searchString: "",
|
||||
|
||||
// The result code of this result object, see |get searchResult| for possible values.
|
||||
_searchResult: 0,
|
||||
@ -60,13 +60,6 @@ FormAutoCompleteResult.prototype = {
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return the user's query string
|
||||
*/
|
||||
get searchString() {
|
||||
return this._searchString;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return the result code of this result object, either:
|
||||
* RESULT_IGNORED (invalid searchString)
|
||||
|
25
toolkit/components/satchel/test/unit/test_previous_result.js
Normal file
25
toolkit/components/satchel/test/unit/test_previous_result.js
Normal file
@ -0,0 +1,25 @@
|
||||
/* 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/. */
|
||||
|
||||
let aaaListener = {
|
||||
onSearchResult: function(search, result) {
|
||||
do_check_eq(result.searchString, "aaa");
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
|
||||
let aaListener = {
|
||||
onSearchResult: function(search, result) {
|
||||
do_check_eq(result.searchString, "aa");
|
||||
search.startSearch("aaa", "", result, aaaListener);
|
||||
}
|
||||
};
|
||||
|
||||
function run_test()
|
||||
{
|
||||
do_test_pending();
|
||||
let search = Cc['@mozilla.org/autocomplete/search;1?name=form-history'].
|
||||
getService(Components.interfaces.nsIAutoCompleteSearch);
|
||||
search.startSearch("aa", "", null, aaListener);
|
||||
}
|
@ -22,3 +22,4 @@ support-files =
|
||||
[test_db_update_v999b.js]
|
||||
[test_history_api.js]
|
||||
[test_notify.js]
|
||||
[test_previous_result.js]
|
||||
|
@ -97,7 +97,7 @@ endif
|
||||
endif #}
|
||||
|
||||
ifneq ($(strip $(MOZ_B2G_RIL)$(MOZ_B2G_BT)),) #{
|
||||
STATIC_LIBS += mozipcunixsocket_s
|
||||
STATIC_LIBS += mozipcunixsocket_s mozkeystore_s
|
||||
endif #}
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
@ -659,7 +659,7 @@
|
||||
if (results && results.matchCount > 0 &&
|
||||
!results.errorDescription && results.defaultIndex != -1)
|
||||
{
|
||||
val = this.getSessionValueAt(name, results.defaultIndex);
|
||||
val = results.getValueAt(results.defaultIndex);
|
||||
this.setTextValue(val);
|
||||
this.mDefaultMatchFilled = true;
|
||||
this.mNeedToFinish = false;
|
||||
@ -865,10 +865,32 @@
|
||||
|
||||
case KeyEvent.DOM_VK_BACK_SPACE:
|
||||
if (!aEvent.ctrlKey && !aEvent.altKey && !aEvent.shiftKey &&
|
||||
this.selectionStart == this.currentSearchString.length &&
|
||||
this.selectionEnd == this.value.length &&
|
||||
this.mDefaultMatchFilled) {
|
||||
this.mDefaultMatchFilled = false;
|
||||
this.value = this.currentSearchString.substring(0, this.selectionStart);
|
||||
this.mDefaultMatchFilled = false;
|
||||
this.value = this.currentSearchString;
|
||||
}
|
||||
|
||||
if (!/Mac/.test(navigator.platform))
|
||||
break;
|
||||
case KeyEvent.DOM_VK_DELETE:
|
||||
if (/Mac/.test(navigator.platform) && !aEvent.shiftKey)
|
||||
break;
|
||||
|
||||
if (this.mMenuOpen && this.popup.selectedIndex != -1) {
|
||||
var obj = this.convertIndexToSession(this.popup.selectedIndex);
|
||||
if (obj) {
|
||||
var result = this.mLastResults[obj.session];
|
||||
if (!result.errorDescription) {
|
||||
var count = result.matchCount;
|
||||
result.removeValueAt(obj.index, true);
|
||||
this.view.updateResults(this.popup.selectedIndex, result.matchCount - count);
|
||||
killEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (killEvent) {
|
||||
@ -1202,7 +1224,7 @@
|
||||
var result = this.mTextbox.mLastResults[name];
|
||||
switch (aCol.id) {
|
||||
case "treecolAutoCompleteValue":
|
||||
return result.errorDescription || result.getValueAt(aRow);
|
||||
return result.errorDescription || result.getLabelAt(aRow);
|
||||
case "treecolAutoCompleteComment":
|
||||
if (!result.errorDescription)
|
||||
return result.getCommentAt(aRow);
|
||||
@ -1243,11 +1265,26 @@
|
||||
{
|
||||
return "";
|
||||
},
|
||||
|
||||
getImageSrc: function(aRow, aCol)
|
||||
{
|
||||
if (aCol.id == "treecolAutoCompleteValue") {
|
||||
for (var name in this.mTextbox.mSessions) {
|
||||
if (aRow < this.mTextbox.mLastRows[name]) {
|
||||
var result = this.mTextbox.mLastResults[name];
|
||||
if (result.errorDescription)
|
||||
return "";
|
||||
return result.getImageAt(aRow);
|
||||
}
|
||||
aRow -= this.mTextbox.mLastRows[name];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
getParentIndex: function(aRowIndex) { },
|
||||
hasNextSibling: function(aRowIndex, aAfterIndex) { },
|
||||
getLevel: function(aIndex) {},
|
||||
getImageSrc: function(aRow, aCol) {},
|
||||
getProgressMode: function(aRow, aCol) {},
|
||||
getCellValue: function(aRow, aCol) {},
|
||||
isContainer: function(aIndex) {},
|
||||
|
Loading…
Reference in New Issue
Block a user