Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucian Branescu Mihaila <lucian.branescu@gmail.com>2009-11-08 15:04:55 (GMT)
committer Lucian Branescu Mihaila <lucian.branescu@gmail.com>2009-11-08 15:04:55 (GMT)
commit0e5585f457be03e929a04345aab5529c9fe12319 (patch)
tree639dda290330f0ed76365dea837da7cdde2e1b33
parente82bbcedd1d3bc5780a30ceb6b15712719897a6e (diff)
Keep offline implements offline bookmarks
-rw-r--r--downloadmanager.py115
-rw-r--r--webactivity.py22
-rw-r--r--webtoolbar.py14
3 files changed, 148 insertions, 3 deletions
diff --git a/downloadmanager.py b/downloadmanager.py
index a3fe6d8..2b513e7 100644
--- a/downloadmanager.py
+++ b/downloadmanager.py
@@ -22,6 +22,7 @@ import time
import tempfile
import urlparse
import urllib
+import zipfile
import gtk
import hulahop
@@ -382,5 +383,117 @@ class _SaveLinkProgressListener(object):
def onDataAvailable(self, request, context, inputStream, offset, count):
self._external_listener.onDataAvailable(request, context, inputStream,
- offset, count);
+ offset, count)
+
+def save_document(activity, browser):
+ '''Save the current webpage for offline use'''
+ cls = components.classes[ \
+ '@mozilla.org/embedding/browser/nsWebBrowserPersist;1']
+ persist = cls.createInstance(interfaces.nsIWebBrowserPersist)
+
+ local = components.classes["@mozilla.org/file/local;1"]
+ local_file = local.createInstance(interfaces.nsILocalFile)
+ local_data = local.createInstance(interfaces.nsILocalFile)
+
+ temp_dir = tempfile.mkdtemp()
+
+ local_file.initWithPath(os.path.join(temp_dir, 'index.html'))
+ local_data.initWithPath(os.path.join(temp_dir, 'data'))
+
+ persist.persistFlags = interfaces.nsIWebBrowserPersist \
+ .PERSIST_FLAGS_REPLACE_EXISTING_FILES
+ persist.progressListener = _SaveDocumentProgressListener(activity,
+ temp_dir, browser.props.title)._wrapped
+ persist.saveDocument(browser.dom_window.document, local_file, local_data,
+ None, 0, 0)
+
+class _SaveDocumentProgressListener(object):
+ _com_interfaces_ = interfaces.nsIWebProgressListener
+
+ def __init__(self, activity, temp_dir, title):
+ self._activity = activity
+ self._temp_dir = temp_dir
+ self._title = title
+ self._zip_path = os.path.join(activity.get_activity_root(),
+ 'instance', self._title+'.zip')
+ self._jobject = None
+
+ self._wrapped = xpcom.server.WrapObject(self,
+ interfaces.nsIWebProgressListener)
+
+ def onStateChange(self, web_progress, request, state_flags, status):
+ if state_flags & interfaces.nsIWebProgressListener.STATE_STOP:
+ if NS_FAILED(status):
+ alert = TimeoutAlert(9)
+ alert.props.title = _('Keep offline')
+ alert.props.msg = _('Saving "%s" for offline use failed') % \
+ self._title
+ self._activity.add_alert(alert)
+ alert.connect('response', self.__fail_response_cb)
+ alert.show()
+ else:
+ try: # HACK because NS_FAILED(status) is wrong
+ self._create_zip()
+ self._create_journal_object()
+ except OSError:
+ return
+
+ alert = Alert()
+ alert.props.title = _('Keep offline')
+
+ cancel_icon = Icon(icon_name='dialog-cancel')
+ alert.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), cancel_icon)
+ cancel_icon.show()
+
+ open_icon = Icon(icon_name='filesave')
+ alert.add_button(gtk.RESPONSE_OK, _('Show in Journal'),
+ open_icon)
+ open_icon.show()
+
+ self._activity.add_alert(alert)
+ alert.connect('response', self.__success_response_cb)
+
+ def onStatusChange(self, web_progress, request, status, message):
+ pass
+
+ def onProgressChange(self, web_progress, request, cur_self_progress,
+ max_self_progress, cur_total_progress,
+ max_total_progress):
+ pass
+
+ def onLocationChange(self, web_progress, request, location):
+ pass
+
+ def onSecurityChange(self, web_progress, request, state):
+ pass
+
+ def __fail_response_cb(self, alert, response_id):
+ self._activity.remove_alert(alert)
+
+ def __success_response_cb(self, alert, response_id):
+ self._activity.remove_alert(alert)
+
+ if response_id is gtk.RESPONSE_OK:
+ activity.show_object_in_journal(self._jobject.object_id)
+
+
+ def _create_zip(self):
+ bundle = zipfile.ZipFile(self._zip_path, 'w', zipfile.ZIP_DEFLATED)
+
+ bundle.write(os.path.join(self._temp_dir, 'index.html'), 'index.html')
+ data_path = os.path.join(self._temp_dir, 'data')
+ for i in os.listdir(data_path):
+ bundle.write(os.path.join(data_path, i),
+ os.path.join('data', i))
+ bundle.close()
+
+ def _create_journal_object(self):
+ self._jobject = datastore.create()
+ self._jobject.metadata['title'] = self._title
+ self._jobject.metadata['icon-color'] = \
+ profile.get_color().to_string()
+ self._jobject.metadata['mime_type'] = 'application/zip'
+ self._jobject.metadata['activity'] = 'org.laptop.WebActivity'
+ self._jobject.file_path = self._zip_path
+ datastore.write(self._jobject)
diff --git a/webactivity.py b/webactivity.py
index 4be551e..8007bce 100644
--- a/webactivity.py
+++ b/webactivity.py
@@ -31,6 +31,8 @@ import sqlite3
import cjson
import gconf
import locale
+import zipfile
+import tempfile
# HACK: Needed by http://dev.sugarlabs.org/ticket/456
import gnome
@@ -191,6 +193,7 @@ class WebActivity(activity.Activity):
self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self)
self._primary_toolbar.connect('add-link', self._link_add_button_cb)
+ self._primary_toolbar.connect('keep-offline', self._keep_offline_cb)
self._tray = HTray()
self.set_tray(self._tray, gtk.POS_BOTTOM)
@@ -391,7 +394,21 @@ class WebActivity(activity.Activity):
self._tabbed_view.props.current_browser.load_uri(uris[0])
else:
_logger.error('Open uri-list: Does not support'
- 'list of multiple uris by now.')
+ 'list of multiple uris by now.')
+ elif self.metadata['mime_type'] == 'application/zip':
+ temp_dir = tempfile.mkdtemp()
+
+ z = zipfile.ZipFile(file_path, 'r')
+ os.mkdir(os.path.join(temp_dir, 'data'))
+ # zipfile can only expand from 2.6 onwards
+ for i in z.namelist():
+ open(os.path.join(temp_dir, i), 'wb').write(z.read(i))
+
+ index_path = os.path.join(temp_dir, 'index.html')
+ if os.path.isfile(index_path):
+ self._tabbed_view.props.current_browser.load_uri(index_path)
+ else:
+ self._tabbed_view.props.current_browser.load_uri(temp_dir)
else:
self._tabbed_view.props.current_browser.load_uri(file_path)
@@ -556,3 +573,6 @@ class WebActivity(activity.Activity):
browser = self._tabbed_view.props.current_browser
browser.get_source(async_cb, async_err_cb)
+ def _keep_offline_cb(self, toolbar):
+ downloadmanager.save_document(self,
+ self._tabbed_view.props.current_browser) \ No newline at end of file
diff --git a/webtoolbar.py b/webtoolbar.py
index 854345c..7be8dfb 100644
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -222,7 +222,10 @@ class PrimaryToolbar(ToolbarBox):
__gsignals__ = {
'add-link': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
- ([]))
+ ([])),
+ 'keep-offline': (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ ([])),
}
def __init__(self, tabbed_view, act):
@@ -237,6 +240,12 @@ class PrimaryToolbar(ToolbarBox):
activity_button = ActivityToolbarButton(self._activity)
self.toolbar.insert(activity_button, 0)
+ self._keep_offline = ToolButton('htmloff')
+ self._keep_offline.set_tooltip(_("Save offline"))
+ self._keep_offline.connect('clicked', self.__keep_offline_cb)
+ self._keep_offline.show()
+ activity_button.props.page.insert(self._keep_offline, -1)
+
self._stop_and_reload = ToolButton('media-playback-stop')
self._stop_and_reload.connect('clicked', self._stop_and_reload_cb)
self.toolbar.insert(self._stop_and_reload, -1)
@@ -294,6 +303,9 @@ class PrimaryToolbar(ToolbarBox):
def __switch_page_cb(self, tabbed_view, page, page_num):
self._connect_to_browser(tabbed_view.props.current_browser)
+ def __keep_offline_cb(self, button):
+ self.emit('keep-offline')
+
def _connect_to_browser(self, browser):
if self._progress_listener is not None:
self._progress_listener.disconnect(self._location_changed_hid)