Bug 570387 - PlacesDBUtils should register itself in the idle-daily category. r+a=dietrich

This commit is contained in:
Marco Bonardo 2010-10-19 12:44:03 +02:00
Родитель 6af2d876b3
Коммит c76fbed899
7 изменённых файлов: 174 добавлений и 179 удалений

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

@ -1532,11 +1532,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
}
}, 10000);
// Delayed initialization of PlacesDBUtils.
// This component checks for database coherence once per day, on
// an idle timer, taking corrective actions where needed.
setTimeout(function() PlacesUtils.startPlacesDBUtils(), 15000);
#ifndef XP_MACOSX
updateEditUIVisibility();
let placesContext = document.getElementById("placesContext");

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

@ -350,6 +350,7 @@
@BINPATH@/components/nsPlacesAutoComplete.js
@BINPATH@/components/nsPlacesExpiration.js
@BINPATH@/components/PlacesProtocolHandler.js
@BINPATH@/components/PlacesCategoriesStarter.js
@BINPATH@/components/nsDefaultCLH.manifest
@BINPATH@/components/nsDefaultCLH.js
@BINPATH@/components/nsContentPrefService.manifest

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

@ -89,6 +89,7 @@ EXTRA_COMPONENTS = \
nsPlacesDBFlush.js \
nsPlacesExpiration.js \
nsMicrosummaryService.js \
PlacesCategoriesStarter.js \
$(NULL)
ifdef MOZ_XUL

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

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 sts=2 expandtab
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Marco Bonardo <mak77@bonardo.net> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
////////////////////////////////////////////////////////////////////////////////
//// Constants
const Cc = Components.classes;
const Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
/**
* This component can be used as a starter for modules that have to run when
* certain categories are invoked.
*/
function PlacesCategoriesStarter()
{
}
PlacesCategoriesStarter.prototype = {
//////////////////////////////////////////////////////////////////////////////
//// nsIObserver
observe: function PCS_observe(aSubject, aTopic, aData)
{
switch (aTopic) {
case "idle-daily":
// Run places.sqlite maintenance tasks.
Components.utils.import("resource://gre/modules/PlacesDBUtils.jsm");
PlacesDBUtils.maintenanceOnIdle();
break;
default:
throw new Error("Trying to handle an unknown category.");
}
},
//////////////////////////////////////////////////////////////////////////////
//// nsISupports
classID: Components.ID("803938d5-e26d-4453-bf46-ad4b26e41114"),
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIObserver
])
};
////////////////////////////////////////////////////////////////////////////////
//// Module Registration
let components = [PlacesCategoriesStarter];
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

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

@ -43,118 +43,32 @@ const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PlacesUtils.jsm");
let EXPORTED_SYMBOLS = [ "PlacesDBUtils" ];
////////////////////////////////////////////////////////////////////////////////
//// Constants
const IS_CONTRACTID = "@mozilla.org/widget/idleservice;1";
const OS_CONTRACTID = "@mozilla.org/observer-service;1";
const HS_CONTRACTID = "@mozilla.org/browser/nav-history-service;1";
const BS_CONTRACTID = "@mozilla.org/browser/nav-bookmarks-service;1";
const TS_CONTRACTID = "@mozilla.org/timer;1";
const SB_CONTRACTID = "@mozilla.org/intl/stringbundle;1";
const TIM_CONTRACTID = "@mozilla.org/updates/timer-manager;1";
const PLACES_STRING_BUNDLE_URI = "chrome://places/locale/places.properties";
const FINISHED_MAINTENANCE_NOTIFICATION_TOPIC = "places-maintenance-finished";
// Do maintenance after 10 minutes of idle.
// We choose a small idle time because we must not prevent laptops from going
// to standby, also we don't want to hit cpu/disk while the user is doing other
// activities on the computer, like watching a movie.
// So, we suppose that after 10 idle minutes the user is moving to another task
// and we can hit without big troubles.
const IDLE_TIMEOUT = 10 * 60 * 1000;
////////////////////////////////////////////////////////////////////////////////
//// Smart getters
// Check for idle every 10 minutes and do maintenance if the user has been idle
// for more than IDLE_TIMEOUT.
const IDLE_LOOKUP_REPEAT = 10 * 60 * 1000;
// These are the seconds between each maintenance (24h).
const MAINTENANCE_REPEAT = 24 * 60 * 60;
XPCOMUtils.defineLazyGetter(this, "DBConn", function() {
return PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
});
////////////////////////////////////////////////////////////////////////////////
//// nsPlacesDBUtils class
function nsPlacesDBUtils() {
//////////////////////////////////////////////////////////////////////////////
//// Smart getters
XPCOMUtils.defineLazyServiceGetter(this, "_bms", BS_CONTRACTID,
"nsINavBookmarksService");
XPCOMUtils.defineLazyServiceGetter(this, "_hs", HS_CONTRACTID,
"nsINavHistoryService");
XPCOMUtils.defineLazyServiceGetter(this, "_os", OS_CONTRACTID,
"nsIObserverService");
XPCOMUtils.defineLazyServiceGetter(this, "_idlesvc", IS_CONTRACTID,
"nsIIdleService");
XPCOMUtils.defineLazyGetter(this, "_dbConn", function() {
return Cc[HS_CONTRACTID].getService(Ci.nsPIPlacesDatabase).DBConnection;
});
XPCOMUtils.defineLazyGetter(this, "_bundle", function() {
return Cc[SB_CONTRACTID].
getService(Ci.nsIStringBundleService).
createBundle(PLACES_STRING_BUNDLE_URI);
});
// register the maintenance timer
try {
let tim = Cc[TIM_CONTRACTID].getService(Ci.nsIUpdateTimerManager);
tim.registerTimer("places-maintenance-timer", this, MAINTENANCE_REPEAT);
} catch (ex) {
// The timer manager is not available in xpc shell tests
}
}
nsPlacesDBUtils.prototype = {
_idleLookupTimer: null,
_statementsRunningCount: 0,
//////////////////////////////////////////////////////////////////////////////
//// nsISupports
QueryInterface: XPCOMUtils.generateQI([
Ci.nsITimerCallback,
]),
//////////////////////////////////////////////////////////////////////////////
//// nsITimerCallback
notify: function PDBU_notify(aTimer) {
switch (aTimer) {
case this._idleLookUpTimer:
let idleTime = 0;
try {
idleTime = this._idlesvc.idleTime;
} catch (ex) {}
// do maintenance on idle
if (idleTime > IDLE_TIMEOUT) {
// Stop the timer, we do maintenance once per day
this._idleLookUpTimer.cancel();
this._idleLookUpTimer = null;
// start the cleanup
this.maintenanceOnIdle();
}
break;
default:
// Start the idle lookup timer
this._idleLookUpTimer = Cc[TS_CONTRACTID].createInstance(Ci.nsITimer);
this._idleLookUpTimer.initWithCallback(this, IDLE_LOOKUP_REPEAT,
Ci.nsITimer.TYPE_REPEATING_SLACK);
break;
}
},
//////////////////////////////////////////////////////////////////////////////
//// mozIStorageStatementCallback
@ -171,10 +85,10 @@ nsPlacesDBUtils.prototype = {
// We finished executing all statements.
// Sending Begin/EndUpdateBatch notification will ensure that the UI
// is correctly refreshed.
this._hs.runInBatchMode({runBatched: function(aUserData){}}, null);
this._bms.runInBatchMode({runBatched: function(aUserData){}}, null);
PlacesUtils.history.runInBatchMode({runBatched: function(aUserData){}}, null);
PlacesUtils.bookmarks.runInBatchMode({runBatched: function(aUserData){}}, null);
// Notify observers that maintenance tasks are complete
this._os.notifyObservers(null, FINISHED_MAINTENANCE_NOTIFICATION_TOPIC, null);
Services.obs.notifyObservers(null, FINISHED_MAINTENANCE_NOTIFICATION_TOPIC, null);
},
//////////////////////////////////////////////////////////////////////////////
@ -186,7 +100,7 @@ nsPlacesDBUtils.prototype = {
// MOZ_ANNO_ATTRIBUTES
// A.1 remove unused attributes
let deleteUnusedAnnoAttributes = this._dbConn.createStatement(
let deleteUnusedAnnoAttributes = DBConn.createStatement(
"DELETE FROM moz_anno_attributes WHERE id IN ( " +
"SELECT id FROM moz_anno_attributes n " +
"WHERE NOT EXISTS " +
@ -198,7 +112,7 @@ nsPlacesDBUtils.prototype = {
// MOZ_ANNOS
// B.1 remove annos with an invalid attribute
let deleteInvalidAttributeAnnos = this._dbConn.createStatement(
let deleteInvalidAttributeAnnos = DBConn.createStatement(
"DELETE FROM moz_annos WHERE id IN ( " +
"SELECT id FROM moz_annos a " +
"WHERE NOT EXISTS " +
@ -208,7 +122,7 @@ nsPlacesDBUtils.prototype = {
cleanupStatements.push(deleteInvalidAttributeAnnos);
// B.2 remove orphan annos
let deleteOrphanAnnos = this._dbConn.createStatement(
let deleteOrphanAnnos = DBConn.createStatement(
"DELETE FROM moz_annos WHERE id IN ( " +
"SELECT id FROM moz_annos a " +
"WHERE NOT EXISTS " +
@ -222,24 +136,24 @@ nsPlacesDBUtils.prototype = {
// C.1 fix missing Places root
// Bug 477739 shows a case where the root could be wrongly removed
// due to an endianness issue. We try to fix broken roots here.
let selectPlacesRoot = this._dbConn.createStatement(
let selectPlacesRoot = DBConn.createStatement(
"SELECT id FROM moz_bookmarks WHERE id = :places_root");
selectPlacesRoot.params["places_root"] = this._bms.placesRoot;
selectPlacesRoot.params["places_root"] = PlacesUtils.placesRootId;
if (!selectPlacesRoot.executeStep()) {
// We are missing the root, try to recreate it.
let createPlacesRoot = this._dbConn.createStatement(
let createPlacesRoot = DBConn.createStatement(
"INSERT INTO moz_bookmarks (id, type, fk, parent, position, title) " +
"VALUES (:places_root, 2, NULL, 0, 0, :title)");
createPlacesRoot.params["places_root"] = this._bms.placesRoot;
createPlacesRoot.params["places_root"] = PlacesUtils.placesRootId;
createPlacesRoot.params["title"] = "";
cleanupStatements.push(createPlacesRoot);
// Now ensure that other roots are children of Places root.
let fixPlacesRootChildren = this._dbConn.createStatement(
let fixPlacesRootChildren = DBConn.createStatement(
"UPDATE moz_bookmarks SET parent = :places_root WHERE id IN " +
"(SELECT folder_id FROM moz_bookmarks_roots " +
"WHERE folder_id <> :places_root)");
fixPlacesRootChildren.params["places_root"] = this._bms.placesRoot;
fixPlacesRootChildren.params["places_root"] = PlacesUtils.placesRootId;
cleanupStatements.push(fixPlacesRootChildren);
}
selectPlacesRoot.finalize();
@ -250,39 +164,39 @@ nsPlacesDBUtils.prototype = {
let updateRootTitleSql = "UPDATE moz_bookmarks SET title = :title " +
"WHERE id = :root_id AND title <> :title";
// root
let fixPlacesRootTitle = this._dbConn.createStatement(updateRootTitleSql);
fixPlacesRootTitle.params["root_id"] = this._bms.placesRoot;
let fixPlacesRootTitle = DBConn.createStatement(updateRootTitleSql);
fixPlacesRootTitle.params["root_id"] = PlacesUtils.placesRootId;
fixPlacesRootTitle.params["title"] = "";
cleanupStatements.push(fixPlacesRootTitle);
// bookmarks menu
let fixBookmarksMenuTitle = this._dbConn.createStatement(updateRootTitleSql);
fixBookmarksMenuTitle.params["root_id"] = this._bms.bookmarksMenuFolder;
let fixBookmarksMenuTitle = DBConn.createStatement(updateRootTitleSql);
fixBookmarksMenuTitle.params["root_id"] = PlacesUtils.bookmarksMenuFolderId;
fixBookmarksMenuTitle.params["title"] =
this._bundle.GetStringFromName("BookmarksMenuFolderTitle");
PlacesUtils.getString("BookmarksMenuFolderTitle");
cleanupStatements.push(fixBookmarksMenuTitle);
// bookmarks toolbar
let fixBookmarksToolbarTitle = this._dbConn.createStatement(updateRootTitleSql);
fixBookmarksToolbarTitle.params["root_id"] = this._bms.toolbarFolder;
let fixBookmarksToolbarTitle = DBConn.createStatement(updateRootTitleSql);
fixBookmarksToolbarTitle.params["root_id"] = PlacesUtils.toolbarFolderId;
fixBookmarksToolbarTitle.params["title"] =
this._bundle.GetStringFromName("BookmarksToolbarFolderTitle");
PlacesUtils.getString("BookmarksToolbarFolderTitle");
cleanupStatements.push(fixBookmarksToolbarTitle);
// unsorted bookmarks
let fixUnsortedBookmarksTitle = this._dbConn.createStatement(updateRootTitleSql);
fixUnsortedBookmarksTitle.params["root_id"] = this._bms.unfiledBookmarksFolder;
let fixUnsortedBookmarksTitle = DBConn.createStatement(updateRootTitleSql);
fixUnsortedBookmarksTitle.params["root_id"] = PlacesUtils.unfiledBookmarksFolderId;
fixUnsortedBookmarksTitle.params["title"] =
this._bundle.GetStringFromName("UnsortedBookmarksFolderTitle");
PlacesUtils.getString("UnsortedBookmarksFolderTitle");
cleanupStatements.push(fixUnsortedBookmarksTitle);
// tags
let fixTagsRootTitle = this._dbConn.createStatement(updateRootTitleSql);
fixTagsRootTitle.params["root_id"] = this._bms.tagsFolder;
let fixTagsRootTitle = DBConn.createStatement(updateRootTitleSql);
fixTagsRootTitle.params["root_id"] = PlacesUtils.tagsFolderId;
fixTagsRootTitle.params["title"] =
this._bundle.GetStringFromName("TagsFolderTitle");
PlacesUtils.getString("TagsFolderTitle");
cleanupStatements.push(fixTagsRootTitle);
// MOZ_BOOKMARKS
// D.1 remove items without a valid place
// if fk IS NULL we fix them in D.7
let deleteNoPlaceItems = this._dbConn.createStatement(
let deleteNoPlaceItems = DBConn.createStatement(
"DELETE FROM moz_bookmarks WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
@ -291,11 +205,11 @@ nsPlacesDBUtils.prototype = {
"AND NOT EXISTS (SELECT url FROM moz_places_temp WHERE id = b.fk LIMIT 1) " +
"AND NOT EXISTS (SELECT url FROM moz_places WHERE id = b.fk LIMIT 1) " +
")");
deleteNoPlaceItems.params["bookmark_type"] = this._bms.TYPE_BOOKMARK;
deleteNoPlaceItems.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
cleanupStatements.push(deleteNoPlaceItems);
// D.2 remove items that are not uri bookmarks from tag containers
let deleteBogusTagChildren = this._dbConn.createStatement(
let deleteBogusTagChildren = DBConn.createStatement(
"DELETE FROM moz_bookmarks WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
@ -304,12 +218,12 @@ nsPlacesDBUtils.prototype = {
"(SELECT id FROM moz_bookmarks WHERE parent = :tags_folder) " +
"AND b.type <> :bookmark_type " +
")");
deleteBogusTagChildren.params["tags_folder"] = this._bms.tagsFolder;
deleteBogusTagChildren.params["bookmark_type"] = this._bms.TYPE_BOOKMARK;
deleteBogusTagChildren.params["tags_folder"] = PlacesUtils.tagsFolderId;
deleteBogusTagChildren.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
cleanupStatements.push(deleteBogusTagChildren);
// D.3 remove empty tags
let deleteEmptyTags = this._dbConn.createStatement(
let deleteEmptyTags = DBConn.createStatement(
"DELETE FROM moz_bookmarks WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
@ -319,11 +233,11 @@ nsPlacesDBUtils.prototype = {
"AND NOT EXISTS " +
"(SELECT id from moz_bookmarks WHERE parent = b.id LIMIT 1) " +
")");
deleteEmptyTags.params["tags_folder"] = this._bms.tagsFolder;
deleteEmptyTags.params["tags_folder"] = PlacesUtils.tagsFolderId;
cleanupStatements.push(deleteEmptyTags);
// D.4 move orphan items to unsorted folder
let fixOrphanItems = this._dbConn.createStatement(
let fixOrphanItems = DBConn.createStatement(
"UPDATE moz_bookmarks SET parent = :unsorted_folder WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
@ -332,11 +246,11 @@ nsPlacesDBUtils.prototype = {
"AND NOT EXISTS " +
"(SELECT id FROM moz_bookmarks WHERE id = b.parent LIMIT 1) " +
")");
fixOrphanItems.params["unsorted_folder"] = this._bms.unfiledBookmarksFolder;
fixOrphanItems.params["unsorted_folder"] = PlacesUtils.unfiledBookmarksFolderId;
cleanupStatements.push(fixOrphanItems);
// D.5 fix wrong keywords
let fixInvalidKeywords = this._dbConn.createStatement(
let fixInvalidKeywords = DBConn.createStatement(
"UPDATE moz_bookmarks SET keyword_id = NULL WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
@ -351,7 +265,7 @@ nsPlacesDBUtils.prototype = {
// Folders, separators and dynamic containers should not have an fk.
// If they have a valid fk convert them to bookmarks. Later in D.9 we
// will move eventual children to unsorted bookmarks.
let fixBookmarksAsFolders = this._dbConn.createStatement(
let fixBookmarksAsFolders = DBConn.createStatement(
"UPDATE moz_bookmarks SET type = :bookmark_type WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
@ -359,16 +273,16 @@ nsPlacesDBUtils.prototype = {
"WHERE type IN (:folder_type, :separator_type, :dynamic_type) " +
"AND fk NOTNULL " +
")");
fixBookmarksAsFolders.params["bookmark_type"] = this._bms.TYPE_BOOKMARK;
fixBookmarksAsFolders.params["folder_type"] = this._bms.TYPE_FOLDER;
fixBookmarksAsFolders.params["separator_type"] = this._bms.TYPE_SEPARATOR;
fixBookmarksAsFolders.params["dynamic_type"] = this._bms.TYPE_DYNAMIC_CONTAINER;
fixBookmarksAsFolders.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
fixBookmarksAsFolders.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
fixBookmarksAsFolders.params["separator_type"] = PlacesUtils.bookmarks.TYPE_SEPARATOR;
fixBookmarksAsFolders.params["dynamic_type"] = PlacesUtils.bookmarks.TYPE_DYNAMIC_CONTAINER;
cleanupStatements.push(fixBookmarksAsFolders);
// D.7 fix wrong item types
// Bookmarks should have an fk, if they don't have any, convert them to
// folders.
let fixFoldersAsBookmarks = this._dbConn.createStatement(
let fixFoldersAsBookmarks = DBConn.createStatement(
"UPDATE moz_bookmarks SET type = :folder_type WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
@ -376,14 +290,14 @@ nsPlacesDBUtils.prototype = {
"WHERE type = :bookmark_type " +
"AND fk IS NULL " +
")");
fixFoldersAsBookmarks.params["bookmark_type"] = this._bms.TYPE_BOOKMARK;
fixFoldersAsBookmarks.params["folder_type"] = this._bms.TYPE_FOLDER;
fixFoldersAsBookmarks.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
fixFoldersAsBookmarks.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
cleanupStatements.push(fixFoldersAsBookmarks);
// D.8 fix wrong item types
// Dynamic containers should have a folder_type, if they don't have any
// convert them to folders.
let fixFoldersAsDynamic = this._dbConn.createStatement(
let fixFoldersAsDynamic = DBConn.createStatement(
"UPDATE moz_bookmarks SET type = :folder_type WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
@ -391,14 +305,14 @@ nsPlacesDBUtils.prototype = {
"WHERE type = :dynamic_type " +
"AND folder_type IS NULL " +
")");
fixFoldersAsDynamic.params["dynamic_type"] = this._bms.TYPE_DYNAMIC_CONTAINER;
fixFoldersAsDynamic.params["folder_type"] = this._bms.TYPE_FOLDER;
fixFoldersAsDynamic.params["dynamic_type"] = PlacesUtils.bookmarks.TYPE_DYNAMIC_CONTAINER;
fixFoldersAsDynamic.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
cleanupStatements.push(fixFoldersAsDynamic);
// D.9 fix wrong parents
// Items cannot have dynamic containers, separators or other bookmarks
// as parent, if they have bad parent move them to unsorted bookmarks.
let fixInvalidParents = this._dbConn.createStatement(
let fixInvalidParents = DBConn.createStatement(
"UPDATE moz_bookmarks SET parent = :unsorted_folder WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
@ -408,10 +322,10 @@ nsPlacesDBUtils.prototype = {
"AND type IN (:bookmark_type, :separator_type, :dynamic_type) " +
"LIMIT 1) " +
")");
fixInvalidParents.params["unsorted_folder"] = this._bms.unfiledBookmarksFolder;
fixInvalidParents.params["bookmark_type"] = this._bms.TYPE_BOOKMARK;
fixInvalidParents.params["separator_type"] = this._bms.TYPE_SEPARATOR;
fixInvalidParents.params["dynamic_type"] = this._bms.TYPE_DYNAMIC_CONTAINER;
fixInvalidParents.params["unsorted_folder"] = PlacesUtils.unfiledBookmarksFolderId;
fixInvalidParents.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
fixInvalidParents.params["separator_type"] = PlacesUtils.bookmarks.TYPE_SEPARATOR;
fixInvalidParents.params["dynamic_type"] = PlacesUtils.bookmarks.TYPE_DYNAMIC_CONTAINER;
cleanupStatements.push(fixInvalidParents);
/* XXX needs test
@ -420,7 +334,7 @@ nsPlacesDBUtils.prototype = {
// We can detect a folder with bad position values comparing the sum of
// all position values with the triangular numbers obtained by the number
// of children: (n * (n + 1) / 2). Starting from 0 is (n * (n - 1) / 2).
let detectWrongPositionsParents = this._dbConn.createStatement(
let detectWrongPositionsParents = DBConn.createStatement(
"SELECT parent FROM " +
"(SELECT parent, " +
"(SUM(position) - (count(*) * (count(*) - 1) / 2)) AS diff " +
@ -431,7 +345,7 @@ nsPlacesDBUtils.prototype = {
let parent = detectWrongPositionsParents.getInt64(0);
// We will lose the previous position values and reposition items based
// on the ROWID value. Not perfect, but we can't rely on position values.
let fixPositionsForParent = this._dbConn.createStatement(
let fixPositionsForParent = DBConn.createStatement(
"UPDATE moz_bookmarks SET position = ( " +
"SELECT " +
"((SELECT count(*) FROM moz_bookmarks WHERE parent = :parent) - " +
@ -448,11 +362,11 @@ nsPlacesDBUtils.prototype = {
// Livemark status items are now static but some livemark has still old
// status items bookmarks inside it. We should remove them.
// Note: This does not need to query the temp table.
let removeLivemarkStaticItems = this._dbConn.createStatement(
let removeLivemarkStaticItems = DBConn.createStatement(
"DELETE FROM moz_bookmarks WHERE type = :bookmark_type AND fk IN ( " +
"SELECT id FROM moz_places WHERE url = :lmloading OR url = :lmfailed " +
")");
removeLivemarkStaticItems.params["bookmark_type"] = this._bms.TYPE_BOOKMARK;
removeLivemarkStaticItems.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
removeLivemarkStaticItems.params["lmloading"] = "about:livemark-loading";
removeLivemarkStaticItems.params["lmfailed"] = "about:livemark-failed";
cleanupStatements.push(removeLivemarkStaticItems);
@ -460,19 +374,19 @@ nsPlacesDBUtils.prototype = {
// D.12 Fix empty-named tags.
// Tags were allowed to have empty names due to a UI bug. Fix them
// replacing their title with "(notitle)".
let fixEmptyNamedTags = this._dbConn.createStatement(
let fixEmptyNamedTags = DBConn.createStatement(
"UPDATE moz_bookmarks SET title = :empty_title " +
"WHERE length(title) = 0 AND type = :folder_type " +
"AND parent = :tags_folder"
);
fixEmptyNamedTags.params["empty_title"] = "(notitle)";
fixEmptyNamedTags.params["folder_type"] = this._bms.TYPE_FOLDER;
fixEmptyNamedTags.params["tags_folder"] = this._bms.tagsFolder;
fixEmptyNamedTags.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
fixEmptyNamedTags.params["tags_folder"] = PlacesUtils.tagsFolderId;
cleanupStatements.push(fixEmptyNamedTags);
// MOZ_FAVICONS
// E.1 remove orphan icons
let deleteOrphanIcons = this._dbConn.createStatement(
let deleteOrphanIcons = DBConn.createStatement(
"DELETE FROM moz_favicons WHERE id IN (" +
"SELECT id FROM moz_favicons f " +
"WHERE NOT EXISTS " +
@ -484,7 +398,7 @@ nsPlacesDBUtils.prototype = {
// MOZ_HISTORYVISITS
// F.1 remove orphan visits
let deleteOrphanVisits = this._dbConn.createStatement(
let deleteOrphanVisits = DBConn.createStatement(
"DELETE FROM moz_historyvisits WHERE id IN (" +
"SELECT id FROM moz_historyvisits v " +
"WHERE NOT EXISTS " +
@ -496,7 +410,7 @@ nsPlacesDBUtils.prototype = {
// MOZ_INPUTHISTORY
// G.1 remove orphan input history
let deleteOrphanInputHistory = this._dbConn.createStatement(
let deleteOrphanInputHistory = DBConn.createStatement(
"DELETE FROM moz_inputhistory WHERE place_id IN (" +
"SELECT place_id FROM moz_inputhistory i " +
"WHERE NOT EXISTS " +
@ -508,7 +422,7 @@ nsPlacesDBUtils.prototype = {
// MOZ_ITEMS_ANNOS
// H.1 remove item annos with an invalid attribute
let deleteInvalidAttributeItemsAnnos = this._dbConn.createStatement(
let deleteInvalidAttributeItemsAnnos = DBConn.createStatement(
"DELETE FROM moz_items_annos WHERE id IN ( " +
"SELECT id FROM moz_items_annos t " +
"WHERE NOT EXISTS " +
@ -518,7 +432,7 @@ nsPlacesDBUtils.prototype = {
cleanupStatements.push(deleteInvalidAttributeItemsAnnos);
// H.2 remove orphan item annos
let deleteOrphanItemsAnnos = this._dbConn.createStatement(
let deleteOrphanItemsAnnos = DBConn.createStatement(
"DELETE FROM moz_items_annos WHERE id IN ( " +
"SELECT id FROM moz_items_annos t " +
"WHERE NOT EXISTS " +
@ -528,7 +442,7 @@ nsPlacesDBUtils.prototype = {
// MOZ_KEYWORDS
// I.1 remove unused keywords
let deleteUnusedKeywords = this._dbConn.createStatement(
let deleteUnusedKeywords = DBConn.createStatement(
"DELETE FROM moz_keywords WHERE id IN ( " +
"SELECT id FROM moz_keywords k " +
"WHERE NOT EXISTS " +
@ -538,7 +452,7 @@ nsPlacesDBUtils.prototype = {
// MOZ_PLACES
// L.1 fix wrong favicon ids
let fixInvalidFaviconIds = this._dbConn.createStatement(
let fixInvalidFaviconIds = DBConn.createStatement(
"UPDATE moz_places SET favicon_id = NULL WHERE id IN ( " +
"SELECT id FROM moz_places h " +
"WHERE favicon_id NOT NULL " +
@ -551,7 +465,7 @@ nsPlacesDBUtils.prototype = {
// L.2 recalculate visit_count
// We're detecting errors only in disk table since temp tables could have
// different values based on the number of visits not yet synced to disk.
let detectWrongCountPlaces = this._dbConn.createStatement(
let detectWrongCountPlaces = DBConn.createStatement(
"SELECT id FROM moz_places h " +
"WHERE id NOT IN (SELECT id FROM moz_places_temp) " +
"AND h.visit_count <> " +
@ -559,7 +473,7 @@ nsPlacesDBUtils.prototype = {
"WHERE place_id = h.id AND visit_type NOT IN (0,4,7,8))");
while (detectWrongCountPlaces.executeStep()) {
let placeId = detectWrongCountPlaces.getInt64(0);
let fixCountForPlace = this._dbConn.createStatement(
let fixCountForPlace = DBConn.createStatement(
"UPDATE moz_places_view SET visit_count = ( " +
"(SELECT count(*) FROM moz_historyvisits " +
"WHERE place_id = :place_id AND visit_type NOT IN (0,4,7,8)) + " +
@ -594,7 +508,7 @@ nsPlacesDBUtils.prototype = {
function integrity() {
let integrityCheckStmt =
self._dbConn.createStatement("PRAGMA integrity_check");
DBConn.createStatement("PRAGMA integrity_check");
log.push("INTEGRITY");
let logIndex = log.length;
while (integrityCheckStmt.executeStep()) {
@ -613,7 +527,7 @@ nsPlacesDBUtils.prototype = {
placesDBFile.append("places.sqlite");
log.push("places.sqlite: " + placesDBFile.fileSize + " byte");
log.push(sep);
let stmt = self._dbConn.createStatement("VACUUM");
let stmt = DBConn.createStatement("VACUUM");
stmt.executeAsync({
handleResult: function() {},
handleError: function() {
@ -645,7 +559,7 @@ nsPlacesDBUtils.prototype = {
function reindex() {
log.push("REINDEX");
self._dbConn.executeSimpleSQL("REINDEX");
DBConn.executeSimpleSQL("REINDEX");
log.push(sep);
}
@ -681,12 +595,12 @@ nsPlacesDBUtils.prototype = {
let placesDBFile = dirSvc.get("ProfD", Ci.nsILocalFile);
placesDBFile.append("places.sqlite");
log.push("places.sqlite: " + placesDBFile.fileSize + " byte");
let stmt = self._dbConn.createStatement(
let stmt = DBConn.createStatement(
"SELECT name FROM sqlite_master WHERE type = :DBType");
stmt.params["DBType"] = "table";
while (stmt.executeStep()) {
let tableName = stmt.getString(0);
let countStmt = self._dbConn.createStatement(
let countStmt = DBConn.createStatement(
"SELECT count(*) FROM " + tableName);
countStmt.executeStep();
log.push(tableName + ": " + countStmt.getInt32(0));

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

@ -2049,14 +2049,6 @@ var PlacesUtils = {
}
},
/**
* Starts the database coherence check and executes update tasks on a timer,
* this method is called by browser.js in delayed startup.
*/
startPlacesDBUtils: function PU_startPlacesDBUtils() {
Cu.import("resource://gre/modules/PlacesDBUtils.jsm");
}
};
XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "history",

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

@ -24,3 +24,8 @@ component {460a9792-b154-4f26-a922-0f653e2c8f91} nsMicrosummaryService.js
contract @mozilla.org/microsummary/service;1 {460a9792-b154-4f26-a922-0f653e2c8f91}
# How often to check for generator updates, in seconds 7 * 86400 == 1 week
category update-timer nsMicrosummaryService @mozilla.org/microsummary/service;1,getService,microsummary-generator-update-timer,browser.microsummary.generatorUpdateInterval,604800
# PlacesCategoriesStarter.js
component {803938d5-e26d-4453-bf46-ad4b26e41114} PlacesCategoriesStarter.js
contract @mozilla.org/places/categoriesStarter;1 {803938d5-e26d-4453-bf46-ad4b26e41114}
category idle-daily PlacesCategoriesStarter @mozilla.org/places/categoriesStarter;1