WebCore:
Reviewed by Darin, John, Maciej, Oliver, and Tim
<rdar://problem/5394708> - Crash on launch with corrupt icon database
The main part of the fix is to not disable SQLite's default level of protection - to leave the sync options at their normal,
mostly safe levels.
But in case lightning strikes at the exact right moment and someone ends up with a corrupt database, add some support code to
detect that condition and recover from it.
This is mainly accomplished by exposing the "PRAGMA integrity_check;" facilities of sqlite through IconDatabase SPI as well as
running that integrity check if a journal file is detected at launch (a strong indication that the last quit was not clean).
There's also a method exposed to allow clients to tell the icon database "I suspect something bad happened, please check integrity"
* loader/icon/IconDatabase.cpp:
(WebCore::IconDatabase::checkIntegrityBeforeOpening): Allow clients to suggest an integrity check
(WebCore::IconDatabase::open): Add a check to see if the journal file for the database exists. If it does, run the integrity
check. Also run the check if a client has suggested it to be necessary.
If the integrity-check fails, we sadly have to destroy the database and recreate from scratch.
Also - quite importantly - do not adjust the default sync preferences for the SQLDatabase. They were an optimization that
might have been valid at one time but no longer affects any benchmarks we care about.
(WebCore::IconDatabase::checkIntegrity): Perform the SQLite integrity_check pragma
* loader/icon/IconDatabase.h:
* loader/icon/IconDatabaseNone.cpp:
(WebCore::IconDatabase::checkIntegrity): Keep IconDatabaseNone users building
(WebCore::IconDatabase::checkIntegrityBeforeOpening): Ditto
* loader/icon/SQLDatabase.cpp:
(WebCore::SQLDatabase::open): Make a copy of the path string so we don't accidentally mutate anyone else's string on ::close()
* platform/FileSystem.h: Added. Begin a long-needed platform file system abstraction
* platform/mac/FileSystemMac.mm: Added.
(WebCore::fileExists): Check if a file exists
(WebCore::deleteFile): Delete a file
* platform/gdk/TemporaryLinkStubs.cpp:
(WebCore::fileExists):
(WebCore::deleteFile):
* platform/qt/TemporaryLinkStubs.cpp:
(WebCore::fileExists):
(WebCore::deleteFile):
* platform/win/TemporaryLinkStubs.cpp:
(WebCore::fileExists):
(WebCore::deleteFile):
* WebCore.exp:
* WebCore.xcodeproj/project.pbxproj:
WebKit:
Reviewed by Darin, John, Maciej, Oliver, and Tim
<rdar://problem/5394708> - Crash on launch with corrupt icon database
Expose some new SPI to help recover from this case should it happen again
* Misc/WebIconDatabase.mm:
(-[WebIconDatabase init]): Use the new _databaseDirectory to determine where to open the database on disk
(+[WebIconDatabase _checkIntegrityBeforeOpening]): Tell the icon database to check integrity when it opens
(-[WebIconDatabase _databaseDirectory]): Moved the database-directory-determining logic here as it's now used in two places
* Misc/WebIconDatabasePrivate.h: Added _checkIntegrityBeforeOpening SPI for clients to give hints about when the
integrity check should run
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@25081 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 2f9119a..0a36311 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,54 @@
+2007-08-14 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Darin, John, Maciej, Oliver, and Tim
+
+ <rdar://problem/5394708> - Crash on launch with corrupt icon database
+
+ The main part of the fix is to not disable SQLite's default level of protection - to leave the sync options at their normal,
+ mostly safe levels.
+
+ But in case lightning strikes at the exact right moment and someone ends up with a corrupt database, add some support code to
+ detect that condition and recover from it.
+
+ This is mainly accomplished by exposing the "PRAGMA integrity_check;" facilities of sqlite through IconDatabase SPI as well as
+ running that integrity check if a journal file is detected at launch (a strong indication that the last quit was not clean).
+ There's also a method exposed to allow clients to tell the icon database "I suspect something bad happened, please check integrity"
+
+ * loader/icon/IconDatabase.cpp:
+ (WebCore::IconDatabase::checkIntegrityBeforeOpening): Allow clients to suggest an integrity check
+ (WebCore::IconDatabase::open): Add a check to see if the journal file for the database exists. If it does, run the integrity
+ check. Also run the check if a client has suggested it to be necessary.
+ If the integrity-check fails, we sadly have to destroy the database and recreate from scratch.
+ Also - quite importantly - do not adjust the default sync preferences for the SQLDatabase. They were an optimization that
+ might have been valid at one time but no longer affects any benchmarks we care about.
+ (WebCore::IconDatabase::checkIntegrity): Perform the SQLite integrity_check pragma
+ * loader/icon/IconDatabase.h:
+
+ * loader/icon/IconDatabaseNone.cpp:
+ (WebCore::IconDatabase::checkIntegrity): Keep IconDatabaseNone users building
+ (WebCore::IconDatabase::checkIntegrityBeforeOpening): Ditto
+
+ * loader/icon/SQLDatabase.cpp:
+ (WebCore::SQLDatabase::open): Make a copy of the path string so we don't accidentally mutate anyone else's string on ::close()
+
+ * platform/FileSystem.h: Added. Begin a long-needed platform file system abstraction
+ * platform/mac/FileSystemMac.mm: Added.
+ (WebCore::fileExists): Check if a file exists
+ (WebCore::deleteFile): Delete a file
+
+ * platform/gdk/TemporaryLinkStubs.cpp:
+ (WebCore::fileExists):
+ (WebCore::deleteFile):
+ * platform/qt/TemporaryLinkStubs.cpp:
+ (WebCore::fileExists):
+ (WebCore::deleteFile):
+ * platform/win/TemporaryLinkStubs.cpp:
+ (WebCore::fileExists):
+ (WebCore::deleteFile):
+
+ * WebCore.exp:
+ * WebCore.xcodeproj/project.pbxproj:
+
2007-08-14 Jon Honeycutt <jhoneycutt@apple.com>
Reviewed by Steve.
diff --git a/WebCore/WebCore.exp b/WebCore/WebCore.exp
index c8dd1fb..5ee5130 100644
--- a/WebCore/WebCore.exp
+++ b/WebCore/WebCore.exp
@@ -223,6 +223,7 @@
__ZN7WebCore12IconDatabase23isIconExpiredForIconURLERKNS_6StringE
__ZN7WebCore12IconDatabase23setHaveNoIconForIconURLERKNS_6StringE
__ZN7WebCore12IconDatabase25setPrivateBrowsingEnabledEb
+__ZN7WebCore12IconDatabase27checkIntegrityBeforeOpeningEv
__ZN7WebCore12IconDatabase4openERKNS_6StringE
__ZN7WebCore12IconDatabase5closeEv
__ZN7WebCore12IconDatabase7isEmptyEv
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index df81e47..eeaf101 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -333,6 +333,8 @@
513BF1280B4F57DC00CCFECE /* AuthenticationMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 513BF1270B4F57DC00CCFECE /* AuthenticationMac.mm */; };
513F14530AB634C400094DDF /* IconLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 513F14510AB634C400094DDF /* IconLoader.cpp */; };
513F14540AB634C400094DDF /* IconLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 513F14520AB634C400094DDF /* IconLoader.h */; };
+ 514B3F730C722047000530DF /* FileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 514B3F720C722047000530DF /* FileSystem.h */; };
+ 514B3F760C722055000530DF /* FileSystemMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 514B3F750C722055000530DF /* FileSystemMac.mm */; };
5160F3BC0B0A99C900C1D2AF /* CachedPageMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160F3BB0B0A99C900C1D2AF /* CachedPageMac.mm */; };
5160F4980B0AA75F00C1D2AF /* HistoryItemMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160F4970B0AA75F00C1D2AF /* HistoryItemMac.mm */; };
51741D0F0B07259A00ED442C /* BackForwardList.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0B0B07259A00ED442C /* BackForwardList.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3579,6 +3581,8 @@
513F14510AB634C400094DDF /* IconLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IconLoader.cpp; sourceTree = "<group>"; };
513F14520AB634C400094DDF /* IconLoader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IconLoader.h; sourceTree = "<group>"; };
514AF320BE854014A7DA49FB /* BidiContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BidiContext.h; sourceTree = "<group>"; };
+ 514B3F720C722047000530DF /* FileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileSystem.h; sourceTree = "<group>"; };
+ 514B3F750C722055000530DF /* FileSystemMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FileSystemMac.mm; sourceTree = "<group>"; };
5150C2A10702629000AF642C /* WebDashboardRegion.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebDashboardRegion.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
5150C2A50702629800AF642C /* WebDashboardRegion.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebDashboardRegion.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
5160F3BB0B0A99C900C1D2AF /* CachedPageMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CachedPageMac.mm; path = mac/CachedPageMac.mm; sourceTree = "<group>"; };
@@ -7224,6 +7228,7 @@
A795463D0B5C4C80007B438F /* DragDataMac.mm */,
A7CFB3D40B7ED1180070C32D /* DragImageMac.mm */,
066C772C0AB603D200238CC4 /* FileChooserMac.mm */,
+ 514B3F750C722055000530DF /* FileSystemMac.mm */,
BCF7C2330A16B5F80032F75B /* FontCacheMac.mm */,
BCC088850A1BD78D006189A6 /* FontDataMac.mm */,
BCEB377209B7BA3900CB38B1 /* FontMac.mm */,
@@ -9562,6 +9567,7 @@
BC073BA90C399B1F000F5979 /* FloatConversion.h */,
934FE9E40B5CA539003E4A73 /* FileChooser.cpp */,
066C772A0AB603B700238CC4 /* FileChooser.h */,
+ 514B3F720C722047000530DF /* FileSystem.h */,
BC6D6DD009AF906600F59759 /* Font.cpp */,
BC6D6DD109AF906600F59759 /* Font.h */,
BC6DABF20A19015700E5CD14 /* FontCache.cpp */,
@@ -11705,6 +11711,7 @@
B402FD0B0C4C9C3900210AA6 /* BidiResolver.h in Headers */,
0F31CBF92B654730BA0535E8 /* BidiContext.h in Headers */,
1432E8470C51493800B1500F /* GCController.h in Headers */,
+ 514B3F730C722047000530DF /* FileSystem.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -13165,6 +13172,7 @@
BC2ED6500C6BC48C00920BFF /* JSHTMLIFrameElementCustom.cpp in Sources */,
BC2ED6BC0C6BD2F000920BFF /* JSAttrCustom.cpp in Sources */,
BC2ED7A50C6C0F3600920BFF /* JSHTMLFrameElementCustom.cpp in Sources */,
+ 514B3F760C722055000530DF /* FileSystemMac.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/WebCore/loader/icon/IconDatabase.cpp b/WebCore/loader/icon/IconDatabase.cpp
index 0b777ac..403bcc1 100644
--- a/WebCore/loader/icon/IconDatabase.cpp
+++ b/WebCore/loader/icon/IconDatabase.cpp
@@ -27,6 +27,7 @@
#include "IconDatabase.h"
#include "CString.h"
+#include "FileSystem.h"
#include "IconDataCache.h"
#include "Image.h"
#include "Logging.h"
@@ -60,12 +61,19 @@
const int updateTimerDelay = 5;
+static bool checkIntegrityOnOpen = false;
+
const String& IconDatabase::defaultDatabaseFilename()
{
static String defaultDatabaseFilename = "Icons.db";
return defaultDatabaseFilename;
}
+void IconDatabase::checkIntegrityBeforeOpening()
+{
+ checkIntegrityOnOpen = true;
+}
+
IconDatabase* iconDatabase()
{
if (!sharedIconDatabase)
@@ -157,6 +165,10 @@
dbFilename = databasePath + "/" + defaultDatabaseFilename();
#endif
+ String journalFilename = dbFilename + "-journal";
+ if (!checkIntegrityOnOpen)
+ checkIntegrityOnOpen = fileExists(journalFilename);
+
// <rdar://problem/4707718> - If user's Icon directory is unwritable, Safari will crash at startup
// Now, we'll see if we can open the on-disk database. And, if we can't, we'll return false.
// WebKit will then ignore us and act as if the database is disabled
@@ -165,15 +177,29 @@
return false;
}
+ if (checkIntegrityOnOpen) {
+ checkIntegrityOnOpen = false;
+ if (!checkIntegrity()) {
+ LOG(IconDatabase, "Integrity check was bad - dumping IconDatabase");
+ close();
+
+ // Should've been consumed by SQLite, delete just to make sure we don't see it again in the future;
+ deleteFile(journalFilename);
+ deleteFile(dbFilename);
+
+ // Reopen the main database, creating it from scratch
+ if (!m_mainDB.open(dbFilename)) {
+ LOG_ERROR("Unable to open icon database at path %s - %s", dbFilename.ascii().data(), m_mainDB.lastErrorMsg());
+ return false;
+ }
+ }
+ }
+
if (!isValidDatabase(m_mainDB)) {
LOG(IconDatabase, "%s is missing or in an invalid state - reconstructing", dbFilename.ascii().data());
m_mainDB.clearAllTables();
createDatabaseTables(m_mainDB);
}
-
- // These are actually two different SQLite config options - not my fault they are named confusingly ;)
- m_mainDB.setSynchronous(SQLDatabase::SyncOff);
- m_mainDB.setFullsync(false);
// Reduce sqlite RAM cache size from default 2000 pages (~1.5kB per page). 3MB of cache for icon database is overkill
if (!SQLStatement(m_mainDB, "PRAGMA cache_size = 200;").executeCommand())
@@ -1130,4 +1156,35 @@
m_setImportedStatement->reset();
}
+bool IconDatabase::checkIntegrity()
+{
+ SQLStatement integrity(m_mainDB, "PRAGMA integrity_check;");
+ if (integrity.prepare() != SQLResultOk) {
+ LOG_ERROR("checkIntegrity failed to execute");
+ return false;
+ }
+
+ int resultCode = integrity.step();
+ if (resultCode == SQLResultOk)
+ return true;
+
+ if (resultCode != SQLResultRow)
+ return false;
+
+ int columns = integrity.columnCount();
+ if (columns != 1) {
+ LOG_ERROR("Received %i columns performing integrity check, should be 1", columns);
+ return false;
+ }
+
+ String resultText = integrity.getColumnText16(0);
+
+ // A successful, no-error integrity check will be "ok" - all other strings imply failure
+ if (resultText == "ok")
+ return true;
+
+ LOG_ERROR("Icon database integrity check failed - \n%s", resultText.ascii().data());
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/loader/icon/IconDatabase.h b/WebCore/loader/icon/IconDatabase.h
index 0b71aca..acbac28 100644
--- a/WebCore/loader/icon/IconDatabase.h
+++ b/WebCore/loader/icon/IconDatabase.h
@@ -88,6 +88,12 @@
static const String& defaultDatabaseFilename();
+ // For clients to tell the IconDatabase that when it does open it should run the integrity check.
+ // The flag is reset to false after the integrity check is run
+ static void checkIntegrityBeforeOpening();
+
+ bool checkIntegrity();
+
private:
IconDatabase();
~IconDatabase();
diff --git a/WebCore/loader/icon/IconDatabaseNone.cpp b/WebCore/loader/icon/IconDatabaseNone.cpp
index 5e70b72..177474b 100644
--- a/WebCore/loader/icon/IconDatabaseNone.cpp
+++ b/WebCore/loader/icon/IconDatabaseNone.cpp
@@ -168,4 +168,13 @@
ASSERT_NOT_REACHED();
}
+bool IconDatabase::checkIntegrity()
+{
+ return true;
+}
+
+void IconDatabase::checkIntegrityBeforeOpening()
+{
+}
+
} // namespace WebCore
diff --git a/WebCore/loader/icon/SQLDatabase.cpp b/WebCore/loader/icon/SQLDatabase.cpp
index 3bda0ef..34f4350 100644
--- a/WebCore/loader/icon/SQLDatabase.cpp
+++ b/WebCore/loader/icon/SQLDatabase.cpp
@@ -49,7 +49,7 @@
close();
//SQLite expects a null terminator on its UTF16 strings
- m_path = filename;
+ m_path = filename.copy();
m_lastError = sqlite3_open16(m_path.charactersWithNullTermination(), &m_db);
if (m_lastError != SQLITE_OK) {
diff --git a/WebCore/platform/FileSystem.h b/WebCore/platform/FileSystem.h
new file mode 100644
index 0000000..8477486
--- /dev/null
+++ b/WebCore/platform/FileSystem.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FileSystem_h
+#define FileSystem_h
+
+namespace WebCore {
+
+class String;
+
+bool fileExists(const String&);
+bool deleteFile(const String&);
+
+} // namespace WebCore
+
+#endif // FileSystem_h
diff --git a/WebCore/platform/gdk/TemporaryLinkStubs.cpp b/WebCore/platform/gdk/TemporaryLinkStubs.cpp
index 5df55e9..7d8b4e4 100644
--- a/WebCore/platform/gdk/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/gdk/TemporaryLinkStubs.cpp
@@ -41,6 +41,7 @@
#include "EditCommand.h"
#include "Editor.h"
#include "FileChooser.h"
+#include "FileSystem.h"
#include "Font.h"
#include "FrameLoadRequest.h"
#include "FrameLoader.h"
@@ -233,5 +234,7 @@
Vector<String> supportedKeySizes() { notImplemented(); return Vector<String>(); }
String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &challengeString, const KURL &url) { return String(); }
float userIdleTime() { notImplemented(); return 0.0; }
+bool fileExists(const String& path) { notImplemented(); return false; }
+bool deleteFile(const String& path) { notImplemented(); return false; }
}
diff --git a/WebCore/platform/mac/FileSystemMac.mm b/WebCore/platform/mac/FileSystemMac.mm
new file mode 100644
index 0000000..17010ee
--- /dev/null
+++ b/WebCore/platform/mac/FileSystemMac.mm
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#import "config.h"
+#import "FileSystem.h"
+
+#import "PlatformString.h"
+
+namespace WebCore {
+
+bool fileExists(const String& path)
+{
+ const char* fsRep = [(NSString *)path fileSystemRepresentation];
+
+ if (!fsRep || fsRep[0] == '\0')
+ return false;
+
+ struct stat fileInfo;
+
+ // stat(...) returns 0 on successful stat'ing of the file, and non-zero in any case where the file doesn't exist or cannot be accessed
+ return !stat(fsRep, &fileInfo);
+}
+
+bool deleteFile(const String& path)
+{
+ const char* fsRep = [(NSString *)path fileSystemRepresentation];
+
+ if (!fsRep || fsRep[0] == '\0')
+ return false;
+
+ // unlink(...) returns 0 on successful deletion of the path and non-zero in any other case (including invalid permissions or non-existent file)
+ return !unlink(fsRep);
+}
+
+} //namespace WebCore
diff --git a/WebCore/platform/qt/TemporaryLinkStubs.cpp b/WebCore/platform/qt/TemporaryLinkStubs.cpp
index afbfb6c..376499e 100644
--- a/WebCore/platform/qt/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/qt/TemporaryLinkStubs.cpp
@@ -44,6 +44,7 @@
#include "GraphicsContext.h"
#include "Cursor.h"
#include "loader.h"
+#include "FileSystem.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "GlobalHistory.h"
@@ -83,6 +84,9 @@
float userIdleTime() { notImplemented(); return 0.0; }
+bool fileExists(const String& path) { notImplemented(); return false; }
+bool deleteFile(const String& path) { notImplemented(); return false; }
+
}
// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/win/TemporaryLinkStubs.cpp b/WebCore/platform/win/TemporaryLinkStubs.cpp
index 135cb01..7a4b0f3 100644
--- a/WebCore/platform/win/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/win/TemporaryLinkStubs.cpp
@@ -36,6 +36,7 @@
#include "Editor.h"
#include "EventHandler.h"
#include "FileChooser.h"
+#include "FileSystem.h"
#include "Font.h"
#include "FormState.h"
#include "FrameLoader.h"
@@ -88,6 +89,9 @@
void FrameView::updateBorder() { notImplemented(); }
+bool fileExists(const String& path) { notImplemented(); return false; }
+bool deleteFile(const String& path) { notImplemented(); return false; }
+
}
void Widget::setIsSelected(bool) { notImplemented(); }
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 1bf75b9..d104789 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,18 @@
+2007-08-14 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Darin, John, Maciej, Oliver, and Tim
+
+ <rdar://problem/5394708> - Crash on launch with corrupt icon database
+
+ Expose some new SPI to help recover from this case should it happen again
+
+ * Misc/WebIconDatabase.mm:
+ (-[WebIconDatabase init]): Use the new _databaseDirectory to determine where to open the database on disk
+ (+[WebIconDatabase _checkIntegrityBeforeOpening]): Tell the icon database to check integrity when it opens
+ (-[WebIconDatabase _databaseDirectory]): Moved the database-directory-determining logic here as it's now used in two places
+ * Misc/WebIconDatabasePrivate.h: Added _checkIntegrityBeforeOpening SPI for clients to give hints about when the
+ integrity check should run
+
2007-08-12 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin.
diff --git a/WebKit/Misc/WebIconDatabase.mm b/WebKit/Misc/WebIconDatabase.mm
index 5ab8791..b1d66ea 100644
--- a/WebKit/Misc/WebIconDatabase.mm
+++ b/WebKit/Misc/WebIconDatabase.mm
@@ -72,6 +72,7 @@
- (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache;
- (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size;
- (void)_importToWebCoreFormat;
+- (NSString *)_databaseDirectory;
@end
@implementation WebIconDatabase
@@ -104,12 +105,7 @@
return self;
// Figure out the directory we should be using for the icon.db
- NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
- if (!databaseDirectory) {
- databaseDirectory = WebIconDatabasePath;
- [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
- }
- databaseDirectory = [[databaseDirectory stringByExpandingTildeInPath] stringByStandardizingPath];
+ NSString *databaseDirectory = [self _databaseDirectory];
// Rename legacy icon database files to the new icon database name
BOOL isDirectory = NO;
@@ -256,6 +252,15 @@
@end
+@implementation WebIconDatabase (WebPrivate)
+
++ (void)_checkIntegrityBeforeOpening
+{
+ iconDatabase()->checkIntegrityBeforeOpening();
+}
+
+@end
+
@implementation WebIconDatabase (WebInternal)
- (BOOL)_isEnabled
@@ -590,6 +595,20 @@
rmdir([databaseDirectory fileSystemRepresentation]);
}
+- (NSString *)_databaseDirectory
+{
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+
+ // Figure out the directory we should be using for the icon.db
+ NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
+ if (!databaseDirectory) {
+ databaseDirectory = WebIconDatabasePath;
+ [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
+ }
+
+ return [[databaseDirectory stringByExpandingTildeInPath] stringByStandardizingPath];
+}
+
@end
@implementation WebIconDatabasePrivate
diff --git a/WebKit/Misc/WebIconDatabasePrivate.h b/WebKit/Misc/WebIconDatabasePrivate.h
index 47c19d8..aff923e 100644
--- a/WebKit/Misc/WebIconDatabasePrivate.h
+++ b/WebKit/Misc/WebIconDatabasePrivate.h
@@ -51,3 +51,9 @@
@end
+@interface WebIconDatabase (WebPrivate)
+
++ (void)_checkIntegrityBeforeOpening;
+
+@end
+