Bug 1193387 - Import reading list from MS Edge. r=jaws

This commit is contained in:
Gijs Kruitbosch 2015-08-26 15:34:02 +01:00
Родитель cf626448a7
Коммит 9b55c67e43
13 изменённых файлов: 917 добавлений и 548 удалений

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

@ -24,11 +24,15 @@ LOCAL_INCLUDES += [
if CONFIG['OS_ARCH'] == 'WINNT': if CONFIG['OS_ARCH'] == 'WINNT':
OS_LIBS += [ OS_LIBS += [
'esent',
'ole32', 'ole32',
'shell32', 'shell32',
'shlwapi', 'shlwapi',
'version', 'version',
] ]
DELAYLOAD_DLLS += [
'esent.dll',
]
# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code) # Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
# GTK2: Need to link with glib for GNOME shell service # GTK2: Need to link with glib for GNOME shell service

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

@ -10,6 +10,12 @@
#define NS_IEHISTORYENUMERATOR_CONTRACTID \ #define NS_IEHISTORYENUMERATOR_CONTRACTID \
"@mozilla.org/profile/migrator/iehistoryenumerator;1" "@mozilla.org/profile/migrator/iehistoryenumerator;1"
#define NS_EDGEREADINGLISTEXTRACTOR_CID \
{ 0xeeff77b1, 0xdb98, 0x4241, { 0x94, 0x36, 0x14, 0xf7, 0xa2, 0x28, 0x84, 0xc1 } }
#define NS_EDGEREADINGLISTEXTRACTOR_CONTRACTID \
"@mozilla.org/profile/migrator/edgereadinglistextractor;1"
#endif #endif
#define NS_SHELLSERVICE_CID \ #define NS_SHELLSERVICE_CID \

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

@ -18,6 +18,7 @@
#if defined(XP_WIN) #if defined(XP_WIN)
#include "nsIEHistoryEnumerator.h" #include "nsIEHistoryEnumerator.h"
#include "nsEdgeReadingListExtractor.h"
#endif #endif
#include "rdf.h" #include "rdf.h"
@ -42,6 +43,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
#if defined(XP_WIN) #if defined(XP_WIN)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator) NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsEdgeReadingListExtractor)
#endif #endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
@ -56,6 +58,7 @@ NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID);
NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID); NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID);
#if defined(XP_WIN) #if defined(XP_WIN)
NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID); NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID);
NS_DEFINE_NAMED_CID(NS_EDGEREADINGLISTEXTRACTOR_CID);
#elif defined(XP_MACOSX) #elif defined(XP_MACOSX)
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID); NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
#endif #endif
@ -71,6 +74,7 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
{ &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, nullptr, AboutRedirector::Create }, { &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, nullptr, AboutRedirector::Create },
#if defined(XP_WIN) #if defined(XP_WIN)
{ &kNS_WINIEHISTORYENUMERATOR_CID, false, nullptr, nsIEHistoryEnumeratorConstructor }, { &kNS_WINIEHISTORYENUMERATOR_CID, false, nullptr, nsIEHistoryEnumeratorConstructor },
{ &kNS_EDGEREADINGLISTEXTRACTOR_CID, false, nullptr, nsEdgeReadingListExtractorConstructor },
#elif defined(XP_MACOSX) #elif defined(XP_MACOSX)
{ &kNS_SHELLSERVICE_CID, false, nullptr, nsMacShellServiceConstructor }, { &kNS_SHELLSERVICE_CID, false, nullptr, nsMacShellServiceConstructor },
#endif #endif
@ -119,6 +123,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "pocket-signup", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "pocket-signup", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#if defined(XP_WIN) #if defined(XP_WIN)
{ NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID }, { NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
{ NS_EDGEREADINGLISTEXTRACTOR_CONTRACTID, &kNS_EDGEREADINGLISTEXTRACTOR_CID },
#elif defined(XP_MACOSX) #elif defined(XP_MACOSX)
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID }, { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
#endif #endif

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

@ -1,30 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource:///modules/MigrationUtils.jsm"); Cu.import("resource:///modules/MigrationUtils.jsm");
Cu.import("resource:///modules/MSMigrationUtils.jsm"); Cu.import("resource:///modules/MSMigrationUtils.jsm");
function EdgeProfileMigrator() { function EdgeProfileMigrator() {
} }
EdgeProfileMigrator.prototype = Object.create(MigratorPrototype); EdgeProfileMigrator.prototype = Object.create(MigratorPrototype);
EdgeProfileMigrator.prototype.getResources = function() { EdgeProfileMigrator.prototype.getResources = function() {
let resources = [ let resources = [
MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE), MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE), MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
]; ];
return resources.filter(r => r.exists); return resources.filter(r => r.exists);
}; };
EdgeProfileMigrator.prototype.classDescription = "Edge Profile Migrator"; EdgeProfileMigrator.prototype.classDescription = "Edge Profile Migrator";
EdgeProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=edge"; EdgeProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=edge";
EdgeProfileMigrator.prototype.classID = Components.ID("{62e8834b-2d17-49f5-96ff-56344903a2ae}"); EdgeProfileMigrator.prototype.classID = Components.ID("{62e8834b-2d17-49f5-96ff-56344903a2ae}");
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EdgeProfileMigrator]); this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EdgeProfileMigrator]);

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

@ -84,7 +84,8 @@ History.prototype = {
let transitionType = this._typedURLs[uri.spec] ? let transitionType = this._typedURLs[uri.spec] ?
Ci.nsINavHistoryService.TRANSITION_TYPED : Ci.nsINavHistoryService.TRANSITION_TYPED :
Ci.nsINavHistoryService.TRANSITION_LINK; Ci.nsINavHistoryService.TRANSITION_LINK;
let lastVisitTime = entry.get("time"); // use the current date if we have no visits for this entry
let lastVisitTime = entry.get("time") || Date.now();
places.push( places.push(
{ uri: uri, { uri: uri,

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -10,12 +10,14 @@ JAR_MANIFESTS += ['jar.mn']
XPIDL_SOURCES += [ XPIDL_SOURCES += [
'nsIBrowserProfileMigrator.idl', 'nsIBrowserProfileMigrator.idl',
'nsIEdgeReadingListExtractor.idl',
] ]
XPIDL_MODULE = 'migration' XPIDL_MODULE = 'migration'
if CONFIG['OS_ARCH'] == 'WINNT': if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [ SOURCES += [
'nsEdgeReadingListExtractor.cpp',
'nsIEHistoryEnumerator.cpp', 'nsIEHistoryEnumerator.cpp',
] ]

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

@ -0,0 +1,203 @@
/* 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 "nsEdgeReadingListExtractor.h"
#include <windows.h>
#include "nsCOMPtr.h"
#include "nsIConsoleService.h"
#include "nsIMutableArray.h"
#include "nsIWritablePropertyBag2.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsWindowsMigrationUtils.h"
#define NS_HANDLE_JET_ERROR(err) { \
if (err < JET_errSuccess) { \
rv = ConvertJETError(err); \
goto CloseDB; \
} \
}
#define MAX_URL_LENGTH 4168
#define MAX_TITLE_LENGTH 1024
NS_IMPL_ISUPPORTS(nsEdgeReadingListExtractor, nsIEdgeReadingListExtractor)
NS_IMETHODIMP
nsEdgeReadingListExtractor::Extract(const nsAString& aDBPath, nsIArray** aItems)
{
nsresult rv = NS_OK;
*aItems = nullptr;
JET_ERR err;
JET_INSTANCE instance;
JET_SESID sesid;
JET_DBID dbid;
JET_TABLEID tableid;
JET_COLUMNDEF urlColumnInfo = { 0 };
JET_COLUMNDEF titleColumnInfo = { 0 };
JET_COLUMNDEF addedDateColumnInfo = { 0 };
// Need to ensure this happens before we skip ahead to CloseDB,
// otherwise the compiler complains.
nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
// JET does not throw exceptions, and so error handling and ensuring we close
// the DB is a bit finnicky. Keep track of how far we got so we guarantee closing
// the right things
bool instanceCreated, sessionCreated, dbOpened, tableOpened;
char16_t* dbPath = ToNewUnicode(aDBPath);
// Check for the right page size and initialize with that
unsigned long pageSize;
err = JetGetDatabaseFileInfoW(dbPath, &pageSize, sizeof(pageSize), JET_DbInfoPageSize);
NS_HANDLE_JET_ERROR(err)
err = JetSetSystemParameter(&instance, NULL, JET_paramDatabasePageSize, pageSize, NULL);
NS_HANDLE_JET_ERROR(err)
// Turn off recovery, because otherwise we will create log files in either the cwd or
// overwrite Edge's own logfiles, which is useless at best and at worst might mess with
// Edge actually using the DB
err = JetSetSystemParameter(&instance, NULL, JET_paramRecovery, NULL, "Off");
NS_HANDLE_JET_ERROR(err)
// Start our session:
err = JetCreateInstance(&instance, "edge_readinglist_migration");
NS_HANDLE_JET_ERROR(err)
instanceCreated = true;
err = JetInit(&instance);
NS_HANDLE_JET_ERROR(err)
err = JetBeginSession(instance, &sesid, 0, 0);
NS_HANDLE_JET_ERROR(err)
sessionCreated = true;
// Actually open the DB, and make sure to do so readonly:
err = JetAttachDatabaseW(sesid, dbPath, JET_bitDbReadOnly);
NS_HANDLE_JET_ERROR(err)
dbOpened = true;
err = JetOpenDatabaseW(sesid, dbPath, NULL, &dbid, JET_bitDbReadOnly);
NS_HANDLE_JET_ERROR(err)
// Open the readinglist table and get information on the columns we are interested in:
err = JetOpenTable(sesid, dbid, "ReadingList", NULL, 0, JET_bitTableReadOnly, &tableid);
NS_HANDLE_JET_ERROR(err)
tableOpened = true;
err = JetGetColumnInfo(sesid, dbid, "ReadingList", "URL", &urlColumnInfo,
sizeof(urlColumnInfo), JET_ColInfo);
NS_HANDLE_JET_ERROR(err)
if (urlColumnInfo.cbMax > MAX_URL_LENGTH) {
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService) {
consoleService->LogStringMessage(NS_LITERAL_STRING("Edge migration: URL column size increased").get());
}
}
err = JetGetColumnInfo(sesid, dbid, "ReadingList", "Title", &titleColumnInfo,
sizeof(titleColumnInfo), JET_ColInfo);
NS_HANDLE_JET_ERROR(err)
if (titleColumnInfo.cbMax > MAX_TITLE_LENGTH) {
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService) {
consoleService->LogStringMessage(NS_LITERAL_STRING("Edge migration: Title column size increased").get());
}
}
err = JetGetColumnInfo(sesid, dbid, "ReadingList", "AddedDate", &addedDateColumnInfo,
sizeof(addedDateColumnInfo), JET_ColInfo);
NS_HANDLE_JET_ERROR(err)
// verify the column types are what we expect:
if (urlColumnInfo.coltyp != JET_coltypLongText ||
titleColumnInfo.coltyp != JET_coltypLongText ||
addedDateColumnInfo.coltyp != JET_coltypLongLong) {
rv = NS_ERROR_NOT_IMPLEMENTED;
goto CloseDB;
}
JET_COLUMNID urlColumnId = urlColumnInfo.columnid;
JET_COLUMNID titleColumnId = titleColumnInfo.columnid;
JET_COLUMNID addedDateColumnId = addedDateColumnInfo.columnid;
// If we got here, we've found our table and column information
err = JetMove(sesid, tableid, JET_MoveFirst, 0);
// It's possible there are 0 items in this table, in which case we want to
// not fail:
if (err == JET_errNoCurrentRecord) {
items.forget(aItems);
goto CloseDB;
}
// Check for any other errors
NS_HANDLE_JET_ERROR(err)
FILETIME addedDate;
wchar_t urlBuffer[MAX_URL_LENGTH] = { 0 };
wchar_t titleBuffer[MAX_TITLE_LENGTH] = { 0 };
do {
err = JetRetrieveColumn(sesid, tableid, urlColumnId, &urlBuffer,
sizeof(urlBuffer), NULL, 0, NULL);
NS_HANDLE_JET_ERROR(err)
err = JetRetrieveColumn(sesid, tableid, titleColumnId, &titleBuffer,
sizeof(titleBuffer), NULL, 0, NULL);
NS_HANDLE_JET_ERROR(err)
err = JetRetrieveColumn(sesid, tableid, addedDateColumnId, &addedDate,
sizeof(addedDate), NULL, 0, NULL);
NS_HANDLE_JET_ERROR(err)
nsCOMPtr<nsIWritablePropertyBag2> pbag = do_CreateInstance("@mozilla.org/hash-property-bag;1");
bool dateIsValid;
PRTime prAddedDate = WinMigrationFileTimeToPRTime(&addedDate, &dateIsValid);
nsDependentString url(urlBuffer);
nsDependentString title(titleBuffer);
pbag->SetPropertyAsAString(NS_LITERAL_STRING("uri"), url);
pbag->SetPropertyAsAString(NS_LITERAL_STRING("title"), title);
if (dateIsValid) {
pbag->SetPropertyAsInt64(NS_LITERAL_STRING("time"), prAddedDate);
}
items->AppendElement(pbag, false);
memset(urlBuffer, 0, sizeof(urlBuffer));
memset(titleBuffer, 0, sizeof(titleBuffer));
} while (JET_errSuccess == JetMove(sesid, tableid, JET_MoveNext, 0));
items.forget(aItems);
CloseDB:
// Terminate ESENT. This performs a clean shutdown.
// Ignore errors while closing:
if (tableOpened)
JetCloseTable(sesid, tableid);
if (dbOpened)
JetCloseDatabase(sesid, dbid, 0);
if (sessionCreated)
JetEndSession(sesid, 0);
if (instanceCreated)
JetTerm(instance);
return rv;
}
nsresult
nsEdgeReadingListExtractor::ConvertJETError(const JET_ERR &aError)
{
switch (aError) {
case JET_errPageSizeMismatch:
case JET_errInvalidName:
case JET_errColumnNotFound:
// The DB format has changed and we haven't updated this migration code:
return NS_ERROR_NOT_IMPLEMENTED;
case JET_errDatabaseLocked:
return NS_ERROR_FILE_IS_LOCKED;
case JET_errPermissionDenied:
case JET_errAccessDenied:
return NS_ERROR_FILE_ACCESS_DENIED;
case JET_errInvalidFilename:
return NS_ERROR_FILE_INVALID_PATH;
case JET_errFileNotFound:
return NS_ERROR_FILE_NOT_FOUND;
default:
return NS_ERROR_FAILURE;
}
}

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

@ -0,0 +1,31 @@
/* 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 edgereadinglistextractor__h__
#define edgereadinglistextractor__h__
#include "nsIArray.h"
#include "nsIEdgeReadingListExtractor.h"
// To get access to the long data types, we need to use at least the Vista version of the JET APIs
#undef JET_VERSION
#define JET_VERSION 0x0600
#include <esent.h>
class nsEdgeReadingListExtractor final : public nsIEdgeReadingListExtractor
{
public:
nsEdgeReadingListExtractor() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIEDGEREADINGLISTEXTRACTOR
private:
~nsEdgeReadingListExtractor() {}
nsresult ConvertJETError(const JET_ERR &err);
};
#endif

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

@ -7,37 +7,13 @@
#include <urlhist.h> #include <urlhist.h>
#include <shlguid.h> #include <shlguid.h>
#include "nsStringAPI.h"
#include "nsNetUtil.h"
#include "prtime.h"
#include "nsIVariant.h"
#include "nsCOMArray.h"
#include "nsArrayEnumerator.h" #include "nsArrayEnumerator.h"
#include "nsCOMArray.h"
namespace { #include "nsIVariant.h"
#include "nsNetUtil.h"
PRTime FileTimeToPRTime(FILETIME* filetime) #include "nsStringAPI.h"
{ #include "nsWindowsMigrationUtils.h"
SYSTEMTIME st; #include "prtime.h"
::FileTimeToSystemTime(filetime, &st);
PRExplodedTime prt;
prt.tm_year = st.wYear;
// SYSTEMTIME's day-of-month parameter is 1-based,
// PRExplodedTime's is 0-based.
prt.tm_month = st.wMonth - 1;
prt.tm_mday = st.wDay;
prt.tm_hour = st.wHour;
prt.tm_min = st.wMinute;
prt.tm_sec = st.wSecond;
prt.tm_usec = st.wMilliseconds * 1000;
prt.tm_wday = 0;
prt.tm_yday = 0;
prt.tm_params.tp_gmt_offset = 0;
prt.tm_params.tp_dst_offset = 0;
return PR_ImplodeTime(&prt);
}
} // namespace
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//// nsIEHistoryEnumerator //// nsIEHistoryEnumerator
@ -106,14 +82,17 @@ nsIEHistoryEnumerator::HasMoreElements(bool* _retval)
nsDependentString title(statURL.pwcsTitle); nsDependentString title(statURL.pwcsTitle);
PRTime lastVisited = FileTimeToPRTime(&(statURL.ftLastVisited)); bool lastVisitTimeIsValid;
PRTime lastVisited = WinMigrationFileTimeToPRTime(&(statURL.ftLastVisited), &lastVisitTimeIsValid);
mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1"); mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1");
MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag"); MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag");
if (mCachedNextEntry) { if (mCachedNextEntry) {
mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri); mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri);
mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title); mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title);
mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited); if (lastVisitTimeIsValid) {
mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited);
}
*_retval = true; *_retval = true;
} }

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

@ -0,0 +1,23 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIArray;
[scriptable, uuid(bfdef4aa-dcd1-4d31-b5d9-188fe8d98623)]
interface nsIEdgeReadingListExtractor : nsISupports
{
/**
* Import data from the database indicated by the databasePath
* May fail if the path is invalid, unreadable, the database is corrupt,
* or the data in the database is not in the format we expect.
*
* @param databasePath the absolute path to the database we'd like to import
* @return an enumerator of nsIPropertyBag2 items that each have a URL, title, and
* creation dates.
*/
nsIArray extract(in DOMString databasePath);
};

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

@ -0,0 +1,36 @@
/* 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 windowsmigrationutils__h__
#define windowsmigrationutils__h__
#include "prtime.h"
static
PRTime WinMigrationFileTimeToPRTime(FILETIME* filetime, bool* isValid)
{
SYSTEMTIME st;
*isValid = ::FileTimeToSystemTime(filetime, &st);
if (!*isValid) {
return 0;
}
PRExplodedTime prt;
prt.tm_year = st.wYear;
// SYSTEMTIME's day-of-month parameter is 1-based,
// PRExplodedTime's is 0-based.
prt.tm_month = st.wMonth - 1;
prt.tm_mday = st.wDay;
prt.tm_hour = st.wHour;
prt.tm_min = st.wMinute;
prt.tm_sec = st.wSecond;
prt.tm_usec = st.wMilliseconds * 1000;
prt.tm_wday = 0;
prt.tm_yday = 0;
prt.tm_params.tp_gmt_offset = 0;
prt.tm_params.tp_dst_offset = 0;
return PR_ImplodeTime(&prt);
}
#endif

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

@ -17,6 +17,7 @@ sourceName360se=360 Secure Browser
importedBookmarksFolder=From %S importedBookmarksFolder=From %S
importedSafariReadingList=Reading List (From Safari) importedSafariReadingList=Reading List (From Safari)
importedEdgeReadingList=Reading List (From Edge)
# Import Sources # Import Sources
# Note: When adding an import source for profile reset, add the string name to # Note: When adding an import source for profile reset, add the string name to