Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2007-05-04 17:32:25 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2007-05-04 17:32:25 (GMT)
commitbbb96e9c89e6e12fc2a83dc291514ba1859db325 (patch)
tree76767fd2f2789f27b53655c2a8cd45c064a97868
parent2ad2b11d6c2751303495dea85dd74f48cb7191b0 (diff)
Implemented saving web history to the journal. Ifdefed by now while we wait for a patch to be applied to mozilla upstream.
-rw-r--r--browser/GeckoDirectoryProvider.cpp66
-rw-r--r--browser/GeckoDirectoryProvider.h38
-rw-r--r--browser/Makefile.am12
-rw-r--r--browser/sessionstore/Makefile.am34
-rw-r--r--browser/sessionstore/nsISessionStore.idl63
-rw-r--r--browser/sessionstore/nsSessionStore.js541
-rw-r--r--browser/sugar-browser.cpp100
-rw-r--r--browser/sugar-browser.h4
-rw-r--r--configure.ac30
-rw-r--r--sugar/browser/_sugarbrowser.defs15
10 files changed, 875 insertions, 28 deletions
diff --git a/browser/GeckoDirectoryProvider.cpp b/browser/GeckoDirectoryProvider.cpp
new file mode 100644
index 0000000..c94a7cf
--- /dev/null
+++ b/browser/GeckoDirectoryProvider.cpp
@@ -0,0 +1,66 @@
+#include "GeckoDirectoryProvider.h"
+
+#include <nsCOMPtr.h>
+#include <nsIIOService.h>
+#include <nsNetUtil.h>
+#include <nsArrayEnumerator.h>
+#include <nsILocalFile.h>
+#include <nsDirectoryServiceDefs.h>
+#include <nsIToolkitChromeRegistry.h>
+#include <nsIDirectoryService.h>
+#include <nsCOMArray.h>
+
+#include <glib.h>
+
+NS_IMPL_ISUPPORTS2 (GeckoDirectoryProvider,
+ nsIDirectoryServiceProvider,
+ nsIDirectoryServiceProvider2)
+
+GeckoDirectoryProvider::GeckoDirectoryProvider(const char *sugar_path)
+{
+ mComponentPath = g_strconcat(sugar_path, "/mozilla/components", NULL);
+}
+
+GeckoDirectoryProvider::~GeckoDirectoryProvider()
+{
+ if(mComponentPath)
+ g_free(mComponentPath);
+}
+
+/* nsIFile getFile (in string prop, out PRBool persistent); */
+NS_IMETHODIMP
+GeckoDirectoryProvider::GetFile (const char *prop,
+ PRBool *persistent,
+ nsIFile **_retval)
+{
+ return NS_ERROR_FAILURE;
+}
+
+/* nsISimpleEnumerator getFiles (in string aProperty); */
+NS_IMETHODIMP
+GeckoDirectoryProvider::GetFiles (const char *aProperty, nsISimpleEnumerator **aResult)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (!strcmp(aProperty, NS_XPCOM_COMPONENT_DIR_LIST)) {
+ if (mComponentPath) {
+ nsCOMPtr<nsILocalFile> componentDir;
+ rv = NS_NewNativeLocalFile(nsDependentCString(mComponentPath),
+ PR_TRUE,
+ getter_AddRefs (componentDir));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMArray<nsIFile> array;
+
+ rv = array.AppendObject (componentDir);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = NS_NewArrayEnumerator (aResult, array);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = NS_SUCCESS_AGGREGATE_RESULT;
+ }
+ }
+
+ return rv;
+}
diff --git a/browser/GeckoDirectoryProvider.h b/browser/GeckoDirectoryProvider.h
new file mode 100644
index 0000000..5b74169
--- /dev/null
+++ b/browser/GeckoDirectoryProvider.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007, One Laptop Per Child
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef GECKO_DIRECTORY_PROVIDER_H
+#define GECKO_DIRECTORY_PROVIDER_H
+
+#include <nsIDirectoryService.h>
+
+class GeckoDirectoryProvider : public nsIDirectoryServiceProvider2
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+ GeckoDirectoryProvider(const char *sugar_path);
+ virtual ~GeckoDirectoryProvider();
+
+ private:
+ char *mComponentPath;
+};
+
+#endif /* GECKO_DIRECTORY_PROVIDER_H */
diff --git a/browser/Makefile.am b/browser/Makefile.am
index b418583..9a7e4b0 100644
--- a/browser/Makefile.am
+++ b/browser/Makefile.am
@@ -1,9 +1,13 @@
+SUBDIRS = sessionstore
+
libsugarbrowser_la_CPPFLAGS = \
$(WARN_CFLAGS) \
$(LIB_CFLAGS) \
$(GECKO_CFLAGS) \
$(NSPR_CFLAGS) \
- -I$(MOZILLA_INCLUDE_DIR)/commandhandler \
+ -I$(MOZILLA_INCLUDE_DIR)/chrome \
+ -I$(MOZILLA_INCLUDE_DIR)/commandhandler \
+ -I$(MOZILLA_INCLUDE_DIR)/content \
-I$(MOZILLA_INCLUDE_DIR)/dom \
-I$(MOZILLA_INCLUDE_DIR)/docshell \
-I$(MOZILLA_INCLUDE_DIR)/exthandler \
@@ -35,8 +39,10 @@ libsugarbrowser_la_SOURCES = \
GeckoContentHandler.cpp \
GeckoDocumentObject.h \
GeckoDocumentObject.cpp \
- GeckoDragDropHooks.h \
- GeckoDragDropHooks.cpp \
+ GeckoDirectoryProvider.h \
+ GeckoDirectoryProvider.cpp \
+ GeckoDragDropHooks.h \
+ GeckoDragDropHooks.cpp \
GeckoDownload.h \
GeckoDownload.cpp \
sugar-address-entry.c \
diff --git a/browser/sessionstore/Makefile.am b/browser/sessionstore/Makefile.am
new file mode 100644
index 0000000..3c9a055
--- /dev/null
+++ b/browser/sessionstore/Makefile.am
@@ -0,0 +1,34 @@
+sessionstoredir = $(pkgdatadir)/mozilla/components
+
+sessionstore_DATA = \
+ nsISessionStore.xpt \
+ nsSessionStore.js
+
+EXTRA_DIST = $(sessionstore_DATA)
+
+BUILT_SOURCES = \
+ nsISessionStore.xpt \
+ nsISessionStore.h
+
+stamp_files = \
+ stamp-nsISessionStore.xpt \
+ stamp-nsISessionStore.h
+
+nsISessionStore.xpt: stamp-nsISessionStore.xpt
+ @true
+stamp-nsISessionStore.xpt: nsISessionStore.idl
+ $(XPIDL) -m typelib -w -v -I $(MOZILLA_IDL_DIR) -e nsISessionStore.xpt \
+ nsISessionStore.idl \
+ && echo timestamp > $(@F)
+
+nsISessionStore.h: stamp-nsISessionStore.h
+ @true
+stamp-nsISessionStore.h: nsISessionStore.idl
+ $(XPIDL) -m header -w -v -I $(MOZILLA_IDL_DIR) -e nsISessionStore.h \
+ nsISessionStore.idl \
+ && echo timestamp > $(@F)
+
+CLEANFILES = $(stamp_files) $(BUILT_SOURCES)
+DISTCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
+MAINTAINERCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
+
diff --git a/browser/sessionstore/nsISessionStore.idl b/browser/sessionstore/nsISessionStore.idl
new file mode 100644
index 0000000..97f9668
--- /dev/null
+++ b/browser/sessionstore/nsISessionStore.idl
@@ -0,0 +1,63 @@
+/* ***** 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 the Session Restore component.
+ *
+ * The Initial Developer of the Original Code is
+ * Simon Bünzli <zeniko@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dietrich Ayala <dietrich@mozilla.com>
+ *
+ * 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 ***** */
+
+#include "nsISupports.idl"
+
+interface nsIWebBrowser;
+
+/**
+ * nsISessionStore keeps track of the current browsing state - i.e.
+ * tab history, cookies, scroll state, form data, POSTDATA and window features
+ * - and allows to restore everything into one window.
+ */
+
+[scriptable, uuid(11852a90-20de-11db-a98b-0800200c9a66)]
+interface nsISessionStore : nsISupports
+{
+ /**
+ * @param aBrowser is the browser whose state is to be returned.
+ *
+ * @return a JSON string representing the session state.
+ */
+ AString getBrowserState(in nsIWebBrowser aBrowser);
+
+ /**
+ * @param aBrowser is the browser whose state is to be set.
+ * @param aState is a JSON string representing a session state.
+ */
+ void setBrowserState(in nsIWebBrowser aBrowser, in AString aState);
+};
diff --git a/browser/sessionstore/nsSessionStore.js b/browser/sessionstore/nsSessionStore.js
new file mode 100644
index 0000000..0ce3401
--- /dev/null
+++ b/browser/sessionstore/nsSessionStore.js
@@ -0,0 +1,541 @@
+/* ***** 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 the nsSessionStore component.
+ *
+ * The Initial Developer of the Original Code is
+ * Simon Bünzli <zeniko@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dietrich Ayala <autonome@gmail.com>
+ *
+ * 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 ***** */
+
+/*
+ * Heavily adapted to xulrunner for the OLPC from the firefox code in
+ * http://lxr.mozilla.org/seamonkey/source/browser/components/sessionstore.
+ *
+ * May 2007 Tomeu Vizoso
+ */
+
+/**
+ * Session Storage and Restoration
+ *
+ * Overview
+ * This service keeps track of a user's session, storing the various bits
+ * required to return the browser to it's current state. The relevant data is
+ * stored in memory, and is periodically saved to disk in a file in the
+ * profile directory. The service is started at first window load, in
+ * delayedStartup, and will restore the session from the data received from
+ * the nsSessionStartup service.
+ */
+
+/* :::::::: Constants and Helpers ::::::::::::::: */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+const CID = Components.ID("{5280606b-2510-4fe0-97ef-9b5a22eafe6b}");
+const CONTRACT_ID = "@mozilla.org/browser/sessionstore;1";
+const CLASS_NAME = "Browser Session Store Service";
+
+// sandbox to evaluate JavaScript code from non-trustable sources
+var EVAL_SANDBOX = new Components.utils.Sandbox("about:blank");
+
+function debug(aMsg) {
+ aMsg = ("SessionStore: " + aMsg).replace(/\S{80}/g, "$&\n");
+ Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
+ .logStringMessage(aMsg);
+}
+
+/* :::::::: The Service ::::::::::::::: */
+
+function SessionStoreService() {
+}
+
+SessionStoreService.prototype = {
+
+/* ........ nsISessionStore API .............. */
+
+ getBrowserState: function sss_getBrowserState(aBrowser) {
+ dump("nsSessionStore::getBrowserState\n")
+ return this._toJSONString(this._getWindowState(aBrowser));
+ },
+
+ setBrowserState: function sss_setBrowserState(aBrowser, aState) {
+ dump("nsSessionStore::setBrowserState\n")
+ this.restoreWindow(aBrowser, "(" + aState + ")");
+ },
+
+/* ........ Saving Functionality .............. */
+
+ /**
+ * Store all session data for a window
+ * @param aSHistory
+ * nsISHistory reference
+ */
+ _saveWindowHistory: function sss_saveWindowHistory(aSHistory) {
+ var entries = [];
+ dump("nsSessionStore._saveWindowHistory " + aSHistory.count);
+ for (var i = 0; i < aSHistory.count; i++) {
+ entries.push(this._serializeHistoryEntry(aSHistory.getEntryAtIndex(i, false)));
+ }
+
+ return entries;
+ },
+
+ /**
+ * Get an object that is a serialized representation of a History entry
+ * Used for data storage
+ * @param aEntry
+ * nsISHEntry instance
+ * @returns object
+ */
+ _serializeHistoryEntry: function sss_serializeHistoryEntry(aEntry) {
+ var entry = { url: aEntry.URI.spec, children: [] };
+
+ if (aEntry.title && aEntry.title != entry.url) {
+ entry.title = aEntry.title;
+ }
+ if (aEntry.isSubFrame) {
+ entry.subframe = true;
+ }
+ if (!(aEntry instanceof Ci.nsISHEntry)) {
+ return entry;
+ }
+
+ var cacheKey = aEntry.cacheKey;
+ if (cacheKey && cacheKey instanceof Ci.nsISupportsPRUint32) {
+ entry.cacheKey = cacheKey.data;
+ }
+ entry.ID = aEntry.ID;
+
+ var x = {}, y = {};
+ aEntry.getScrollPosition(x, y);
+ entry.scroll = x.value + "," + y.value;
+
+ try {
+ var prefPostdata = this._prefBranch.getIntPref("sessionstore.postdata");
+ if (prefPostdata && aEntry.postData && this._checkPrivacyLevel(aEntry.URI.schemeIs("https"))) {
+ aEntry.postData.QueryInterface(Ci.nsISeekableStream).
+ seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
+ var stream = Cc["@mozilla.org/scriptableinputstream;1"].
+ createInstance(Ci.nsIScriptableInputStream);
+ stream.init(aEntry.postData);
+ var postdata = stream.read(stream.available());
+ if (prefPostdata == -1 || postdata.replace(/^(Content-.*\r\n)+(\r\n)*/, "").length <= prefPostdata) {
+ entry.postdata = postdata;
+ }
+ }
+ }
+ catch (ex) { debug(ex); } // POSTDATA is tricky - especially since some extensions don't get it right
+
+ if (!(aEntry instanceof Ci.nsISHContainer)) {
+ return entry;
+ }
+
+ for (var i = 0; i < aEntry.childCount; i++) {
+ var child = aEntry.GetChildAt(i);
+ if (child) {
+ entry.children.push(this._serializeHistoryEntry(child));
+ }
+ else { // to maintain the correct frame order, insert a dummy entry
+ entry.children.push({ url: "about:blank" });
+ }
+ }
+
+ return entry;
+ },
+
+ /**
+ * serialize session data for a window
+ * @param aBrowser
+ * Browser reference
+ * @returns string
+ */
+ _getWindowState: function sss_getWindowState(aBrowser) {
+ dump("nsSessionStore::_getWindowState: " + aBrowser + "\n")
+ windowState = this._collectWindowData(aBrowser);
+
+ /*
+ this._updateCookies(windowState);
+ */
+
+ return windowState;
+ },
+
+ _collectWindowData: function sss_collectWindowData(aBrowser) {
+ dump("nsSessionStore::_collectWindowData\n")
+ aBrowser.QueryInterface(Ci.nsIWebNavigation);
+ historyState = this._saveWindowHistory(aBrowser.sessionHistory);
+ /*
+ this._updateTextAndScrollData(aWindow);
+ this._updateCookieHosts(aWindow);
+ this._updateWindowFeatures(aWindow);
+ */
+
+ return {history: historyState/*, textAndScroll: textAndScrollState*/};
+ },
+
+/* ........ Restoring Functionality .............. */
+
+ /**
+ * restore features to a single window
+ * @param aBrowser
+ * Browser reference
+ * @param aState
+ * JS object or its eval'able source
+ */
+ restoreWindow: function sss_restoreWindow(aBrowser, aState) {
+ try {
+ var winData = typeof aState == "string" ? this._safeEval(aState) : aState;
+ }
+ catch (ex) { // invalid state object - don't restore anything
+ debug(ex);
+ dump(ex);
+ return;
+ }
+
+ this.restoreHistoryPrecursor(aBrowser, winData.history);
+ },
+
+ /**
+ * Manage history restoration for a window
+ * @param aBrowser
+ * Browser reference
+ * @param aHistoryData
+ * History data to be restored
+ */
+ restoreHistoryPrecursor: function sss_restoreHistoryPrecursor(aBrowser, aHistoryData) {
+ /*
+ // make sure that all browsers and their histories are available
+ // - if one's not, resume this check in 100ms (repeat at most 10 times)
+ for (var t = aIx; t < aTabs.length; t++) {
+ try {
+ if (!tabbrowser.getBrowserForTab(aTabs[t]._tab).webNavigation.sessionHistory) {
+ throw new Error();
+ }
+ }
+ catch (ex) { // in case browser or history aren't ready yet
+ if (aCount < 10) {
+ var restoreHistoryFunc = function(self) {
+ self.restoreHistoryPrecursor(aWindow, aTabs, aSelectTab, aIx, aCount + 1);
+ }
+ aWindow.setTimeout(restoreHistoryFunc, 100, this);
+ return;
+ }
+ }
+ }
+ */
+
+ // helper hash for ensuring unique frame IDs
+ var aIdMap = { used: {} };
+ this.restoreHistory(aBrowser, aHistoryData, aIdMap);
+ },
+
+ /**
+ * Restory history for a window
+ * @param aBrowser
+ * Browser reference
+ * @param aHistoryData
+ * History data to be restored
+ * @param aIdMap
+ * Hash for ensuring unique frame IDs
+ */
+ restoreHistory: function sss_restoreHistory(aBrowser, aHistoryData, aIdMap) {
+ dump("nsSessionStore::restoreHistory\n")
+
+ aBrowser.QueryInterface(Ci.nsIWebNavigation);
+ aSHistory = aBrowser.sessionHistory;
+ aSHistory.QueryInterface(Ci.nsISHistoryInternal);
+
+ if (aSHistory.count > 0) {
+ aSHistory.PurgeHistory(aSHistory.count);
+ }
+
+ if (!aHistoryData) {
+ aHistoryData = [];
+ }
+
+ for (var i = 0; i < aHistoryData.length; i++) {
+ aSHistory.addEntry(this._deserializeHistoryEntry(aHistoryData[i], aIdMap), true);
+ }
+
+ /*
+ // make sure to reset the capabilities and attributes, in case this tab gets reused
+ var disallow = (aHistoryData.disallow)?aHistoryData.disallow.split(","):[];
+ CAPABILITIES.forEach(function(aCapability) {
+ browser.docShell["allow" + aCapability] = disallow.indexOf(aCapability) == -1;
+ });
+ Array.filter(tab.attributes, function(aAttr) {
+ return (_this.xulAttributes.indexOf(aAttr.name) > -1);
+ }).forEach(tab.removeAttribute, tab);
+ if (aHistoryData.xultab) {
+ aHistoryData.xultab.split(" ").forEach(function(aAttr) {
+ if (/^([^\s=]+)=(.*)/.test(aAttr)) {
+ tab.setAttribute(RegExp.$1, decodeURI(RegExp.$2));
+ }
+ });
+ }
+ */
+ try {
+ aBrowser.gotoIndex(aHistoryData.length - 1);
+ }
+ catch (ex) { dump(ex + "\n"); } // ignore an invalid aHistoryData.index
+ },
+
+ /**
+ * expands serialized history data into a session-history-entry instance
+ * @param aEntry
+ * Object containing serialized history data for a URL
+ * @param aIdMap
+ * Hash for ensuring unique frame IDs
+ * @returns nsISHEntry
+ */
+ _deserializeHistoryEntry: function sss_deserializeHistoryEntry(aEntry, aIdMap) {
+ var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
+ createInstance(Ci.nsISHEntry);
+
+ var ioService = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+ shEntry.setURI(ioService.newURI(aEntry.url, null, null));
+ shEntry.setTitle(aEntry.title || aEntry.url);
+ shEntry.setIsSubFrame(aEntry.subframe || false);
+ shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
+
+ if (aEntry.cacheKey) {
+ var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
+ createInstance(Ci.nsISupportsPRUint32);
+ cacheKey.data = aEntry.cacheKey;
+ shEntry.cacheKey = cacheKey;
+ }
+ if (aEntry.ID) {
+ // get a new unique ID for this frame (since the one from the last
+ // start might already be in use)
+ var id = aIdMap[aEntry.ID] || 0;
+ if (!id) {
+ for (id = Date.now(); aIdMap.used[id]; id++);
+ aIdMap[aEntry.ID] = id;
+ aIdMap.used[id] = true;
+ }
+ shEntry.ID = id;
+ }
+
+ var scrollPos = (aEntry.scroll || "0,0").split(",");
+ scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
+ shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
+
+ if (aEntry.postdata) {
+ var stream = Cc["@mozilla.org/io/string-input-stream;1"].
+ createInstance(Ci.nsIStringInputStream);
+ stream.setData(aEntry.postdata, -1);
+ shEntry.postData = stream;
+ }
+
+ if (aEntry.children && shEntry instanceof Ci.nsISHContainer) {
+ for (var i = 0; i < aEntry.children.length; i++) {
+ shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap), i);
+ }
+ }
+
+ return shEntry;
+ },
+
+/* ........ Auxiliary Functions .............. */
+
+ /**
+ * don't save sensitive data if the user doesn't want to
+ * (distinguishes between encrypted and non-encrypted sites)
+ * @param aIsHTTPS
+ * Bool is encrypted
+ * @returns bool
+ */
+ _checkPrivacyLevel: function sss_checkPrivacyLevel(aIsHTTPS) {
+ return this._prefBranch.getIntPref("sessionstore.privacy_level") < (aIsHTTPS ? PRIVACY_ENCRYPTED : PRIVACY_FULL);
+ },
+
+ /**
+ * safe eval'ing
+ */
+ _safeEval: function sss_safeEval(aStr) {
+ return Components.utils.evalInSandbox(aStr, EVAL_SANDBOX);
+ },
+
+ /**
+ * Converts a JavaScript object into a JSON string
+ * (see http://www.json.org/ for the full grammar).
+ *
+ * The inverse operation consists of eval("(" + JSON_string + ")");
+ * and should be provably safe.
+ *
+ * @param aJSObject is the object to be converted
+ * @return the object's JSON representation
+ */
+ _toJSONString: function sss_toJSONString(aJSObject) {
+ // these characters have a special escape notation
+ const charMap = { "\b": "\\b", "\t": "\\t", "\n": "\\n", "\f": "\\f",
+ "\r": "\\r", '"': '\\"', "\\": "\\\\" };
+ // we use a single string builder for efficiency reasons
+ var parts = [];
+
+ // this recursive function walks through all objects and appends their
+ // JSON representation to the string builder
+ function jsonIfy(aObj) {
+ if (typeof aObj == "boolean") {
+ parts.push(aObj ? "true" : "false");
+ }
+ else if (typeof aObj == "number" && isFinite(aObj)) {
+ // there is no representation for infinite numbers or for NaN!
+ parts.push(aObj.toString());
+ }
+ else if (typeof aObj == "string") {
+ aObj = aObj.replace(/[\\"\x00-\x1F\u0080-\uFFFF]/g, function($0) {
+ // use the special escape notation if one exists, otherwise
+ // produce a general unicode escape sequence
+ return charMap[$0] ||
+ "\\u" + ("0000" + $0.charCodeAt(0).toString(16)).slice(-4);
+ });
+ parts.push('"' + aObj + '"')
+ }
+ else if (aObj == null) {
+ parts.push("null");
+ }
+ else if (aObj instanceof Array || aObj instanceof EVAL_SANDBOX.Array) {
+ parts.push("[");
+ for (var i = 0; i < aObj.length; i++) {
+ jsonIfy(aObj[i]);
+ parts.push(",");
+ }
+ if (parts[parts.length - 1] == ",")
+ parts.pop(); // drop the trailing colon
+ parts.push("]");
+ }
+ else if (typeof aObj == "object") {
+ parts.push("{");
+ for (var key in aObj) {
+ jsonIfy(key.toString());
+ parts.push(":");
+ jsonIfy(aObj[key]);
+ parts.push(",");
+ }
+ if (parts[parts.length - 1] == ",")
+ parts.pop(); // drop the trailing colon
+ parts.push("}");
+ }
+ else {
+ throw new Error("No JSON representation for this object!");
+ }
+ }
+ jsonIfy(aJSObject);
+
+ var newJSONString = parts.join(" ");
+ // sanity check - so that API consumers can just eval this string
+ if (/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
+ newJSONString.replace(/"(\\.|[^"\\])*"/g, "")
+ ))
+ throw new Error("JSON conversion failed unexpectedly!");
+
+ return newJSONString;
+ },
+
+/* ........ QueryInterface .............. */
+
+ QueryInterface: function(aIID) {
+ if (!aIID.equals(Ci.nsISupports) &&
+ !aIID.equals(Ci.nsIObserver) &&
+ !aIID.equals(Ci.nsISupportsWeakReference) &&
+ !aIID.equals(Ci.nsIDOMEventListener) &&
+ !aIID.equals(Ci.nsISessionStore)) {
+ Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
+ return null;
+ }
+
+ return this;
+ }
+};
+
+/* :::::::: Service Registration & Initialization ::::::::::::::: */
+
+/* ........ nsIModule .............. */
+
+const SessionStoreModule = {
+
+ getClassObject: function(aCompMgr, aCID, aIID) {
+ if (aCID.equals(CID)) {
+ return SessionStoreFactory;
+ }
+
+ Components.returnCode = Cr.NS_ERROR_NOT_REGISTERED;
+ return null;
+ },
+
+ registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) {
+ aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
+ aCompMgr.registerFactoryLocation(CID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
+ },
+
+ unregisterSelf: function(aCompMgr, aLocation, aType) {
+ aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
+ aCompMgr.unregisterFactoryLocation(CID, aLocation);
+ },
+
+ canUnload: function(aCompMgr) {
+ return true;
+ }
+}
+
+/* ........ nsIFactory .............. */
+
+const SessionStoreFactory = {
+
+ createInstance: function(aOuter, aIID) {
+ if (aOuter != null) {
+ Components.returnCode = Cr.NS_ERROR_NO_AGGREGATION;
+ return null;
+ }
+
+ return (new SessionStoreService()).QueryInterface(aIID);
+ },
+
+ lockFactory: function(aLock) { },
+
+ QueryInterface: function(aIID) {
+ if (!aIID.equals(Ci.nsISupports) && !aIID.equals(Ci.nsIModule) &&
+ !aIID.equals(Ci.nsIFactory) && !aIID.equals(Ci.nsISessionStore)) {
+ Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
+ return null;
+ }
+
+ return this;
+ }
+};
+
+function NSGetModule(aComMgr, aFileSpec) {
+ dump("nsSessionStore: NSGetModule\n")
+ return SessionStoreModule;
+}
diff --git a/browser/sugar-browser.cpp b/browser/sugar-browser.cpp
index df5769b..f3a3d87 100644
--- a/browser/sugar-browser.cpp
+++ b/browser/sugar-browser.cpp
@@ -28,6 +28,7 @@
#include "GeckoDragDropHooks.h"
#include "GeckoDocumentObject.h"
#include "GeckoBrowserPersist.h"
+#include "GeckoDirectoryProvider.h"
#endif
#include <gdk/gdkx.h>
@@ -65,6 +66,8 @@
#include <nsICommandManager.h>
#include <nsIClipboardDragDropHooks.h>
+#include "sessionstore/nsISessionStore.h"
+
#define SUGAR_PATH "SUGAR_PATH"
enum {
@@ -156,6 +159,25 @@ sugar_browser_startup(const char *profile_path, const char *profile_name)
old_handler = XSetErrorHandler(error_handler);
+ #if 0
+ GeckoDirectoryProvider *dirProvider =
+ new GeckoDirectoryProvider(g_getenv(SUGAR_PATH));
+ if (!dirProvider) {
+ g_warning ("failed to create GeckoDirectoryProvider");
+ return FALSE;
+ }
+
+ NS_ADDREF (dirProvider);
+
+ nsCOMPtr<nsIDirectoryServiceProvider> dp (do_QueryInterface (dirProvider));
+ NS_RELEASE (dirProvider);
+ dirProvider = nsnull;
+
+ if (!dp) return FALSE;
+
+ gtk_moz_embed_set_directory_service_provider(dp);
+ #endif
+
gtk_moz_embed_push_startup();
nsCOMPtr<nsIPrefService> prefService;
@@ -354,10 +376,10 @@ sugar_browser_realize(GtkWidget *widget)
GTK_WIDGET_CLASS(parent_class)->realize(widget);
#ifdef HAVE_NS_WEB_BROWSER
- GtkMozEmbed *embed = GTK_MOZ_EMBED(widget);
- nsCOMPtr<nsIWebBrowser> webBrowser;
- gtk_moz_embed_get_nsIWebBrowser(embed, getter_AddRefs(webBrowser));
- NS_ENSURE_TRUE(webBrowser, );
+ GtkMozEmbed *embed = GTK_MOZ_EMBED(widget);
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser(embed, getter_AddRefs(webBrowser));
+ NS_ENSURE_TRUE(webBrowser, );
nsCOMPtr<nsICommandManager> commandManager = do_GetInterface(webBrowser);
if (commandManager) {
@@ -732,6 +754,76 @@ sugar_browser_save_document(SugarBrowser *browser,
#endif
}
+char *
+sugar_browser_get_session(SugarBrowser *browser)
+{
+#if 0
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
+ getter_AddRefs(webBrowser));
+ if (!webBrowser) {
+ g_warning ("failed to get nsIWebBrowser");
+ return NULL;
+ }
+
+ nsCOMPtr<nsISessionStore> sessionStore;
+ sessionStore = do_GetService("@mozilla.org/browser/sessionstore;1");
+ if (!sessionStore) {
+ g_warning ("failed to get nsISessionStore");
+ return NULL;
+ }
+
+ nsString session;
+ nsresult rv = sessionStore->GetBrowserState(webBrowser, session);
+ if (NS_FAILED(rv)) {
+ g_warning ("failed to get browser state");
+ return NULL;
+ }
+
+ nsCString sessionUTF8;
+ NS_UTF16ToCString (session, NS_CSTRING_ENCODING_UTF8, sessionUTF8);
+
+ return g_strdup(sessionUTF8.get());
+#else
+ return NULL;
+#endif
+}
+
+gboolean
+sugar_browser_set_session(SugarBrowser *browser,
+ const char *session)
+{
+#if 0
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
+ getter_AddRefs(webBrowser));
+ if (!webBrowser) {
+ g_warning ("failed to get nsIWebBrowser");
+ return FALSE;
+ }
+
+ nsCOMPtr<nsISessionStore> sessionStore;
+ sessionStore = do_GetService("@mozilla.org/browser/sessionstore;1");
+ if (!sessionStore) {
+ g_warning ("failed to get nsISessionStore");
+ return FALSE;
+ }
+
+ nsCString sessionUTF8(session);
+ nsString sessionUTF16;
+ NS_CStringToUTF16(sessionUTF8, NS_CSTRING_ENCODING_UTF8, sessionUTF16);
+ nsresult rv = sessionStore->SetBrowserState(webBrowser, sessionUTF16);
+ if (NS_FAILED(rv)) {
+ g_warning ("failed to set browser state");
+ return FALSE;
+ }
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
GType
sugar_browser_event_get_type(void)
{
diff --git a/browser/sugar-browser.h b/browser/sugar-browser.h
index 43108ec..ab74a12 100644
--- a/browser/sugar-browser.h
+++ b/browser/sugar-browser.h
@@ -74,6 +74,10 @@ gboolean sugar_browser_startup (const char *profile_path,
const char *profile_name);
void sugar_browser_shutdown (void);
+char *sugar_browser_get_session (SugarBrowser *browser);
+gboolean sugar_browser_set_session (SugarBrowser *browser,
+ const char *session);
+
#define SUGAR_TYPE_BROWSER_EVENT (sugar_browser_event_get_type())
struct _SugarBrowserEvent {
diff --git a/configure.ac b/configure.ac
index f35f660..7bcdf0c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,11 +19,11 @@ AC_PROG_LIBTOOL
AC_ARG_ENABLE(ns-web-browser,
AC_HELP_STRING([--enable-ns-web-browser],
[Enable features which requires access to nsIWebBrowser]),
- [have_ns_web_browser=yes],
+ [have_ns_web_browser=yes],
[have_ns_web_browser=no])
if test "x$have_ns_web_browser" != "xno"; then
- AC_DEFINE([HAVE_NS_WEB_BROWSER], [1], ["Have nsIWebBrowser"])
+ AC_DEFINE([HAVE_NS_WEB_BROWSER], [1], ["Have nsIWebBrowser"])
fi
AC_PATH_PROG([GLIB_GENMARSHAL], [glib-genmarshal])
@@ -58,9 +58,14 @@ if test -d "$with_libxul_sdk"; then
GECKO_CFLAGS="-I$with_libxul_sdk/sdk/include -DXPCOM_GLUE"
XPCOMGLUE_LIBS="-L$with_libxul_sdk/sdk/lib -lxpcomglue"
MOZILLA_INCLUDE_DIR="$with_libxul_sdk/include"
+XPIDL="$with_libxul_sdk/sdk/bin/xpidl"
+MOZILLA_IDL_DIR="$with_libxul_sdk/sdk/idl"
AC_SUBST(XPCOMGLUE_LIBS)
AC_SUBST(GECKO_CFLAGS)
+AC_SUBST(MOZILLA_INCLUDE_DIR)
+AC_SUBST(XPIDL)
+AC_SUBST(MOZILLA_IDL_DIR)
AC_DEFINE([HAVE_GECKO_1_9],[1],[Define if we have gecko 1.9])
@@ -82,25 +87,7 @@ fi
else
-# xulrunner 1.8
-
-PKG_CHECK_MODULES(GECKO, [xulrunner-gtkmozembed >= 1.8],
- [have_gecko=true; mozpackage=xulrunner],
- [
-PKG_CHECK_MODULES(GECKO, [firefox-gtkmozembed >= 1.5],
- [have_gecko=true; mozpackage=firefox],
- have_gecko=false)
- ])
-
-if test "x$have_gecko" = xfalse; then
- AC_MSG_ERROR([Could not find xulrunner, mozilla or firefox $mozilla_required_version])
-fi
-
-GECKO_LDFLAGS="-R`$PKG_CONFIG --variable=libdir $mozpackage-gtkmozembed`"
-AC_SUBST(GECKO_LDFLAGS)
-
-MOZILLA_INCLUDE_DIR="`$PKG_CONFIG --variable=includedir $mozpackage-gtkmozembed`"
-AC_SUBST(MOZILLA_INCLUDE_DIR)
+AC_MSG_ERROR([Must specify the xulrunner sdk dir (--with-libxul-sdk)])
fi
@@ -121,6 +108,7 @@ Makefile
bin/Makefile
data/Makefile
browser/Makefile
+browser/sessionstore/Makefile
services/Makefile
services/presence/Makefile
services/clipboard/Makefile
diff --git a/sugar/browser/_sugarbrowser.defs b/sugar/browser/_sugarbrowser.defs
index ed94f74..f323d5e 100644
--- a/sugar/browser/_sugarbrowser.defs
+++ b/sugar/browser/_sugarbrowser.defs
@@ -113,6 +113,21 @@
(return-type "SugarBrowser*")
)
+(define-method get_session
+ (of-object "SugarBrowser")
+ (c-name "sugar_browser_get_session")
+ (return-type "char*")
+)
+
+(define-method set_session
+ (of-object "SugarBrowser")
+ (c-name "sugar_browser_set_session")
+ (return-type "none")
+ (parameters
+ '("const-char*" "session")
+ )
+)
+
;; From sugar-key-grabber.h
(define-function sugar_key_grabber_get_type