Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local Storage in WebView is Not Persistent

I'm trying to get local storage to work in a WebView in Cocoa. I used code shown here in another SO question, but it doesn't work properly for me. The local storage is created properly and keeps its contents across reloads, but whenever the application is restarted, the old local storage is immediately deleted.

For example, I created a new project and set up a WebView inside the window. I then put the following code in my AppDelegate.m:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    WebPreferences *prefs = [webView preferences];
    [prefs _setLocalStorageDatabasePath:@"~/Library/Application Support/Test"];
    [prefs setLocalStorageEnabled:YES];

    [webView setMainFrameURL:@"http://static.diveintojavascript.com/files/tutorials/web-storage-contacts/contacts.html"];
}

The local storage is stored properly in the correct folder and stays there even after quitting the app, but when the app is started again the old local storage is deleted and a new file is created.

like image 893
user1055856 Avatar asked Nov 20 '11 00:11

user1055856


People also ask

Does local storage work in WebView?

On Android, LocalStorage works well but only in the current webview. Multiple webviews of the same app can't share the same data with LocalStorage.

Is browser local storage persistent?

localStorage is a property that allows JavaScript sites and apps to save key-value pairs in a web browser with no expiration date. This means the data stored in the browser will persist even after the browser window is closed.

How do I clear local storage in WebView?

Try calling localStorage. clear() in JavaScript to clear localStorage, rather than jerking WebView around by deleting files that it manages.


1 Answers

After a lot of pain and frustration I found a way to enable local storage and have it persist across application runs properly. This solution is specifically for OSX, but it may be applicable to iOS as well.

Download and add this header file into your project. It's not included in the XCode Webkit distribution.

click to download WebStorageManagerPrivate.h

Add to it, the following lines:

static NSString* _storageDirectoryPath();
+ (NSString *)_storageDirectoryPath;

These allow you to retrieve the directory location of the WebKit local storage tracker database. This is important because due to a bug in WebKit, if you don't store your LocalStorage WebView files in the same directory as the tracker database, they are deleted every other time you run your application. I didn't see a way in the WebStorageManager code to change this location for an individual application. It is always read from the user preferences.

Include the WebStorageManagerPrivate.h in your appDelegate.

#include "WebStorageManagerPrivate.h"

You need to download and include in your project another header not included in XCode distribution. Save it as WebPreferencesPrivate.h

click to download WebPreferencesPrivate.h

Include the WebPreferencesPrivate.h in your appDelegate.

#include "WebPreferencesPrivate.h"

Now use the code below in your applicationDidFinishLaunching handler to initialize and enable LocalStorage. The code assumes you have an IBOutlet named 'webView' for the WebView you are using.

    NSString* dbPath = [WebStorageManager _storageDirectoryPath];

    WebPreferences* prefs = [self.webView preferences];
    NSString* localDBPath = [prefs _localStorageDatabasePath];

        // PATHS MUST MATCH!!!!  otherwise localstorage file is erased when starting program
    if( [localDBPath isEqualToString:dbPath] == NO) {
        [prefs setAutosaves:YES];  //SET PREFS AUTOSAVE FIRST otherwise settings aren't saved.
        // Define application cache quota
        static const unsigned long long defaultTotalQuota = 10 * 1024 * 1024; // 10MB
        static const unsigned long long defaultOriginQuota = 5 * 1024 * 1024; // 5MB
        [prefs setApplicationCacheTotalQuota:defaultTotalQuota];
        [prefs setApplicationCacheDefaultOriginQuota:defaultOriginQuota];

        [prefs setWebGLEnabled:YES];
        [prefs setOfflineWebApplicationCacheEnabled:YES];

        [prefs setDatabasesEnabled:YES];
        [prefs setDeveloperExtrasEnabled:[[NSUserDefaults standardUserDefaults] boolForKey: @"developer"]];
#ifdef DEBUG
        [prefs setDeveloperExtrasEnabled:YES];
#endif
        [prefs _setLocalStorageDatabasePath:dbPath];
        [prefs setLocalStorageEnabled:YES];

        [self.webView setPreferences:prefs];
    }

I hope this helps others have struggled or are still struggling with this issue, until it is fixed properly within WebKit.

like image 100
Derek Wade Avatar answered Oct 13 '22 01:10

Derek Wade