From 835638037a6e11cfdf4fd84c4b362465937a5bba Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Wed, 23 Jul 2014 12:26:59 -0400
Subject: [PATCH] Fix errors when using localStorage in Safari's private browsing mode (#1489996)

---
 CHANGELOG         |    1 
 program/js/app.js |   68 +++++++++++++++++++++-------------
 skins/larry/ui.js |   14 ++----
 3 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 2aaaa3f..0047a42 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,6 +3,7 @@
 
 - Enable contextmenu plugin for TinyMCE editor (#1487014)
 - Fix some mime-type to extension mapping checks in Installer (#1489983)
+- Fix errors when using localStorage in Safari's private browsing mode (#1489996)
 
 RELEASE 1.0.2
 -------------
diff --git a/program/js/app.js b/program/js/app.js
index 54eca74..98c4385 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -3162,9 +3162,7 @@
     }
 
     // check for locally stored compose data
-    if (window.localStorage) {
-      this.compose_restore_dialog(0, html_mode)
-    }
+    this.compose_restore_dialog(0, html_mode)
 
     if (input_to.val() == '')
       input_to.focus();
@@ -3782,15 +3780,16 @@
       }
     });
 
-    if (window.localStorage && !empty) {
+    if (!empty) {
       var index = this.local_storage_get_item('compose.index', []),
         key = this.env.compose_id;
 
-        if ($.inArray(key, index) < 0) {
-          index.push(key);
-        }
-        this.local_storage_set_item('compose.' + key, formdata, true);
-        this.local_storage_set_item('compose.index', index);
+      if ($.inArray(key, index) < 0) {
+        index.push(key);
+      }
+
+      this.local_storage_set_item('compose.' + key, formdata, true);
+      this.local_storage_set_item('compose.index', index);
     }
   };
 
@@ -3829,28 +3828,25 @@
   // remove stored compose data from localStorage
   this.remove_compose_data = function(key)
   {
-    if (window.localStorage) {
-      var index = this.local_storage_get_item('compose.index', []);
+    var index = this.local_storage_get_item('compose.index', []);
 
-      if ($.inArray(key, index) >= 0) {
-        this.local_storage_remove_item('compose.' + key);
-        this.local_storage_set_item('compose.index', $.grep(index, function(val,i) { return val != key; }));
-      }
+    if ($.inArray(key, index) >= 0) {
+      this.local_storage_remove_item('compose.' + key);
+      this.local_storage_set_item('compose.index', $.grep(index, function(val,i) { return val != key; }));
     }
   };
 
   // clear all stored compose data of this user
   this.clear_compose_data = function()
   {
-    if (window.localStorage) {
-      var index = this.local_storage_get_item('compose.index', []);
+    var i, index = this.local_storage_get_item('compose.index', []);
 
-      for (var i=0; i < index.length; i++) {
-        this.local_storage_remove_item('compose.' + index[i]);
-      }
-      this.local_storage_remove_item('compose.index');
+    for (i=0; i < index.length; i++) {
+      this.local_storage_remove_item('compose.' + index[i]);
     }
-  }
+
+    this.local_storage_remove_item('compose.index');
+  };
 
 
   this.change_identity = function(obj, show_sig)
@@ -7717,23 +7713,43 @@
   // wrapper for localStorage.getItem(key)
   this.local_storage_get_item = function(key, deflt, encrypted)
   {
+    var item;
 
     // TODO: add encryption
-    var item = localStorage.getItem(this.get_local_storage_prefix() + key);
+    try {
+      item = localStorage.getItem(this.get_local_storage_prefix() + key);
+    }
+    catch (e) { }
+
     return item !== null ? JSON.parse(item) : (deflt || null);
   };
 
   // wrapper for localStorage.setItem(key, data)
   this.local_storage_set_item = function(key, data, encrypted)
   {
-    // TODO: add encryption
-    return localStorage.setItem(this.get_local_storage_prefix() + key, JSON.stringify(data));
+    // try/catch to handle no localStorage support, but also error
+    // in Safari-in-private-browsing-mode where localStorage exists
+    // but can't be used (#1489996)
+    try {
+      // TODO: add encryption
+      localStorage.setItem(this.get_local_storage_prefix() + key, JSON.stringify(data));
+      return true;
+    }
+    catch (e) {
+      return false;
+    }
   };
 
   // wrapper for localStorage.removeItem(key)
   this.local_storage_remove_item = function(key)
   {
-    return localStorage.removeItem(this.get_local_storage_prefix() + key);
+    try {
+      localStorage.removeItem(this.get_local_storage_prefix() + key);
+      return true;
+    }
+    catch (e) {
+      return false;
+    }
   };
 
 }  // end object rcube_webmail
diff --git a/skins/larry/ui.js b/skins/larry/ui.js
index f25c4fc..1c1df08 100644
--- a/skins/larry/ui.js
+++ b/skins/larry/ui.js
@@ -76,7 +76,7 @@
   function get_pref(key)
   {
     if (!prefs) {
-      prefs = window.localStorage ? rcmail.local_storage_get_item('prefs.larry', {}) : {};
+      prefs = rcmail.local_storage_get_item('prefs.larry', {});
     }
 
     // fall-back to cookies
@@ -85,9 +85,8 @@
       if (cookie != null) {
         prefs[key] = cookie;
 
-        // copy value to local storage and remove cookie
-        if (window.localStorage) {
-          rcmail.local_storage_set_item('prefs.larry', prefs);
+        // copy value to local storage and remove cookie (if localStorage is supported)
+        if (rcmail.local_storage_set_item('prefs.larry', prefs)) {
           rcmail.set_cookie(key, cookie, new Date());  // expire cookie
         }
       }
@@ -103,11 +102,8 @@
   {
     prefs[key] = val;
 
-    // write prefs to local storage
-    if (window.localStorage) {
-      rcmail.local_storage_set_item('prefs.larry', prefs);
-    }
-    else {
+    // write prefs to local storage (if supported)
+    if (!rcmail.local_storage_set_item('prefs.larry', prefs)) {
       // store value in cookie
       var exp = new Date();
       exp.setYear(exp.getFullYear() + 1);

--
Gitblit v1.9.1