WebCore:
authorbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Aug 2007 23:08:51 +0000 (23:08 +0000)
committerbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Aug 2007 23:08:51 +0000 (23:08 +0000)
        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: https://svn.webkit.org/repository/webkit/trunk@25081 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
WebCore/ChangeLog
WebCore/WebCore.exp
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/loader/icon/IconDatabase.cpp
WebCore/loader/icon/IconDatabase.h
WebCore/loader/icon/IconDatabaseNone.cpp
WebCore/loader/icon/SQLDatabase.cpp
WebCore/platform/FileSystem.h [new file with mode: 0644]
WebCore/platform/gdk/TemporaryLinkStubs.cpp
WebCore/platform/mac/FileSystemMac.mm [new file with mode: 0644]
WebCore/platform/qt/TemporaryLinkStubs.cpp
WebCore/platform/win/TemporaryLinkStubs.cpp
WebKit/ChangeLog
WebKit/Misc/WebIconDatabase.mm
WebKit/Misc/WebIconDatabasePrivate.h

index 2f9119a0c83a33ad60880ec0e19e1ce74a5f7045..0a363114d0df5e59988382f3852a6c3f68156b40 100644 (file)
@@ -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.
index c8dd1fbc9f64f8e13c20db96c32289a4e74e0da8..5ee513045863f0bf3b379baa96d273f6272d6f43 100644 (file)
@@ -223,6 +223,7 @@ __ZN7WebCore12IconDatabase23defaultDatabaseFilenameEv
 __ZN7WebCore12IconDatabase23isIconExpiredForIconURLERKNS_6StringE
 __ZN7WebCore12IconDatabase23setHaveNoIconForIconURLERKNS_6StringE
 __ZN7WebCore12IconDatabase25setPrivateBrowsingEnabledEb
+__ZN7WebCore12IconDatabase27checkIntegrityBeforeOpeningEv
 __ZN7WebCore12IconDatabase4openERKNS_6StringE
 __ZN7WebCore12IconDatabase5closeEv
 __ZN7WebCore12IconDatabase7isEmptyEv
index df81e479ca2215f7909ce652a4c303849d713a47..eeaf101352327f9b6497a10279a63639c81a4416 100644 (file)
                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, ); }; };
                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>"; };
                                A795463D0B5C4C80007B438F /* DragDataMac.mm */,
                                A7CFB3D40B7ED1180070C32D /* DragImageMac.mm */,
                                066C772C0AB603D200238CC4 /* FileChooserMac.mm */,
+                               514B3F750C722055000530DF /* FileSystemMac.mm */,
                                BCF7C2330A16B5F80032F75B /* FontCacheMac.mm */,
                                BCC088850A1BD78D006189A6 /* FontDataMac.mm */,
                                BCEB377209B7BA3900CB38B1 /* FontMac.mm */,
                                BC073BA90C399B1F000F5979 /* FloatConversion.h */,
                                934FE9E40B5CA539003E4A73 /* FileChooser.cpp */,
                                066C772A0AB603B700238CC4 /* FileChooser.h */,
+                               514B3F720C722047000530DF /* FileSystem.h */,
                                BC6D6DD009AF906600F59759 /* Font.cpp */,
                                BC6D6DD109AF906600F59759 /* Font.h */,
                                BC6DABF20A19015700E5CD14 /* FontCache.cpp */,
                                B402FD0B0C4C9C3900210AA6 /* BidiResolver.h in Headers */,
                                0F31CBF92B654730BA0535E8 /* BidiContext.h in Headers */,
                                1432E8470C51493800B1500F /* GCController.h in Headers */,
+                               514B3F730C722047000530DF /* FileSystem.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                BC2ED6500C6BC48C00920BFF /* JSHTMLIFrameElementCustom.cpp in Sources */,
                                BC2ED6BC0C6BD2F000920BFF /* JSAttrCustom.cpp in Sources */,
                                BC2ED7A50C6C0F3600920BFF /* JSHTMLFrameElementCustom.cpp in Sources */,
+                               514B3F760C722055000530DF /* FileSystemMac.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 0b777acb434798aac180a8500a2eb475e1c656b8..403bcc19bcf68dfce81fcadd4a4ace9e71eb2c61 100644 (file)
@@ -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 missingIconExpirationTime = 60*60*24*7;
 
 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 @@ bool IconDatabase::open(const String& databasePath)
         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 @@ bool IconDatabase::open(const String& databasePath)
         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 @@ void IconDatabase::setImportedQuery(SQLDatabase& db, bool imported)
     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
index 0b71aca841b2b7a84e4b0ca3101f26917b3da625..acbac2800b2acb77dde10145c163235d15f04eeb 100644 (file)
@@ -88,6 +88,12 @@ public:
 
     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();
index 5e70b7226b1d421a71f3904e82ecfe2bb0295eec..177474beddd94600e69367d4e5c5bfef383d0f6a 100644 (file)
@@ -168,4 +168,13 @@ IconDatabase::~IconDatabase()
     ASSERT_NOT_REACHED();
 }
 
+bool IconDatabase::checkIntegrity()
+{
+    return true;
+}
+
+void IconDatabase::checkIntegrityBeforeOpening()
+{
+}
+
 } // namespace WebCore
index 3bda0ef32f114c892b463113ce8183f9ac435163..34f43505f85737a70ed1fcbb15a5d64eb4e5900a 100644 (file)
@@ -49,7 +49,7 @@ bool SQLDatabase::open(const String& filename)
     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 (file)
index 0000000..8477486
--- /dev/null
@@ -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
index 5df55e971a7ec5273bcdc5f700c1e642d8e15ae6..7d8b4e402899e47f3ca54cb69fbcc41c11afd157 100644 (file)
@@ -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 @@ namespace WebCore {
 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 (file)
index 0000000..17010ee
--- /dev/null
@@ -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
index afbfb6c0e610f31dca5864e7da0355f3746fb488..376499ed74f76444ded25647f1824c14a6c6c554 100644 (file)
@@ -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 @@ String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &ch
 
 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
index 135cb016237ac3df034573cc175f3765b6594175..7a4b0f36bedf27b49c073118cb80815f42c510a4 100644 (file)
@@ -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 @@ namespace WebCore {
 
 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(); }
index 1bf75b9b461e2b32dbb3c49f54ae0a3f9ffc4fc4..d104789bb46dd2d228cdb639c34aa54a334d9c0b 100644 (file)
@@ -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.
index 5ab8791705a97e06a325d26d929953f99394b5a8..b1d66eafbc1113bd9a490bcb1fdd567c744b4ed3 100644 (file)
@@ -72,6 +72,7 @@ NSSize WebIconLargeSize = {128, 128};
 - (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 @@ NSSize WebIconLargeSize = {128, 128};
         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 @@ NSSize WebIconLargeSize = {128, 128};
 
 @end
 
+@implementation WebIconDatabase (WebPrivate)
+
++ (void)_checkIntegrityBeforeOpening
+{
+    iconDatabase()->checkIntegrityBeforeOpening();
+}
+
+@end
+
 @implementation WebIconDatabase (WebInternal)
 
 - (BOOL)_isEnabled
@@ -590,6 +595,20 @@ static NSData* iconDataFromPathForIconURL(NSString *databasePath, NSString *icon
         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
index 47c19d8b2c97b84840dcc230ca4052e0c6c4e3af..aff923e9d59ea5142faf963653a9ce6e104d4d02 100644 (file)
@@ -51,3 +51,9 @@ extern NSString *WebIconDatabaseImportDirectoryDefaultsKey;
 
 @end
 
+@interface WebIconDatabase (WebPrivate)
+
++ (void)_checkIntegrityBeforeOpening;
+
+@end
+