"use strict";
var EXPORTED_SYMBOLS = ["BookmarksEngine"];
Cu.import("resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyGetter(this,"placesDBConnection",function () {
return PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
}
);
[["URI_FIXUP", "@mozilla.org/docshell/urifixup;1", "nsIURIFixup"]].forEach(function ([name, contract, iface]) {
XPCOMUtils.defineLazyServiceGetter(this,name,contract,iface);
}
,this);
var {Engine: Engine} = require("engines");
var {Utils: Utils} = require("utils");
var {Observers: Observers} = require("observers");
var {BookmarksModel: BookmarksModel} = require("./modules/model");
var {QUERIES: QUERIES, STORAGE_QUERIES: STORAGE_QUERIES, TRIGGER_FUNCTION_NAME: TRIGGER_FUNCTION_NAME} = require("./modules/sql");
var IS_YANDEX_HOST_REG = /(^|\.)(yandex\.(ru|ua|by|kz|net|com(\.tr)?)|(ya|narod|moikrug)\.ru)$/i;
var DEFAULT_BOOKMARKS_IDS = [3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14];
var MOZILLA_FIREFOX_FOLDER = 7;
function BookmarksEngine() {
Engine.call(this,"Bookmarks",STORAGE_QUERIES);
}

BookmarksEngine.prototype = {
__proto__: Engine.prototype,
init: function BookmarksEngine_init() {
this._logger.debug("init");
this._model = new BookmarksModel();
this._queue.key = "browser_id";
try {
this.placesDBWrapper.execQuerySpinningly(QUERIES.ATTACH_STORAGE_DB,{
path: this.database.storageFile.path});
}
catch (e) {

}

this.database.connection.createFunction(TRIGGER_FUNCTION_NAME,2,this._hasSameIdSQLFunc.bind(this));
this.database.execQuery(QUERIES.CREATE_TRIGGER);
this._itemTypes = Object.create(null);
this._excludeDuplicate = true;
this.update((function () {
this._excludeDuplicate = false;
this._firstSync();
this._afterFirstSyncHook();
}
).bind(this));
}
,
finalize: function BookmarksEngine_finalize() {
this._logger.debug("finalize");
this.database.execQuery(QUERIES.DROP_TRIGGER);
try {
this.database.connection.removeFunction(TRIGGER_FUNCTION_NAME);
}
catch (e) {

}

try {
this.placesDBWrapper.execQueryAsync(QUERIES.DETACH_STORAGE_DB);
}
catch (e) {

}

try {
PlacesUtils.bookmarks.removeObserver(this);
}
catch (e) {

}

Observers.remove("bookmarks-restore-begin",this);
Observers.remove("bookmarks-restore-success",this);
Observers.remove("bookmarks-restore-failed",this);
this._itemTypes = null;
this._model = null;
}
,
setListData: function Engine_setListData(list) {
this._sortList(list);
var that = this;
PlacesUtils.bookmarks.runInBatchMode({
runBatched: function Engine_runBatched() {
Engine.prototype.setListData.call(that,list);
that._syncQueue();
}
},null);
}
,
setData: function BookmarksEngine_setData(data) {
if (! this.enabled)
throw new Error("Trying setData on disabled engine");
var entry = this._model.get(data);
if (! entry)
return;
var storageEntry = this._storage.findEntry({
id_string: entry.id_string});
this._logger.debug("storageEntry: ",! ! storageEntry);
if (storageEntry && storageEntry.version === entry.version)
return;
if (data.server_defined_unique_tag)
{
this._logger.debug("server_defined_unique_tag: ",data.server_defined_unique_tag);
switch (data.server_defined_unique_tag) {
case "google_chrome_bookmarks":
entry.browser_id = parseInt(PlacesUtils.bookmarks.placesRoot,10);
break;
case "bookmark_bar":
entry.browser_id = parseInt(PlacesUtils.bookmarks.toolbarFolder,10);
break;
case "other_bookmarks":
entry.browser_id = parseInt(PlacesUtils.bookmarks.unfiledBookmarksFolder,10);
break;
default:
this._logger.error("Unknown 'server_defined_unique_tag': " + data.server_defined_unique_tag);
return;
}

entry.parent_browser_id = "0";
this._storage.updateEntry(entry);
return;
}

if (data.yandex_client_tag)
{
this._logger.debug("yandex_client_tag: ",data.yandex_client_tag);
switch (data.yandex_client_tag) {
case "firefox_menu_folder":
entry.browser_id = parseInt(PlacesUtils.bookmarks.bookmarksMenuFolder,10);
entry.parent_browser_id = 0;
break;
case "mozilla_firefox_folder":
let localEntry = this._getLocalEntryById(MOZILLA_FIREFOX_FOLDER);
let parentEntry = this._storage.findEntry({
id_string: entry.parent_id_string});
if (! parentEntry)
return;
entry.parent_browser_id = parentEntry.browser_id;
entry.parent_id_string = parentEntry.id_string;
if (localEntry)
{
entry.browser_id = MOZILLA_FIREFOX_FOLDER;
parentEntry = this._storage.findEntry({
browser_id: localEntry.parentId});
if (! parentEntry || entry.parent_browser_id !== parentEntry.browser_id)
return;
}
 else
{
entry.browser_id = PlacesUtils.bookmarks.createFolder(entry.parent_browser_id,entry.title,PlacesUtils.bookmarks.DEFAULT_INDEX);
this.ignoreKey(entry.browser_id);
}

default:
break;
}

this._storage.updateEntry(entry);
this.unignoreKey(entry.browser_id);
return;
}

if (entry.browser_id)
{
this._storage.updateEntry(entry);
return;
}

if (! storageEntry)
{
if (data.deleted)
return;
let parentEntry = this._storage.findEntry({
id_string: entry.parent_id_string});
if (! parentEntry || ! parentEntry.browser_id)
{
this._logger.error("setData: can not find parent folder id for storage entry.");
return;
}

entry.parent_browser_id = parentEntry.browser_id;
if (this._excludeDuplicate)
{
let duplicateEntry = this._findDuplicate(entry);
if (duplicateEntry)
{
this._logger.debug("foundedDuplicate " + JSON.stringify(duplicateEntry));
this._storage.updateEntry(entry);
return;
}

}

if (data.folder)
{
entry.browser_id = PlacesUtils.bookmarks.createFolder(entry.parent_browser_id,entry.title,PlacesUtils.bookmarks.DEFAULT_INDEX);
this.ignoreKey(entry.browser_id);
}
 else
{
try {
let bookmarkURI = this._createURI(entry.url);
entry.browser_id = PlacesUtils.bookmarks.insertBookmark(entry.parent_browser_id,bookmarkURI,PlacesUtils.bookmarks.DEFAULT_INDEX,entry.title);
this.ignoreKey(entry.browser_id);
}
catch (e) {
this._logger.error("setData: can not create bookmark URI");
return;
}

}

this._storage.updateEntry(entry);
NativeAPI.Async.nextTick(this.unignoreKey.bind(this,entry.browser_id));
return;
}

this._logger.debug("StorageEntry: ",JSON.stringify(storageEntry));
this.ignoreKey(storageEntry.browser_id);
entry.browser_id = storageEntry.browser_id;
entry.parent_browser_id = storageEntry.parent_browser_id;
if (entry.deleted)
{
try {
PlacesUtils.bookmarks.removeItem(storageEntry.browser_id);
}
catch (ex) {
this._logger.debug("setData: can not remove bookmark. " + ex);
}

NativeAPI.Async.nextTick(this.unignoreKey.bind(this,entry.browser_id));
this._storage.removeEntries({
id_string: entry.id_string});
return;
}

var localEntry = this._getLocalEntryById(storageEntry.browser_id);
if (! localEntry)
{
NativeAPI.Async.nextTick(this.unignoreKey.bind(this,entry.browser_id));
return;
}

if (! data.folder)
{
try {
if (localEntry.url === storageEntry.url)
{
let bookmarkURI = this._createURI(entry.url);
if (bookmarkURI)
PlacesUtils.bookmarks.changeBookmarkURI(storageEntry.browser_id,bookmarkURI);
}

}
catch (e) {
this._logger.error("setData: can not create bookmark URI ",e);
}

}

if (entry.title && localEntry.title === storageEntry.title)
PlacesUtils.bookmarks.setItemTitle(storageEntry.browser_id,entry.title);
var parentEntry = this._storage.findEntry({
id_string: entry.parent_id_string});
if (! parentEntry)
{
this._logger.error("setData: can not find parent folder for storage entry.");
this._logger.debug("id_string: " + entry.id_string + ", parent_id_string: " + entry.parent_id_string);
this.unignoreKey(entry.browser_id);
return;
}

if (parentEntry.browser_id !== storageEntry.parent_browser_id && storageEntry.parent_browser_id === localEntry.parentId)
{
PlacesUtils.bookmarks.moveItem(storageEntry.browser_id,parentEntry.browser_id,PlacesUtils.bookmarks.DEFAULT_INDEX);
entry.parent_browser_id = parentEntry.browser_id;
}

NativeAPI.Async.nextTick(this.unignoreKey.bind(this,entry.browser_id));
this._storage.updateEntry(entry);
}
,
_firstSync: function BookmarksEngine__firstSync() {
this._logger.debug("_firstSync");
var result = this.placesDBWrapper.execQuerySpinningly(QUERIES.SELECT_ALL_BOOKMARKS);
var needSync = false;
result.forEach(function (item) {
if (item.storageId && ! item.itemId)
{
needSync = this.removeEntry({
browser_id: item.storageId}) || needSync;
return;
}

if (this._ignore(item.itemId,item.parentId))
return;
var entry = {
id_string: item.id_string || Utils.generateUUIDString(),
parent_id_string: null,
version: item.version || 0,
ctime: item.dateAdded,
mtime: item.lastModified,
folder: item.type === PlacesUtils.bookmarks.TYPE_FOLDER,
url: item.url,
title: item.title,
browser_id: item.itemId,
parent_browser_id: item.parentId};
if (item.storageId)
{
if (item.title !== item.storageTitle || item.url !== item.storageUrl)
{
needSync = this.changeEntry(entry) || needSync;
}

if (item.parentId !== item.storageParentId)
{
needSync = this.moveEntry(entry) || needSync;
}

return;
}

needSync = this.addEntry(entry) || needSync;
}
,this);
if (needSync)
this.sync();
PlacesUtils.bookmarks.addObserver(this,true);
Observers.add("bookmarks-restore-begin",this);
Observers.add("bookmarks-restore-success",this);
Observers.add("bookmarks-restore-failed",this);
}
,
observe: function BookmarksEngine_observe(subject, topic, data) {
switch (topic) {
case "bookmarks-restore-begin":
this._logger.debug("Ignoring changes from importing bookmarks.");
this.ignoreAll = true;
break;
case "bookmarks-restore-success":
this._logger.debug("Continue tracking changes after restore.");
this.ignoreAll = false;
break;
case "bookmarks-restore-failed":
this._logger.debug("Continue tracking changes after failed restore.");
this.ignoreAll = false;
break;
}

}
,
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver, Ci.nsISupportsWeakReference]),
_knownTypes: [PlacesUtils.bookmarks.TYPE_BOOKMARK, PlacesUtils.bookmarks.TYPE_FOLDER],
_knownRootFolders: [parseInt(PlacesUtils.bookmarks.unfiledBookmarksFolder,10), parseInt(PlacesUtils.bookmarks.toolbarFolder,10), parseInt(PlacesUtils.bookmarks.bookmarksMenuFolder,10)],
_findDuplicate: function BookmarksEngine__findDuplicate(entry) {
var localEntries = this.placesDBWrapper.execQuerySpinningly(QUERIES.SELECT_BOOKMARKS_BY_PARENT,{
browser_id: entry.parent_browser_id});
var matchedEntry = null;
for (let i = 0, length = localEntries.length;i < length;i++) {
let localEntry = localEntries[i];
if (this._storage.findEntry({
browser_id: localEntry.itemId}))
continue;
let isFolder = localEntry.type === PlacesUtils.bookmarks.TYPE_FOLDER;
if (localEntry.title === entry.title && isFolder === entry.folder)
{
if (isFolder)
{
matchedEntry = entry;
matchedEntry.browser_id = localEntry.itemId;
break;
}
 else
{
let uri1;
let uri2;
try {
uri1 = URI_FIXUP.createFixupURI(entry.url,URI_FIXUP.FIXUP_FLAG_NONE);
uri2 = URI_FIXUP.createFixupURI(localEntry.url,URI_FIXUP.FIXUP_FLAG_NONE);
}
catch (e) {
continue;
}

if (uri1.spec === uri2.spec)
{
matchedEntry = entry;
matchedEntry.browser_id = localEntry.itemId;
break;
}
 else
{
try {
if (IS_YANDEX_HOST_REG.test(uri1.host) && IS_YANDEX_HOST_REG.test(uri2.host))
{
matchedEntry = entry;
matchedEntry.browser_id = localEntry.itemId;
matchedEntry.url = entry.url;
break;
}

}
catch (e) {

}

}

}

}

}

return matchedEntry;
}
,
_isMatched: function BookmarksEngine__isMatched(entry, localEntry) {
var isFolder = localEntry.type === PlacesUtils.bookmarks.TYPE_FOLDER;
if (locaEntry.title === entry.title && isFolder === entry.folder)
{
if (isFolder)
return true; else
if (localEntry.url === entry.url)
{
return true;
}

}

return false;
}
,
_ignore: function BookmarksEngine__ignore(itemId, folder, guid) {
if (this.ignoreAll)
return true;
try {
let itemType = PlacesUtils.bookmarks.getItemType(itemId);
if (this._knownTypes.indexOf(itemType) === - 1)
return true;
}
catch (e) {
this._logger.debug("Couldn't get item type for item: ",itemId);
let itemType = this._itemTypes[itemId];
if (itemType && this._knownTypes.indexOf(itemType) === - 1)
return true;
}

if (this.isIgnoredKey(itemId))
{
this._logger.debug("isIgnoredKey ",itemId);
return true;
}

if (! folder)
{
folder = PlacesUtils.bookmarks.getFolderIdForItem(itemId);
}

var topTrackingFolder = this._getTopTrackingFolder(folder);
if (! topTrackingFolder)
{
this._logger.trace("Can not get root folder for item: " + itemId);
return true;
}

if (~ DEFAULT_BOOKMARKS_IDS.indexOf(itemId))
return true;
return false;
}
,
_getTopTrackingFolder: function BookmarksEngine__getTopTrackingFolder(folder) {
var topTrackingFolder = folder;
while (topTrackingFolder) {
if (this._knownRootFolders.indexOf(topTrackingFolder) !== - 1)
break;
topTrackingFolder = PlacesUtils.bookmarks.getFolderIdForItem(topTrackingFolder);
}

return topTrackingFolder;
}
,
_createMenuFolder: function BookmarsEngine__createMenuFolder() {
this._createMenuFolder = function BookmarsEngine__createMenuFolder() {

}
;
var parentEntry = this._storage.findEntry({
browser_id: PlacesUtils.bookmarks.unfiledBookmarksFolder});
if (! parentEntry)
return;
var entry = {
id_string: Utils.generateUUIDString(),
parent_id_string: null,
version: 0,
ctime: Date.now(),
mtime: Date.now(),
folder: true,
url: null,
title: "firefox menu",
browser_id: PlacesUtils.bookmarks.bookmarksMenuFolder,
parent_browser_id: parentEntry.browser_id,
yandex_client_tag: "firefox_menu_folder"};
if (this.addEntry(entry))
this.sync();
}
,
_createMozillaFirefoxFolder: function BookmarksEngine__createMozillaFirefoxFolder() {
this._createMozillaFirefoxFolder = function BookmarksEngine__createMozillaFirefoxFolder() {

}
;
var localEntry = this._getLocalEntryById(MOZILLA_FIREFOX_FOLDER);
if (! localEntry)
return;
var entry = {
id_string: Utils.generateUUIDString(),
parent_id_string: null,
version: 0,
ctime: localEntry.dateAdded,
mtime: Date.now(),
folder: true,
url: null,
title: localEntry.title,
browser_id: MOZILLA_FIREFOX_FOLDER,
parent_browser_id: localEntry.parentId,
yandex_client_tag: "mozilla_firefox_folder"};
if (this.addEntry(entry))
this.sync();
}
,
_createURI: function BookmarksEngine__createURI(url) {
try {
let bookmarkURI = URI_FIXUP.createFixupURI(url,URI_FIXUP.FIXUP_FLAG_NONE);
if (IS_YANDEX_HOST_REG.test(bookmarkURI.asciiHost) && ~ bookmarkURI.path.indexOf("clid"))
{
let clid = NativeAPI.DistrData.getRecord("clid15");
if (clid)
{
let url = bookmarkURI.spec.replace(/([?&])clid=[^&]+/g,function (match, match1) match1 + "clid=" + clid);
bookmarkURI = URI_FIXUP.createFixupURI(url,URI_FIXUP.FIXUP_FLAG_NONE);
}

}

return bookmarkURI;
}
catch (e) {

}

return null;
}
,
onItemAdded: function BookmarksEngine_onItemAdded(itemId, parentId, index, itemType, uri, title, dateAdded, guid, parentGuid) {
NativeAPI.Async.nextTick((function () {
this._logger.debug("onItemAdded: " + itemId + " " + parentId);
try {
this._itemTypes[itemId] = PlacesUtils.bookmarks.getItemType(itemId);
}
catch (e) {
this._logger.debug("Couldn't get item type");
}

var ignore = this._ignore(itemId,parentId,guid);
this._logger.debug("ignore: ",ignore);
if (ignore)
return;
var timeAdded = (new Date(dateAdded / 1000)).getTime();
var newEntry = {
id_string: Utils.generateUUIDString(),
parent_id_string: null,
version: 0,
ctime: timeAdded,
mtime: timeAdded,
folder: itemType === PlacesUtils.bookmarks.TYPE_FOLDER,
url: uri && uri.spec || "",
favicon: "",
title: title || "",
icon_url: null,
browser_id: itemId,
parent_browser_id: parentId};
if (this.addEntry(newEntry))
this.sync();
}
).bind(this));
}
,
onItemRemoved: function BookmarksEngine_onItemRemoved(itemId, parentId, index, itemType, uri, guid, parentGuid) {
this._logger.debug("onItemRemoved: " + itemId);
var ignore = this._ignore(itemId,parentId,guid);
this._logger.debug("ignore: ",ignore);
if (ignore)
{
if (itemId !== MOZILLA_FIREFOX_FOLDER)
{
return;
}
 else
{
let storageEntry = this._storage.findEntry({
browser_id: MOZILLA_FIREFOX_FOLDER});
if (! storageEntry)
return;
}

}

var entry = {
id_string: null,
parent_id_string: null,
browser_id: itemId,
parent_browser_id: parentId,
folder: itemType === PlacesUtils.bookmarks.TYPE_FOLDER};
if (this.removeEntry(entry))
this.sync();
}
,
onItemChanged: function BookmarksEngine_onItemChanged(itemId, property, isAnno, value, lastModified, itemType, parentId, guid, parentGuid) {
if (isAnno)
return;
if (property === "favicon")
return;
this._logger.debug("onItemChanged: " + itemId + (", " + property) + (value ? " = \"" + value + "\"" : ""));
var ignore = this._ignore(itemId,parentId,guid);
this._logger.debug("ignore: ",ignore);
if (ignore)
return;
var entry = {
id_string: null,
parent_id_string: null,
browser_id: itemId,
parent_browser_id: parentId,
folder: itemType === PlacesUtils.bookmarks.TYPE_FOLDER};
if (lastModified)
{
entry.mtime = (new Date(lastModified / 1000)).getTime();
}

if (this.changeEntry(entry))
this.sync();
}
,
onItemMoved: function BookmarksEngine_onItemMoved(itemId, oldParentId, oldIndex, newParentId, newIndex, itemType, guid, oldParentGuid, newParentGuid) {
this._logger.debug("onItemMoved: ",itemId);
var ignore = this._ignore(itemId,newParentId,guid);
this._logger.debug("ignore: ",ignore);
if (ignore)
return;
if (oldParentId === newParentId)
return;
var entry = {
id_string: null,
parent_id_string: null,
browser_id: itemId,
parent_browser_id: newParentId,
folder: itemType === PlacesUtils.bookmarks.TYPE_FOLDER};
if (this.moveEntry(entry))
this.sync();
}
,
onBeginUpdateBatch: function BookmarksEngine_onBeginUpdateBatch() {

}
,
onEndUpdateBatch: function BookmarksEngine_onEndUpdateBatch() {

}
,
onItemVisited: function BookmarksEngine_onItemVisited() {

}
,
addEntry: function BookmarksEngine_addEntry(entry) {
this._logger.debug("addEntry",JSON.stringify(entry));
if (! entry)
return false;
var parentEntry = this._storage.findEntry({
browser_id: entry.parent_browser_id});
if (! parentEntry)
{
this._logger.debug("Can not find parent entry for '" + entry.browser_id + "'");
if (entry.parent_browser_id === PlacesUtils.bookmarks.bookmarksMenuFolder)
this._createMenuFolder();
if (entry.parent_browser_id === MOZILLA_FIREFOX_FOLDER)
this._createMozillaFirefoxFolder();
this._queue.write("add",[entry]);
return false;
}

this._logger.debug("parentEntry: ",JSON.stringify(parentEntry));
entry.parent_id_string = parentEntry.id_string;
this._insertRecords({
add: [entry]},true);
return true;
}
,
removeEntry: function BookmarksEngine_removeEntry(entry) {
this._logger.debug("removeEntry",JSON.stringify(entry));
if (! entry)
return false;
var deletedEntry = this._storage.findEntry({
browser_id: entry.browser_id});
if (! deletedEntry)
{
this._queue.write("remove",[entry]);
return false;
}

if (entry.folder)
{
let someChild = this._storage.findEntry({
parent_browser_id: entry.browser_id});
if (someChild)
{
this._queue.write("remove",[entry]);
return false;
}

this._queue.remove([entry.browser_id]);
}

this._insertRecords({
remove: [deletedEntry]},true);
return true;
}
,
changeEntry: function BookmarksEngine_changeEntry(entry) {
this._logger.debug("changeEntry",JSON.stringify(entry));
if (! entry)
return false;
var changedEntry = this._storage.findEntry({
browser_id: entry.browser_id});
if (! changedEntry)
{
this._logger.debug("Can not find entry for '" + entry.browser_id + "'");
this._queue.write("modify",[entry]);
return false;
}

var localEntry = this._getLocalEntryById(entry.browser_id);
if (! localEntry)
{
this._logger.debug("Can not find local entry for '" + entry.browser_id + "'");
return false;
}

this._logger.debug("localEntry: ",JSON.stringify(localEntry));
if (localEntry.parentId !== entry.parent_browser_id && entry.browser_id !== PlacesUtils.bookmarks.bookmarksMenuFolder)
{
this._logger.debug("Changed parent folder");
this._queue.write("modify",[entry]);
return false;
}

this._updateEntryByLocal(changedEntry,localEntry);
for(let [key, value] in Iterator(entry)) {
if (value != null)
changedEntry[key] = value;
}

this._logger.debug("changedEntry: ",JSON.stringify(changedEntry));
this._insertRecords({
add: [changedEntry]},true);
return true;
}
,
moveEntry: function BookmarksEngine_moveEntry(entry) {
this._logger.debug("moveEntry",JSON.stringify(entry));
var movedEntry = this._storage.findEntry({
browser_id: entry.browser_id});
if (! movedEntry)
{
this._logger.debug("Can not find entry for '" + entry.browser_id + "'");
this._queue.write("move",[entry]);
return false;
}

var parentEntry = this._storage.findEntry({
browser_id: entry.parent_browser_id});
if (! parentEntry)
{
this._logger.debug("Can not find parent entry for '" + entry.browser_id + "' with parent '" + entry.parent_browser_id + "'");
if (entry.parent_browser_id === PlacesUtils.bookmarks.bookmarksMenuFolder)
this._createMenuFolder();
if (entry.parent_browser_id === MOZILLA_FIREFOX_FOLDER)
this._createMozillaFirefoxFolder();
this._queue.write("move",[entry]);
return false;
}

var localEntry = this._getLocalEntryById(entry.browser_id);
if (! localEntry)
{
this._logger.debug("Can not find local entry for '" + entry.browser_id + "'");
return false;
}

this._logger.debug("localEntry: ",JSON.stringify(localEntry));
if (localEntry.parent_browser_id !== entry.parent_browser_id)
{
this._logger.debug("Conflict with parent folders local: ",localEntry.parent_browser_id,", entry: ",entry.parent_browser_id);
}

this._updateEntryByLocal(movedEntry,localEntry);
movedEntry.parent_id_string = parentEntry.id_string;
movedEntry.parent_browser_id = entry.parent_browser_id;
this._insertRecords({
add: [movedEntry]},true);
return true;
}
,
_hasSameIdSQLFunc: function BookmarksEngine__hasSameIdSQLFunc(args) {
var id = JSON.parse(args.getString(0)).browser_id;
var newId = JSON.parse(args.getString(1)).browser_id;
return id === newId ? 1 : 0;
}
,
_syncQueue: function BookmarksEngine__syncQueue() {
this._logger.debug("syncQueue");
var needSync = false;
var data = this._queue.read();
for(let [action, actionData] in Iterator(data)) {
for(let [key, value] in Iterator(actionData)) {
switch (action) {
case "add":
needSync = this.addEntry(value) || needSync;
break;
case "remove":
needSync = this.removeEntry(value) || needSync;
break;
case "modify":
needSync = this.changeEntry(value) || needSync;
break;
case "move":
needSync = this.moveEntry(value) || needSync;
break;
break;
default:
break;
}

}

}

if (needSync)
this.sync();
}
,
_sortList: function BookmarksEngine__sortList(list) {
var length = list.length;
var iters = 0;
var MAX_ITERS = Math.pow(length,2);
for (let i = 0;i < length;i++) {
let iitem = list[i];
let needCheckSameIndex = false;
for (let j = i + 1;j < length;j++) {
let jitem = list[j];
if (iitem.parent_id_string === jitem.id_string)
{
list.splice(i,1);
list.splice(j,0,iitem);
needCheckSameIndex = true;
}

}

if (needCheckSameIndex)
i--;
iters++;
if (iters > MAX_ITERS)
return;
}

}
,
_getLocalEntryById: function BookmarksEngine__getLocalEntry(id) {
return this.placesDBWrapper.execQuerySpinningly(QUERIES.SELECT_SPECIFIC_BOOKMARK,{
browser_id: id})[0];
}
,
_updateEntryByLocal: function BookmarksEngine__updateEntryByLocal(entry, localEntry) {
entry.title = localEntry.title;
entry.url = localEntry.url;
entry.mtime = localEntry.lastModified;
}
,
_migrate: function BookmarksEngine__migrate() {
if (this.version < 1.1)
{
this._logger.debug("Migrating at 1.1 version");
this._afterFirstSyncHook = function BookmarksEngine__afterFirstSyncHook() {
this._logger.debug("_afterFirstSyncHook version 1.1");
var localEntry = this._storage.findEntry({
browser_id: PlacesUtils.bookmarks.bookmarksMenuFolder});
this._logger.debug("Founded client_defined_unique_tag 'firefox_menu_folder': " + ! ! localEntry);
if (localEntry)
{
localEntry.client_defined_unique_tag = "";
localEntry.yandex_client_tag = "firefox_menu_folder";
this.changeEntry(localEntry);
}

localEntry = this._storage.findEntry({
browser_id: MOZILLA_FIREFOX_FOLDER});
this._logger.debug("Founded client_defined_unique_tag 'mozilla_firefox_folder': " + ! ! localEntry);
if (localEntry)
{
localEntry.client_defined_unique_tag = "";
localEntry.yandex_client_tag = "mozilla_firefox_folder";
this.changeEntry(localEntry);
}

}
;
}

}
,
_afterFirstSyncHook: function BookmarksEngine__afterFirstSyncHook() {

}
,
get placesDBWrapper() {
delete this.placesDBWrapper;
var placesDBWrapper = Utils.databaseWrapper(placesDBConnection);
this.__defineGetter__("placesDBWrapper",function () placesDBWrapper);
return placesDBWrapper;
}
,
_excludeDuplicate: false,
_itemTypes: null,
_PROTO_ID: 32904};
