зеркало из https://github.com/mozilla/gecko-dev.git
Make history database store the endianness of the page titles as metadata so
when a single profile is shared among machines of different endianness the database doesn't get all garbled. Bug 108134, patch by rbasch@mit.edu (Robert Basch), r=alecf, sr=bzbarsky
This commit is contained in:
Родитель
4dc7c4bdb5
Коммит
17603e534e
|
@ -787,6 +787,7 @@ nsGlobalHistory::SetRowValue(nsIMdbRow *aRow, mdb_column aCol,
|
|||
mdb_err err;
|
||||
|
||||
PRInt32 len = (nsCRT::strlen(aValue) * sizeof(PRUnichar));
|
||||
PRUnichar *swapval = nsnull;
|
||||
|
||||
// eventually turn this on when we're confident in mork's abilitiy
|
||||
// to handle yarn forms properly
|
||||
|
@ -796,10 +797,20 @@ nsGlobalHistory::SetRowValue(nsIMdbRow *aRow, mdb_column aCol,
|
|||
mdbYarn yarn = { (void *)utf8Value.get(), utf8Value.Length(), utf8Value.Length(), 0, 1, nsnull };
|
||||
#else
|
||||
|
||||
if (mReverseByteOrder) {
|
||||
// The file is other-endian. Byte-swap the value.
|
||||
swapval = (PRUnichar *)malloc(len);
|
||||
if (!swapval)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
SwapBytes(aValue, swapval, len / sizeof(PRUnichar));
|
||||
aValue = swapval;
|
||||
}
|
||||
mdbYarn yarn = { (void *)aValue, len, len, 0, 0, nsnull };
|
||||
|
||||
#endif
|
||||
err = aRow->AddColumn(mEnv, aCol, &yarn);
|
||||
if (swapval)
|
||||
free(swapval);
|
||||
if (err != 0) return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -848,7 +859,19 @@ nsGlobalHistory::GetRowValue(nsIMdbRow *aRow, mdb_column aCol,
|
|||
|
||||
switch (yarn.mYarn_Form) {
|
||||
case 0: // unicode
|
||||
aResult.Assign((const PRUnichar *)yarn.mYarn_Buf, yarn.mYarn_Fill/sizeof(PRUnichar));
|
||||
if (mReverseByteOrder) {
|
||||
// The file is other-endian; we must byte-swap the result.
|
||||
PRUnichar *swapval;
|
||||
int len = yarn.mYarn_Fill / sizeof(PRUnichar);
|
||||
swapval = (PRUnichar *)malloc(yarn.mYarn_Fill);
|
||||
if (!swapval)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
SwapBytes((const PRUnichar *)yarn.mYarn_Buf, swapval, len);
|
||||
aResult.Assign(swapval, len);
|
||||
free(swapval);
|
||||
}
|
||||
else
|
||||
aResult.Assign((const PRUnichar *)yarn.mYarn_Buf, yarn.mYarn_Fill/sizeof(PRUnichar));
|
||||
break;
|
||||
|
||||
// eventually we'll be supporting this in SetRowValue()
|
||||
|
@ -862,6 +885,43 @@ nsGlobalHistory::GetRowValue(nsIMdbRow *aRow, mdb_column aCol,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Copy an array of 16-bit values, reversing the byte order.
|
||||
void
|
||||
nsGlobalHistory::SwapBytes(const PRUint16 *source, PRUint16 *dest, int len)
|
||||
{
|
||||
PRUint16 c;
|
||||
const PRUint16 *inp;
|
||||
PRUint16 *outp;
|
||||
int i;
|
||||
|
||||
inp = source;
|
||||
outp = dest;
|
||||
for (i = 0; i < len; i++) {
|
||||
c = *inp++;
|
||||
*outp++ = (((c >> 8) & 0xff) | (c << 8));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy an array of 32-bit values, reversing the byte order.
|
||||
void
|
||||
nsGlobalHistory::SwapBytes(const PRUint32 *source, PRUint32 *dest, int len)
|
||||
{
|
||||
PRUint32 c;
|
||||
const PRUint32 *inp;
|
||||
PRUint32 *outp;
|
||||
int i;
|
||||
|
||||
inp = source;
|
||||
outp = dest;
|
||||
for (i = 0; i < len; i++) {
|
||||
c = *inp++;
|
||||
*outp++ = (((c >> 24) & 0xff) | ((c >> 8) & 0xff00) |
|
||||
((c << 8) & 0xff0000) | (c << 24));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalHistory::GetRowValue(nsIMdbRow *aRow, mdb_column aCol,
|
||||
PRInt64 *aResult)
|
||||
|
@ -1078,6 +1138,10 @@ nsGlobalHistory::RemoveAllPages()
|
|||
rv = RemoveMatchingRows(matchAllCallback, nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Reset the file byte order.
|
||||
rv = InitByteOrder(PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return Commit(kCompressCommit);
|
||||
}
|
||||
|
||||
|
@ -1209,6 +1273,42 @@ nsGlobalHistory::GetLastPageVisited(char **_retval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Set the byte order in the history file. The given string value should
|
||||
// be either "BE" (big-endian) or "LE" (little-endian).
|
||||
nsresult
|
||||
nsGlobalHistory::SaveByteOrder(const char *aByteOrder)
|
||||
{
|
||||
if (PL_strcmp(aByteOrder, "BE") != 0 && PL_strcmp(aByteOrder, "LE") != 0) {
|
||||
NS_WARNING("Invalid byte order argument.");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
NS_ENSURE_STATE(mMetaRow);
|
||||
|
||||
mdb_err err = SetRowValue(mMetaRow, kToken_ByteOrder, aByteOrder);
|
||||
NS_ENSURE_TRUE(err == 0, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the file byte order.
|
||||
nsresult
|
||||
nsGlobalHistory::GetByteOrder(char **_retval)
|
||||
{
|
||||
NS_ENSURE_SUCCESS(OpenDB(), NS_ERROR_FAILURE);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
NS_ENSURE_STATE(mMetaRow);
|
||||
|
||||
nsCAutoString byteOrder;
|
||||
mdb_err err = GetRowValue(mMetaRow, kToken_ByteOrder, byteOrder);
|
||||
NS_ENSURE_TRUE(err == 0, NS_ERROR_FAILURE);
|
||||
|
||||
*_retval = ToNewCString(byteOrder);
|
||||
NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::HidePage(const char *aURL)
|
||||
{
|
||||
|
@ -2410,6 +2510,9 @@ nsGlobalHistory::OpenDB()
|
|||
LL_I2L(mFileSizeOnDisk, 0);
|
||||
}
|
||||
|
||||
// See if we need to byte-swap.
|
||||
InitByteOrder(PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2509,6 +2612,12 @@ nsGlobalHistory::OpenNewFile(nsIMdbFactory *factory, const char *filePath)
|
|||
if (err != 0) return NS_ERROR_FAILURE;
|
||||
if (!mTable) return NS_ERROR_FAILURE;
|
||||
|
||||
// Create the meta row.
|
||||
mdbOid oid = { kToken_HistoryRowScope, 1 };
|
||||
err = mTable->GetMetaRow(mEnv, &oid, nsnull, getter_AddRefs(mMetaRow));
|
||||
if (err != 0)
|
||||
NS_WARNING("Could not get meta row\n");
|
||||
|
||||
// Force a commit now to get it written out.
|
||||
nsCOMPtr<nsIMdbThumb> thumb;
|
||||
err = mStore->LargeCommit(mEnv, getter_AddRefs(thumb));
|
||||
|
@ -2528,6 +2637,39 @@ nsGlobalHistory::OpenNewFile(nsIMdbFactory *factory, const char *filePath)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Set the history file byte order if necessary, and determine if
|
||||
// we need to byte-swap Unicode values.
|
||||
// If the force argument is true, the file byte order will be set
|
||||
// to that of this machine.
|
||||
nsresult
|
||||
nsGlobalHistory::InitByteOrder(PRBool aForce)
|
||||
{
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
NS_NAMED_LITERAL_CSTRING(machine_byte_order, "LE");
|
||||
#endif
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
NS_NAMED_LITERAL_CSTRING(machine_byte_order, "BE");
|
||||
#endif
|
||||
nsXPIDLCString file_byte_order;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!aForce)
|
||||
rv = GetByteOrder(getter_Copies(file_byte_order));
|
||||
if (aForce || NS_FAILED(rv) ||
|
||||
!(file_byte_order.Equals(NS_LITERAL_CSTRING("BE")) ||
|
||||
file_byte_order.Equals(NS_LITERAL_CSTRING("LE")))) {
|
||||
// Byte order is not yet set, or needs to be reset; initialize it.
|
||||
mReverseByteOrder = PR_FALSE;
|
||||
rv = SaveByteOrder(machine_byte_order.get());
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
mReverseByteOrder = !file_byte_order.Equals(machine_byte_order);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// break the uri down into a search query, and pass off to
|
||||
// SearchEnumerator
|
||||
nsresult
|
||||
|
@ -2681,6 +2823,7 @@ nsGlobalHistory::CreateTokens()
|
|||
|
||||
// meta-data tokens
|
||||
err = mStore->StringToToken(mEnv, "LastPageVisited", &kToken_LastPageVisited);
|
||||
err = mStore->StringToToken(mEnv, "ByteOrder", &kToken_ByteOrder);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -295,6 +295,7 @@ protected:
|
|||
|
||||
// meta-data tokens
|
||||
mdb_column kToken_LastPageVisited;
|
||||
mdb_column kToken_ByteOrder;
|
||||
|
||||
//
|
||||
// AddPage-oriented stuff
|
||||
|
@ -323,6 +324,16 @@ protected:
|
|||
|
||||
nsresult FindRow(mdb_column aCol, const char *aURL, nsIMdbRow **aResult);
|
||||
|
||||
//
|
||||
// byte order
|
||||
//
|
||||
nsresult SaveByteOrder(const char *aByteOrder);
|
||||
nsresult GetByteOrder(char **_retval);
|
||||
nsresult InitByteOrder(PRBool aForce);
|
||||
void SwapBytes(const PRUint16 *source, PRUint16 *dest, int len);
|
||||
void SwapBytes(const PRUint32 *source, PRUint32 *dest, int len);
|
||||
PRBool mReverseByteOrder;
|
||||
|
||||
//
|
||||
// misc unrelated stuff
|
||||
//
|
||||
|
|
Загрузка…
Ссылка в новой задаче