mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge b2g-inbound to m-c.
This commit is contained in:
commit
c511df94e8
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "052499d9ddb89a1168cb5fcd092c15095ef3a6a9",
|
||||
"revision": "01b437206d143e1632ee5a5fd49cc649aee2e970",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bbe0fd0ca135d089b662975eeced57530ebb7554"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c6b5142d3b716f1c4ea502eeb92d3119f2b01c6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -381,7 +381,8 @@ MediaCacheStream::MediaCacheStream(ChannelMediaResource* aClient)
|
||||
mPlaybackBytesPerSecond(10000),
|
||||
mPinCount(0),
|
||||
mCurrentMode(MODE_PLAYBACK),
|
||||
mMetadataInPartialBlockBuffer(false)
|
||||
mMetadataInPartialBlockBuffer(false),
|
||||
mPartialBlockBuffer(new int64_t[BLOCK_SIZE/sizeof(int64_t)])
|
||||
{
|
||||
}
|
||||
|
||||
@ -1735,12 +1736,12 @@ MediaCacheStream::NotifyDataReceived(int64_t aSize, const char* aData,
|
||||
// to clear this flag.
|
||||
mMetadataInPartialBlockBuffer = false;
|
||||
}
|
||||
memcpy(reinterpret_cast<char*>(mPartialBlockBuffer) + blockOffset,
|
||||
memcpy(reinterpret_cast<char*>(mPartialBlockBuffer.get()) + blockOffset,
|
||||
data, chunkSize);
|
||||
|
||||
if (blockOffset + chunkSize == BLOCK_SIZE) {
|
||||
// We completed a block, so lets write it out.
|
||||
blockDataToStore = reinterpret_cast<char*>(mPartialBlockBuffer);
|
||||
blockDataToStore = reinterpret_cast<char*>(mPartialBlockBuffer.get());
|
||||
if (mMetadataInPartialBlockBuffer) {
|
||||
mode = MODE_METADATA;
|
||||
}
|
||||
@ -1788,7 +1789,7 @@ MediaCacheStream::FlushPartialBlockInternal(bool aNotifyAll)
|
||||
aNotifyAll ? "yes" : "no"));
|
||||
|
||||
// Write back the partial block
|
||||
memset(reinterpret_cast<char*>(mPartialBlockBuffer) + blockOffset, 0,
|
||||
memset(reinterpret_cast<char*>(mPartialBlockBuffer.get()) + blockOffset, 0,
|
||||
BLOCK_SIZE - blockOffset);
|
||||
gMediaCache->AllocateAndWriteBlock(this, mPartialBlockBuffer,
|
||||
mMetadataInPartialBlockBuffer ? MODE_METADATA : MODE_PLAYBACK);
|
||||
@ -2182,7 +2183,7 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
||||
// the cache.
|
||||
bytes = std::min<int64_t>(size, streamWithPartialBlock->mChannelOffset - mStreamOffset);
|
||||
memcpy(aBuffer,
|
||||
reinterpret_cast<char*>(streamWithPartialBlock->mPartialBlockBuffer) + offsetInStreamBlock, bytes);
|
||||
reinterpret_cast<char*>(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
|
||||
if (mCurrentMode == MODE_METADATA) {
|
||||
streamWithPartialBlock->mMetadataInPartialBlockBuffer = true;
|
||||
}
|
||||
@ -2277,7 +2278,7 @@ MediaCacheStream::ReadFromCache(char* aBuffer,
|
||||
// the cache.
|
||||
bytes = std::min<int64_t>(size, mChannelOffset - streamOffset);
|
||||
memcpy(aBuffer + count,
|
||||
reinterpret_cast<char*>(mPartialBlockBuffer) + offsetInStreamBlock, bytes);
|
||||
reinterpret_cast<char*>(mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
|
||||
} else {
|
||||
if (cacheBlock < 0) {
|
||||
// We expect all blocks to be cached! Fail!
|
||||
|
@ -499,7 +499,9 @@ private:
|
||||
// mChannelOffset%BLOCK_SIZE bytes have been filled in with good data,
|
||||
// the rest are garbage.
|
||||
// Use int64_t so that the data is well-aligned.
|
||||
int64_t mPartialBlockBuffer[BLOCK_SIZE/sizeof(int64_t)];
|
||||
// Heap allocate this buffer since the exact power-of-2 will cause allocation
|
||||
// slop when combined with the rest of the object members.
|
||||
nsAutoArrayPtr<int64_t> mPartialBlockBuffer;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -86,7 +86,7 @@ class MediaRecorder::Session: public nsIObserver
|
||||
if (mSession->IsEncoderError()) {
|
||||
recorder->NotifyError(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
nsresult rv = recorder->CreateAndDispatchBlobEvent(mSession);
|
||||
nsresult rv = recorder->CreateAndDispatchBlobEvent(mSession->GetEncodedData());
|
||||
if (NS_FAILED(rv)) {
|
||||
recorder->NotifyError(rv);
|
||||
}
|
||||
@ -544,8 +544,8 @@ MediaRecorder::RequestData(ErrorResult& aResult)
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethodWithArg<Session *>(this,
|
||||
&MediaRecorder::CreateAndDispatchBlobEvent, mSession),
|
||||
NS_NewRunnableMethodWithArg<const already_AddRefed<nsIDOMBlob> >(this,
|
||||
&MediaRecorder::CreateAndDispatchBlobEvent, mSession->GetEncodedData()),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
@ -576,7 +576,7 @@ MediaRecorder::Constructor(const GlobalObject& aGlobal,
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaRecorder::CreateAndDispatchBlobEvent(Session *aSession)
|
||||
MediaRecorder::CreateAndDispatchBlobEvent(const already_AddRefed<nsIDOMBlob> &aBlob)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
|
||||
|
||||
@ -588,7 +588,7 @@ MediaRecorder::CreateAndDispatchBlobEvent(Session *aSession)
|
||||
BlobEventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
init.mData = aSession->GetEncodedData();
|
||||
init.mData = aBlob;
|
||||
nsRefPtr<BlobEvent> event =
|
||||
BlobEvent::Constructor(this,
|
||||
NS_LITERAL_STRING("dataavailable"),
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
protected:
|
||||
MediaRecorder& operator = (const MediaRecorder& x) MOZ_DELETE;
|
||||
// Create dataavailable event with Blob data and it runs in main thread
|
||||
nsresult CreateAndDispatchBlobEvent(Session *session);
|
||||
nsresult CreateAndDispatchBlobEvent(const already_AddRefed<nsIDOMBlob> &aBlob);
|
||||
// Creating a simple event to notify UA simple event.
|
||||
void DispatchSimpleEvent(const nsAString & aStr);
|
||||
// Creating a error event with message.
|
||||
|
@ -258,6 +258,7 @@ support-files =
|
||||
[test_mediarecorder_record_immediate_stop.html]
|
||||
[test_mediarecorder_record_session.html]
|
||||
[test_mediarecorder_record_startstopstart.html]
|
||||
[test_mediarecorder_getencodeddata.html]
|
||||
[test_mediarecorder_unsupported_src.html]
|
||||
[test_playback.html]
|
||||
[test_seekLies.html]
|
||||
|
68
content/media/test/test_mediarecorder_getencodeddata.html
Normal file
68
content/media/test/test_mediarecorder_getencodeddata.html
Normal file
@ -0,0 +1,68 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 957452 Test GetEncodedData problem on asan build</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.ogg.enabled", false]]},
|
||||
function () {
|
||||
var ac = new window.AudioContext();
|
||||
var dest = ac.createMediaStreamDestination();
|
||||
var stream = dest.stream;
|
||||
var onErrorFired = false;
|
||||
var expectedMimeType = '';
|
||||
var ondataavailableFired = false;
|
||||
setTimeout(function() {
|
||||
var mediaRecorder = new MediaRecorder(stream);
|
||||
mediaRecorder.onstop = function(e) {
|
||||
is(e.target.state, 'inactive',
|
||||
'Media recorder is inactive after being stopped');
|
||||
ok(onErrorFired, 'onStop after onError');
|
||||
ok(ondataavailableFired, 'ondataavailableFired');
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
mediaRecorder.ondataavailable = function(evt) {
|
||||
if (onErrorFired) {
|
||||
ondataavailableFired = true;
|
||||
ok(evt instanceof BlobEvent,
|
||||
'Events fired from ondataavailable should be BlobEvent');
|
||||
is(evt.type, 'dataavailable',
|
||||
'Event type should dataavailable');
|
||||
is(evt.data.size, 0,
|
||||
'Blob data size received is equal to zero');
|
||||
is(evt.data.type, expectedMimeType,
|
||||
'Blob data received should have type = ' + expectedMimeType);
|
||||
is(evt.target.mimeType, expectedMimeType,
|
||||
'Mime type in ondataavailable = ' + expectedMimeType);
|
||||
} else {
|
||||
ok(false, 'should get onError first');
|
||||
}
|
||||
}
|
||||
mediaRecorder.onerror = function(evt) {
|
||||
ok(evt instanceof RecordErrorEvent,
|
||||
'Events fired from onerror should be RecordErrorEvent');
|
||||
is(evt.type, 'error',
|
||||
'Event type should onerror');
|
||||
is(evt.name, 'GenericError',
|
||||
'Event name is GenericError');
|
||||
onErrorFired = true;
|
||||
}
|
||||
mediaRecorder.start(0);
|
||||
is(mediaRecorder.state, 'recording', 'Media recorder should be recording');
|
||||
is(mediaRecorder.stream, stream,
|
||||
'Media recorder stream = element stream at the start of recording');
|
||||
mediaRecorder.requestData();
|
||||
mediaRecorder.stop();
|
||||
}, 100);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -20,24 +20,15 @@ Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
const DB_NAME = "contacts";
|
||||
const DB_VERSION = 18;
|
||||
const STORE_NAME = "contacts";
|
||||
const SAVED_GETALL_STORE_NAME = "getallcache";
|
||||
/* all exported symbols need to be bound to this on B2G - Bug 961777 */
|
||||
this.DB_NAME = "contacts";
|
||||
this.DB_VERSION = 19;
|
||||
this.STORE_NAME = "contacts";
|
||||
this.SAVED_GETALL_STORE_NAME = "getallcache";
|
||||
const CHUNK_SIZE = 20;
|
||||
const REVISION_STORE = "revision";
|
||||
this.REVISION_STORE = "revision";
|
||||
const REVISION_KEY = "revision";
|
||||
|
||||
function optionalDate(aValue) {
|
||||
if (aValue) {
|
||||
if (!(aValue instanceof Date)) {
|
||||
return new Date(aValue);
|
||||
}
|
||||
return aValue;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function exportContact(aRecord) {
|
||||
if (aRecord) {
|
||||
delete aRecord.search;
|
||||
@ -182,7 +173,16 @@ ContactDB.prototype = {
|
||||
aDb.createObjectStore(REVISION_STORE).put(0, REVISION_KEY);
|
||||
}
|
||||
|
||||
if (DEBUG) debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
|
||||
let valueUpgradeSteps = [];
|
||||
|
||||
function scheduleValueUpgrade(upgradeFunc) {
|
||||
var length = valueUpgradeSteps.push(upgradeFunc);
|
||||
if (DEBUG) debug("Scheduled a value upgrade function, index " + (length - 1));
|
||||
}
|
||||
|
||||
// We always output this debug line because it's useful and the noise ratio
|
||||
// very low.
|
||||
debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
|
||||
let db = aDb;
|
||||
let objectStore;
|
||||
|
||||
@ -491,45 +491,34 @@ ContactDB.prototype = {
|
||||
function upgrade12to13() {
|
||||
if (DEBUG) debug("Add phone substring to the search index if appropriate for country");
|
||||
if (this.substringMatching) {
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
cursor.value.search.parsedTel = cursor.value.search.parsedTel || [];
|
||||
cursor.value.properties.tel.forEach(
|
||||
scheduleValueUpgrade(function upgradeValue12to13(value) {
|
||||
if (value.properties.tel) {
|
||||
value.search.parsedTel = value.search.parsedTel || [];
|
||||
value.properties.tel.forEach(
|
||||
function(tel) {
|
||||
let normalized = PhoneNumberUtils.normalize(tel.value.toString());
|
||||
if (normalized) {
|
||||
if (this.substringMatching && normalized.length > this.substringMatching) {
|
||||
let sub = normalized.slice(-this.substringMatching);
|
||||
if (cursor.value.search.parsedTel.indexOf(sub) === -1) {
|
||||
if (value.search.parsedTel.indexOf(sub) === -1) {
|
||||
if (DEBUG) debug("Adding substring index: " + tel + ", " + sub);
|
||||
cursor.value.search.parsedTel.push(sub);
|
||||
value.search.parsedTel.push(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
return true;
|
||||
} else {
|
||||
next();
|
||||
return false;
|
||||
}
|
||||
}.bind(this);
|
||||
} else {
|
||||
next();
|
||||
}.bind(this));
|
||||
}
|
||||
next();
|
||||
},
|
||||
function upgrade13to14() {
|
||||
if (DEBUG) debug("Cleaning up empty substring entries in telMatch index");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
scheduleValueUpgrade(function upgradeValue13to14(value) {
|
||||
function removeEmptyStrings(value) {
|
||||
if (value) {
|
||||
const oldLength = value.length;
|
||||
@ -542,92 +531,70 @@ ContactDB.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
let modified = removeEmptyStrings(cursor.value.search.parsedTel);
|
||||
let modified2 = removeEmptyStrings(cursor.value.search.tel);
|
||||
if (modified || modified2) {
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
let modified = removeEmptyStrings(value.search.parsedTel);
|
||||
let modified2 = removeEmptyStrings(value.search.tel);
|
||||
return (modified || modified2);
|
||||
});
|
||||
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
function upgrade14to15() {
|
||||
if (DEBUG) debug("Fix array properties saved as scalars");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
const ARRAY_PROPERTIES = ["photo", "adr", "email", "url", "impp", "tel",
|
||||
"name", "honorificPrefix", "givenName",
|
||||
"additionalName", "familyName", "honorificSuffix",
|
||||
"nickname", "category", "org", "jobTitle",
|
||||
"note", "key"];
|
||||
const PROPERTIES_WITH_TYPE = ["adr", "email", "url", "impp", "tel"];
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
|
||||
scheduleValueUpgrade(function upgradeValue14to15(value) {
|
||||
let changed = false;
|
||||
if (cursor) {
|
||||
let props = cursor.value.properties;
|
||||
|
||||
let props = value.properties;
|
||||
for (let prop of ARRAY_PROPERTIES) {
|
||||
if (props[prop]) {
|
||||
if (!Array.isArray(props[prop])) {
|
||||
cursor.value.properties[prop] = [props[prop]];
|
||||
value.properties[prop] = [props[prop]];
|
||||
changed = true;
|
||||
}
|
||||
if (PROPERTIES_WITH_TYPE.indexOf(prop) !== -1) {
|
||||
let subprop = cursor.value.properties[prop];
|
||||
let subprop = value.properties[prop];
|
||||
for (let i = 0; i < subprop.length; ++i) {
|
||||
if (!Array.isArray(subprop[i].type)) {
|
||||
cursor.value.properties[prop][i].type = [subprop[i].type];
|
||||
value.properties[prop][i].type = [subprop[i].type];
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
|
||||
return changed;
|
||||
});
|
||||
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
function upgrade15to16() {
|
||||
if (DEBUG) debug("Fix Date properties");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
const DATE_PROPERTIES = ["bday", "anniversary"];
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
|
||||
scheduleValueUpgrade(function upgradeValue15to16(value) {
|
||||
let changed = false;
|
||||
if (cursor) {
|
||||
let props = cursor.value.properties;
|
||||
let props = value.properties;
|
||||
for (let prop of DATE_PROPERTIES) {
|
||||
if (props[prop] && !(props[prop] instanceof Date)) {
|
||||
cursor.value.properties[prop] = new Date(props[prop]);
|
||||
value.properties[prop] = new Date(props[prop]);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
|
||||
return changed;
|
||||
});
|
||||
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
function upgrade16to17() {
|
||||
if (DEBUG) debug("Fix array with null values");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
const ARRAY_PROPERTIES = ["photo", "adr", "email", "url", "impp", "tel",
|
||||
"name", "honorificPrefix", "givenName",
|
||||
"additionalName", "familyName", "honorificSuffix",
|
||||
@ -638,7 +605,9 @@ ContactDB.prototype = {
|
||||
|
||||
const DATE_PROPERTIES = ["bday", "anniversary"];
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
scheduleValueUpgrade(function upgradeValue16to17(value) {
|
||||
let changed;
|
||||
|
||||
function filterInvalidValues(val) {
|
||||
let shouldKeep = val != null; // null or undefined
|
||||
if (!shouldKeep) {
|
||||
@ -651,10 +620,7 @@ ContactDB.prototype = {
|
||||
return array.filter(filterInvalidValues);
|
||||
}
|
||||
|
||||
let cursor = event.target.result;
|
||||
let changed = false;
|
||||
if (cursor) {
|
||||
let props = cursor.value.properties;
|
||||
let props = value.properties;
|
||||
|
||||
for (let prop of ARRAY_PROPERTIES) {
|
||||
|
||||
@ -693,16 +659,21 @@ ContactDB.prototype = {
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
cursor.value.properties = props;
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
value.properties = props;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
next();
|
||||
}
|
||||
}
|
||||
},
|
||||
function upgrade17to18() {
|
||||
// this upgrade function has been moved to the next upgrade path because
|
||||
// a previous version of it had a bug
|
||||
next();
|
||||
},
|
||||
function upgrade18to19() {
|
||||
if (DEBUG) {
|
||||
debug("Adding the name index");
|
||||
}
|
||||
@ -711,34 +682,93 @@ ContactDB.prototype = {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
// an earlier version of this code could have run, so checking whether
|
||||
// the index exists
|
||||
if (!objectStore.indexNames.contains("name")) {
|
||||
objectStore.createIndex("name", "properties.name", { multiEntry: true });
|
||||
objectStore.createIndex("nameLowerCase", "search.name", { multiEntry: true });
|
||||
}
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
let value = cursor.value;
|
||||
scheduleValueUpgrade(function upgradeValue18to19(value) {
|
||||
value.search.name = [];
|
||||
if (value.properties.name) {
|
||||
value.properties.name.forEach(function addNameIndex(name) {
|
||||
value.search.name.push(name.toLowerCase());
|
||||
var lowerName = name.toLowerCase();
|
||||
// an earlier version of this code could have added it already
|
||||
if (value.search.name.indexOf(lowerName) === -1) {
|
||||
value.search.name.push(lowerName);
|
||||
}
|
||||
});
|
||||
}
|
||||
cursor.update(value);
|
||||
} else {
|
||||
return true;
|
||||
});
|
||||
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
];
|
||||
|
||||
let index = aOldVersion;
|
||||
let outer = this;
|
||||
function next() {
|
||||
if (index == aNewVersion) {
|
||||
outer.incrementRevision(aTransaction);
|
||||
|
||||
/* This function runs all upgrade functions that are in the
|
||||
* valueUpgradeSteps array. These functions have the following properties:
|
||||
* - they must be synchronous
|
||||
* - they must take the value as parameter and modify it directly. They
|
||||
* must not create a new object.
|
||||
* - they must return a boolean true/false; true if the value was actually
|
||||
* changed
|
||||
*/
|
||||
function runValueUpgradeSteps(done) {
|
||||
if (DEBUG) debug("Running the value upgrade functions.");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
let changed = false;
|
||||
let oldValue;
|
||||
let value = cursor.value;
|
||||
if (DEBUG) {
|
||||
oldValue = JSON.stringify(value);
|
||||
}
|
||||
valueUpgradeSteps.forEach(function(upgradeFunc, i) {
|
||||
if (DEBUG) debug("Running upgrade function " + i);
|
||||
changed = upgradeFunc(value) || changed;
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
cursor.update(value);
|
||||
} else if (DEBUG) {
|
||||
let newValue = JSON.stringify(value);
|
||||
if (newValue !== oldValue) {
|
||||
// oops something went wrong
|
||||
debug("upgrade: `changed` was false and still the value changed! Aborting.");
|
||||
aTransaction.abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function finish() {
|
||||
// We always output this debug line because it's useful and the noise ratio
|
||||
// very low.
|
||||
debug("Upgrade finished");
|
||||
|
||||
outer.incrementRevision(aTransaction);
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (index == aNewVersion) {
|
||||
runValueUpgradeSteps(finish);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var i = index++;
|
||||
if (DEBUG) debug("Upgrade step: " + i + "\n");
|
||||
@ -748,7 +778,7 @@ ContactDB.prototype = {
|
||||
aTransaction.abort();
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fail(why) {
|
||||
why = why || "";
|
||||
@ -1164,7 +1194,7 @@ ContactDB.prototype = {
|
||||
for (let key in fields) {
|
||||
if (DEBUG) debug("key: " + fields[key]);
|
||||
if (!store.indexNames.contains(fields[key]) && fields[key] != "id") {
|
||||
if (DEBUG) debug("Key not valid!" + fields[key] + ", " + store.indexNames);
|
||||
if (DEBUG) debug("Key not valid!" + fields[key] + ", " + JSON.stringify(store.indexNames));
|
||||
txn.abort();
|
||||
return;
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageListenerManager");
|
||||
|
||||
let ContactService = {
|
||||
|
||||
/* all exported symbols need to be bound to this on B2G - Bug 961777 */
|
||||
let ContactService = this.ContactService = {
|
||||
init: function() {
|
||||
if (DEBUG) debug("Init");
|
||||
this._messages = ["Contacts:Find", "Contacts:GetAll", "Contacts:GetAll:SendNow",
|
||||
|
@ -10,3 +10,8 @@
|
||||
[test_contacts_international.html]
|
||||
[test_contacts_substringmatching.html]
|
||||
[test_contacts_substringmatchingVE.html]
|
||||
[test_migration.html]
|
||||
support-files =
|
||||
test_migration_chrome.js
|
||||
skip-if = os == "android"
|
||||
|
||||
|
@ -389,7 +389,7 @@ function checkCount(count, msg, then) {
|
||||
var index = 0;
|
||||
|
||||
function next() {
|
||||
ok(true, "Begin!");
|
||||
info("Step " + index);
|
||||
if (index >= steps.length) {
|
||||
ok(false, "Shouldn't get here!");
|
||||
return;
|
||||
|
@ -295,7 +295,8 @@ var steps = [
|
||||
},
|
||||
function () {
|
||||
ok(true, "all done!\n");
|
||||
SpecialPowers.setIntPref("dom.phonenumber.substringmatching.BR", -1);
|
||||
SpecialPowers.clearUserPref("dom.phonenumber.substringmatching.BR");
|
||||
SpecialPowers.clearUserPref("ril.lastKnownSimMcc");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
@ -124,7 +124,8 @@ var steps = [
|
||||
},
|
||||
function () {
|
||||
ok(true, "all done!\n");
|
||||
SpecialPowers.setIntPref("dom.phonenumber.substringmatching.VE", -1);
|
||||
SpecialPowers.clearUserPref("dom.phonenumber.substringmatching.BR");
|
||||
SpecialPowers.clearUserPref("ril.lastKnownSimMcc");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
210
dom/contacts/tests/test_migration.html
Normal file
210
dom/contacts/tests/test_migration.html
Normal file
@ -0,0 +1,210 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Migration tests</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>migration tests</h1>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8" src="shared.js"></script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
"use strict";
|
||||
|
||||
var backend, contactsCount, allContacts;
|
||||
function loadChromeScript() {
|
||||
var url = SimpleTest.getTestFileURL("test_migration_chrome.js");
|
||||
backend = SpecialPowers.loadChromeScript(url);
|
||||
}
|
||||
|
||||
function addBackendEvents() {
|
||||
backend.addMessageListener("createDB.success", function(count) {
|
||||
contactsCount = count;
|
||||
ok(true, "Created the database");
|
||||
next();
|
||||
});
|
||||
backend.addMessageListener("createDB.error", function(err) {
|
||||
ok(false, err);
|
||||
next();
|
||||
});
|
||||
|
||||
backend.addMessageListener("deleteDB.success", function() {
|
||||
ok(true, "Deleted the database");
|
||||
next();
|
||||
});
|
||||
backend.addMessageListener("deleteDB.error", function(err) {
|
||||
ok(false, err);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function createDB(version) {
|
||||
info("Will create the DB at version " + version);
|
||||
backend.sendAsyncMessage("createDB", version);
|
||||
}
|
||||
|
||||
function deleteDB() {
|
||||
info("Will delete the DB.");
|
||||
backend.sendAsyncMessage("deleteDB");
|
||||
}
|
||||
|
||||
function setSubstringMatching(value) {
|
||||
info("Setting substring matching to " + value);
|
||||
|
||||
if (value) {
|
||||
SpecialPowers.setIntPref("dom.phonenumber.substringmatching.BR", value);
|
||||
|
||||
// this is the Mcc for Brazil, so that we trigger the previous pref
|
||||
SpecialPowers.setCharPref("ril.lastKnownSimMcc", "724");
|
||||
} else {
|
||||
SpecialPowers.clearUserPref("dom.phonenumber.substringmatching.BR");
|
||||
SpecialPowers.clearUserPref("ril.lastKnownSimMcc");
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
var steps = [
|
||||
function setupChromeScript() {
|
||||
loadChromeScript();
|
||||
addBackendEvents();
|
||||
next();
|
||||
},
|
||||
|
||||
deleteDB, // let's be sure the DB does not exist yet
|
||||
createDB.bind(null, 12),
|
||||
setSubstringMatching.bind(null, 7),
|
||||
|
||||
function testAccessMozContacts() {
|
||||
info("Checking we have the right number of contacts: " + contactsCount);
|
||||
var req = mozContacts.getCount();
|
||||
req.onsuccess = function onsuccess() {
|
||||
ok(true, "Could access the mozContacts API");
|
||||
ise(this.result, contactsCount, "Contacts count is correct");
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Couldn't access the mozContacts API");
|
||||
next();
|
||||
};
|
||||
},
|
||||
|
||||
function testRetrieveAllContacts() {
|
||||
/* if the migration does not work right, either we'll have an error, or the
|
||||
contacts won't be migrated properly and thus will fail WebIDL conversion,
|
||||
which will manifest as a timeout */
|
||||
info("Checking the contacts are corrected to obey WebIDL constraints. (upgrades 14 to 17)");
|
||||
var req = mozContacts.find();
|
||||
req.onsuccess = function onsuccess() {
|
||||
if (this.result) {
|
||||
ise(this.result.length, contactsCount, "Contacts array length is correct");
|
||||
allContacts = this.result;
|
||||
next();
|
||||
} else {
|
||||
ok(false, "Could access the mozContacts API but got no contacts!");
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Couldn't access the mozContacts API");
|
||||
next();
|
||||
};
|
||||
},
|
||||
|
||||
function checkNameIndex() {
|
||||
info("Checking name index migration (upgrades 17 to 19).");
|
||||
if (!allContacts) {
|
||||
next();
|
||||
}
|
||||
|
||||
var count = allContacts.length;
|
||||
|
||||
function finishRequest() {
|
||||
count--;
|
||||
if (!count) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
allContacts.forEach(function(contact) {
|
||||
var name = contact.name && contact.name[0];
|
||||
if (!name) {
|
||||
count--;
|
||||
return;
|
||||
}
|
||||
|
||||
var req = mozContacts.find({
|
||||
filterBy: ["name"],
|
||||
filterValue: name,
|
||||
filterOp: "equals"
|
||||
});
|
||||
|
||||
req.onsuccess = function onsuccess() {
|
||||
if (this.result) {
|
||||
info("Found contact '" + name + "', checking it's the correct one.");
|
||||
checkContacts(this.result[0], contact);
|
||||
} else {
|
||||
ok(false, "Could not find contact with name '" + name + "'");
|
||||
}
|
||||
|
||||
finishRequest();
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Error while finding contact with name '" + name + "'!");
|
||||
finishRequest();
|
||||
}
|
||||
});
|
||||
|
||||
if (!count) {
|
||||
ok(false, "No contact had a name, this is unexpected.");
|
||||
next();
|
||||
}
|
||||
},
|
||||
|
||||
function checkSubstringMatching() {
|
||||
var subject = "0004567890"; // the last 7 digits are the same that at least one contact
|
||||
info("Looking for a contact matching " + subject);
|
||||
var req = mozContacts.find({
|
||||
filterValue: subject,
|
||||
filterOp: "match",
|
||||
filterBy: ["tel"],
|
||||
filterLimit: 1
|
||||
});
|
||||
|
||||
req.onsuccess = function onsuccess() {
|
||||
if (this.result && this.result[0]) {
|
||||
ok(true, "Found a contact with number " + this.result[0].tel[0].value);
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Error while finding contact for substring matching check!");
|
||||
next();
|
||||
};
|
||||
},
|
||||
|
||||
deleteDB,
|
||||
setSubstringMatching.bind(null, null),
|
||||
|
||||
function finish() {
|
||||
backend.destroy();
|
||||
info("all done!\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
||||
start_tests();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
331
dom/contacts/tests/test_migration_chrome.js
Normal file
331
dom/contacts/tests/test_migration_chrome.js
Normal file
@ -0,0 +1,331 @@
|
||||
/* global
|
||||
sendAsyncMessage,
|
||||
addMessageListener,
|
||||
indexedDB
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
let imports = {};
|
||||
|
||||
Cu.import("resource://gre/modules/ContactDB.jsm", imports);
|
||||
Cu.import("resource://gre/modules/ContactService.jsm", imports);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", imports);
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
const {
|
||||
STORE_NAME,
|
||||
SAVED_GETALL_STORE_NAME,
|
||||
REVISION_STORE,
|
||||
DB_NAME,
|
||||
ContactService,
|
||||
Promise
|
||||
} = imports;
|
||||
|
||||
let DEBUG = false;
|
||||
function debug(str) {
|
||||
if (DEBUG){
|
||||
dump("-*- TestMigrationChromeScript: " + str + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
const DATA = {
|
||||
12: {
|
||||
SCHEMA: function createSchema12(db, transaction) {
|
||||
let objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
|
||||
objectStore.createIndex("familyName", "properties.familyName", { multiEntry: true });
|
||||
objectStore.createIndex("givenName", "properties.givenName", { multiEntry: true });
|
||||
objectStore.createIndex("familyNameLowerCase", "search.familyName", { multiEntry: true });
|
||||
objectStore.createIndex("givenNameLowerCase", "search.givenName", { multiEntry: true });
|
||||
objectStore.createIndex("telLowerCase", "search.tel", { multiEntry: true });
|
||||
objectStore.createIndex("emailLowerCase", "search.email", { multiEntry: true });
|
||||
objectStore.createIndex("tel", "search.exactTel", { multiEntry: true });
|
||||
objectStore.createIndex("category", "properties.category", { multiEntry: true });
|
||||
objectStore.createIndex("email", "search.email", { multiEntry: true });
|
||||
objectStore.createIndex("telMatch", "search.parsedTel", {multiEntry: true});
|
||||
db.createObjectStore(SAVED_GETALL_STORE_NAME);
|
||||
db.createObjectStore(REVISION_STORE).put(0, "revision");
|
||||
},
|
||||
BAD: [
|
||||
{
|
||||
// this contact is bad because its "name" property is not an array and
|
||||
// is the empty string (upgrade 16 to 17)
|
||||
"properties": {
|
||||
"name": "",
|
||||
"email": [],
|
||||
"url": [{
|
||||
"type": ["source"],
|
||||
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
|
||||
}],
|
||||
"category": ["gmail"],
|
||||
"adr": [],
|
||||
"tel": [{
|
||||
"type": ["mobile"],
|
||||
"value": "+7 123 456-78-90"
|
||||
}],
|
||||
"sex": "undefined",
|
||||
"genderIdentity": "undefined"
|
||||
},
|
||||
"search": {
|
||||
"givenName": [],
|
||||
"familyName": [],
|
||||
"email": [],
|
||||
"category": ["gmail"],
|
||||
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
|
||||
"4567890","567890","67890","7890","890","90","0","81234567890"],
|
||||
"exactTel": ["+71234567890"],
|
||||
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
|
||||
},
|
||||
"updated": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"published": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"id": "bad-1"
|
||||
},
|
||||
{
|
||||
// This contact is bad because its "name" property is not an array
|
||||
// (upgrade 14 to 15)
|
||||
"properties": {
|
||||
"name": "name-bad-2",
|
||||
"email": [],
|
||||
"url": [{
|
||||
"type": ["source"],
|
||||
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
|
||||
}],
|
||||
"category": ["gmail"],
|
||||
"adr": [],
|
||||
"tel": [{
|
||||
"type": ["mobile"],
|
||||
"value": "+7 123 456-78-90"
|
||||
}],
|
||||
"sex": "undefined",
|
||||
"genderIdentity": "undefined"
|
||||
},
|
||||
"search": {
|
||||
"givenName": [],
|
||||
"familyName": [],
|
||||
"email": [],
|
||||
"category": ["gmail"],
|
||||
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
|
||||
"4567890","567890","67890","7890","890","90","0","81234567890"],
|
||||
"exactTel": ["+71234567890"],
|
||||
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
|
||||
},
|
||||
"updated": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"published": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"id": "bad-2"
|
||||
},
|
||||
{
|
||||
// This contact is bad because its bday property is a String (upgrade 15
|
||||
// to 16), and its anniversary property is an empty string (upgrade 16
|
||||
// to 17)
|
||||
"properties": {
|
||||
"name": ["name-bad-3"],
|
||||
"email": [],
|
||||
"url": [{
|
||||
"type": ["source"],
|
||||
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
|
||||
}],
|
||||
"category": ["gmail"],
|
||||
"adr": [],
|
||||
"tel": [{
|
||||
"type": ["mobile"],
|
||||
"value": "+7 123 456-78-90"
|
||||
}],
|
||||
"sex": "undefined",
|
||||
"genderIdentity": "undefined",
|
||||
"bday": "2013-07-27T16:47:40.974Z",
|
||||
"anniversary": ""
|
||||
},
|
||||
"search": {
|
||||
"givenName": [],
|
||||
"familyName": [],
|
||||
"email": [],
|
||||
"category": ["gmail"],
|
||||
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
|
||||
"4567890","567890","67890","7890","890","90","0","81234567890"],
|
||||
"exactTel": ["+71234567890"],
|
||||
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
|
||||
},
|
||||
"updated": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"published": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"id": "bad-3"
|
||||
},
|
||||
{
|
||||
// This contact is bad because its tel property has a tel.type null
|
||||
// value (upgrade 16 to 17), and email.type not array value (upgrade 14
|
||||
// to 15)
|
||||
"properties": {
|
||||
"name": ["name-bad-4"],
|
||||
"email": [{
|
||||
"value": "toto@toto.com",
|
||||
"type": "home"
|
||||
}],
|
||||
"url": [{
|
||||
"type": ["source"],
|
||||
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
|
||||
}],
|
||||
"category": ["gmail"],
|
||||
"adr": [],
|
||||
"tel": [{
|
||||
"type": null,
|
||||
"value": "+7 123 456-78-90"
|
||||
}],
|
||||
"sex": "undefined",
|
||||
"genderIdentity": "undefined"
|
||||
},
|
||||
"search": {
|
||||
"givenName": [],
|
||||
"familyName": [],
|
||||
"email": [],
|
||||
"category": ["gmail"],
|
||||
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
|
||||
"4567890","567890","67890","7890","890","90","0","81234567890"],
|
||||
"exactTel": ["+71234567890"],
|
||||
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
|
||||
},
|
||||
"updated": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"published": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"id": "bad-4"
|
||||
}
|
||||
],
|
||||
GOOD: [
|
||||
{
|
||||
"properties": {
|
||||
"name": ["name-good-1"],
|
||||
"email": [],
|
||||
"url": [{
|
||||
"type": ["source"],
|
||||
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
|
||||
}],
|
||||
"category": ["gmail"],
|
||||
"adr": [],
|
||||
"tel": [{
|
||||
"type": ["mobile"],
|
||||
"value": "+7 123 456-78-90"
|
||||
}],
|
||||
"sex": "undefined",
|
||||
"genderIdentity": "undefined"
|
||||
},
|
||||
"search": {
|
||||
"givenName": [],
|
||||
"familyName": [],
|
||||
"email": [],
|
||||
"category": ["gmail"],
|
||||
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
|
||||
"4567890","567890","67890","7890","890","90","0","81234567890"],
|
||||
"exactTel": ["+71234567890"],
|
||||
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
|
||||
},
|
||||
"updated": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"published": new Date("2013-07-27T16:47:40.974Z"),
|
||||
"id": "good-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
function DataManager(version) {
|
||||
if (!(version in DATA)) {
|
||||
throw new Error("Version " + version + " can't be found in our test datas.");
|
||||
}
|
||||
|
||||
this.version = version;
|
||||
this.data = DATA[version];
|
||||
}
|
||||
|
||||
DataManager.prototype = {
|
||||
open: function() {
|
||||
debug("opening for version " + this.version);
|
||||
var deferred = Promise.defer();
|
||||
|
||||
let req = indexedDB.open(DB_NAME, this.version);
|
||||
req.onupgradeneeded = function() {
|
||||
let db = req.result;
|
||||
let transaction = req.transaction;
|
||||
this.createSchema(db, transaction);
|
||||
this.addContacts(db, transaction);
|
||||
}.bind(this);
|
||||
|
||||
req.onsuccess = function() {
|
||||
debug("succeeded opening the db, let's close it now");
|
||||
req.result.close();
|
||||
deferred.resolve(this.contactsCount());
|
||||
}.bind(this);
|
||||
|
||||
req.onerror = function() {
|
||||
deferred.reject(this.error);
|
||||
};
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
createSchema: function(db, transaction) {
|
||||
debug("createSchema for version " + this.version);
|
||||
this.data.SCHEMA(db, transaction);
|
||||
},
|
||||
|
||||
addContacts: function(db, transaction) {
|
||||
debug("adding contacts for version " + this.version);
|
||||
var os = transaction.objectStore(STORE_NAME);
|
||||
|
||||
this.data.GOOD.forEach(function(contact) {
|
||||
os.put(contact);
|
||||
});
|
||||
this.data.BAD.forEach(function(contact) {
|
||||
os.put(contact);
|
||||
});
|
||||
},
|
||||
|
||||
contactsCount: function() {
|
||||
return this.data.BAD.length + this.data.GOOD.length;
|
||||
}
|
||||
};
|
||||
|
||||
DataManager.delete = function() {
|
||||
debug("Deleting the database");
|
||||
var deferred = Promise.defer();
|
||||
|
||||
/* forcibly close the db before deleting it */
|
||||
ContactService._db.close();
|
||||
|
||||
var req = indexedDB.deleteDatabase(DB_NAME);
|
||||
req.onsuccess = function() {
|
||||
debug("Successfully deleted!");
|
||||
deferred.resolve();
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
debug("Not deleted, error is " + this.error.name);
|
||||
deferred.reject(this.error);
|
||||
};
|
||||
|
||||
req.onblocked = function() {
|
||||
debug("Waiting for the current users");
|
||||
};
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
addMessageListener("createDB", function(version) {
|
||||
// Promises help handling gracefully exceptions
|
||||
Promise.resolve().then(function() {
|
||||
return new DataManager(version);
|
||||
}).then(function(manager) {
|
||||
return manager.open();
|
||||
}).then(function onSuccess(count) {
|
||||
sendAsyncMessage("createDB.success", count);
|
||||
}, function onError(err) {
|
||||
sendAsyncMessage("createDB.error", "Failed to create the DB: " +
|
||||
"(" + err.name + ") " + err.message);
|
||||
});
|
||||
});
|
||||
|
||||
addMessageListener("deleteDB", function() {
|
||||
Promise.resolve().then(
|
||||
DataManager.delete
|
||||
).then(function onSuccess() {
|
||||
sendAsyncMessage("deleteDB.success");
|
||||
}, function onError(err) {
|
||||
sendAsyncMessage("deleteDB.error", "Failed to delete the DB:" + err.name);
|
||||
});
|
||||
});
|
@ -5,6 +5,10 @@
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const PREF_FXA_ENABLED = "identity.fxaccounts.enabled";
|
||||
let _fxa_enabled = false;
|
||||
try {
|
||||
@ -18,9 +22,6 @@ const FXA_ENABLED = _fxa_enabled;
|
||||
// This is the parent process corresponding to nsDOMIdentity.
|
||||
this.EXPORTED_SYMBOLS = ["DOMIdentity"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
|
||||
"resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
|
||||
|
@ -231,6 +231,15 @@ static void split(char* str, const char* sep, nsTArray<nsCString>& result)
|
||||
}
|
||||
}
|
||||
|
||||
static void split(char* str, const char* sep, nsTArray<nsString>& result)
|
||||
{
|
||||
char *s = strtok(str, sep);
|
||||
while (s != nullptr) {
|
||||
result.AppendElement(NS_ConvertUTF8toUTF16(s));
|
||||
s = strtok(nullptr, sep);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that implement join function.
|
||||
*/
|
||||
|
@ -75,12 +75,12 @@ public:
|
||||
|
||||
NetworkParams(const NetworkCommandOptions& aOther) {
|
||||
|
||||
#define COPY_SEQUENCE_FIELD(prop) \
|
||||
#define COPY_SEQUENCE_FIELD(prop, type) \
|
||||
if (aOther.prop.WasPassed()) { \
|
||||
mozilla::dom::Sequence<nsString > const & currentValue = aOther.prop.InternalValue(); \
|
||||
mozilla::dom::Sequence<type > const & currentValue = aOther.prop.InternalValue(); \
|
||||
uint32_t length = currentValue.Length(); \
|
||||
for (uint32_t idx = 0; idx < length; idx++) { \
|
||||
mHostnames.AppendElement(currentValue[idx]); \
|
||||
prop.AppendElement(currentValue[idx]); \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ public:
|
||||
COPY_OPT_STRING_FIELD(mDns2_str, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mGateway, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mGateway_str, EmptyString())
|
||||
COPY_SEQUENCE_FIELD(mHostnames)
|
||||
COPY_SEQUENCE_FIELD(mHostnames, nsString)
|
||||
COPY_OPT_STRING_FIELD(mIfname, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mIp, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mNetmask, EmptyString())
|
||||
@ -128,7 +128,7 @@ public:
|
||||
COPY_OPT_STRING_FIELD(mKey, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mPrefix, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mLink, EmptyString())
|
||||
COPY_SEQUENCE_FIELD(mInterfaceList)
|
||||
COPY_SEQUENCE_FIELD(mInterfaceList, nsString)
|
||||
COPY_OPT_STRING_FIELD(mWifiStartIp, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mWifiEndIp, EmptyString())
|
||||
COPY_OPT_STRING_FIELD(mUsbStartIp, EmptyString())
|
||||
@ -178,7 +178,7 @@ public:
|
||||
nsString mKey;
|
||||
nsString mPrefix;
|
||||
nsString mLink;
|
||||
nsTArray<nsCString> mInterfaceList;
|
||||
nsTArray<nsString> mInterfaceList;
|
||||
nsString mWifiStartIp;
|
||||
nsString mWifiEndIp;
|
||||
nsString mUsbStartIp;
|
||||
|
@ -926,13 +926,13 @@ XPCOMUtils.defineLazyGetter(this, "gDataConnectionManager", function () {
|
||||
if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN) {
|
||||
let connHandler = this._connectionHandlers[this._currentDataClientId];
|
||||
let radioInterface = connHandler.radioInterface;
|
||||
if (!connHandler.allDataDisconnected() &&
|
||||
if (connHandler.allDataDisconnected() &&
|
||||
typeof this._pendingDataCallRequest === "function") {
|
||||
if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
|
||||
radioInterface.setDataRegistration(false);
|
||||
}
|
||||
if (DEBUG) {
|
||||
debug("All data calls disconnected, setup pending data call.");
|
||||
this.debug("All data calls disconnected, setup pending data call.");
|
||||
}
|
||||
this._pendingDataCallRequest();
|
||||
this._pendingDataCallRequest = null;
|
||||
|
Loading…
Reference in New Issue
Block a user