385 | | offset, count); |
386 | | |
| 387 | offset, count) |
| 388 | |
| 389 | def save_document(browser, activity): |
| 390 | cls = components.classes[ \ |
| 391 | '@mozilla.org/embedding/browser/nsWebBrowserPersist;1'] |
| 392 | persist = cls.createInstance(interfaces.nsIWebBrowserPersist) |
| 393 | |
| 394 | local = components.classes["@mozilla.org/file/local;1"] |
| 395 | local_file = local.createInstance(interfaces.nsILocalFile) |
| 396 | local_data = local.createInstance(interfaces.nsILocalFile) |
| 397 | |
| 398 | temp_dir = tempfile.mkdtemp() |
| 399 | |
| 400 | local_file.initWithPath(os.path.join(temp_dir, 'index.html')) |
| 401 | local_data.initWithPath(os.path.join(temp_dir, 'data')) |
| 402 | |
| 403 | persist.persistFlags = interfaces.nsIWebBrowserPersist \ |
| 404 | .PERSIST_FLAGS_REPLACE_EXISTING_FILES |
| 405 | persist.progressListener = _SaveDocumentProgressListener(activity, |
| 406 | temp_dir, browser.props.title)._wrapped |
| 407 | persist.saveDocument(browser.dom_window.document, local_file, local_data, |
| 408 | None, 0, 0) |
| 409 | |
| 410 | class _SaveDocumentProgressListener(object): |
| 411 | _com_interfaces_ = interfaces.nsIWebProgressListener |
| 412 | |
| 413 | def __init__(self, activity, temp_dir, title): |
| 414 | self._activity = activity |
| 415 | self._temp_dir = temp_dir |
| 416 | self._title = title |
| 417 | self._zip_path = os.path.join(activity.get_activity_root(), |
| 418 | 'instance', self._title+'.zip') |
| 419 | self._jobject = None |
| 420 | |
| 421 | self._wrapped = xpcom.server.WrapObject(self, |
| 422 | interfaces.nsIWebProgressListener) |
| 423 | |
| 424 | def onStateChange(self, web_progress, request, state_flags, status): |
| 425 | if state_flags & interfaces.nsIWebProgressListener.STATE_STOP: |
| 426 | if NS_FAILED(status): |
| 427 | alert = TimeoutAlert(9) |
| 428 | alert.props.title = _('Keep offline') |
| 429 | alert.props.msg = _('Saving "%s" for offline use failed') % \ |
| 430 | self._title |
| 431 | self._activity.add_alert(alert) |
| 432 | alert.connect('response', self.__fail_response_cb) |
| 433 | alert.show() |
| 434 | else: |
| 435 | try: # HACK because NS_FAILED(status) is wrong |
| 436 | self._create_zip() |
| 437 | self._create_journal_object() |
| 438 | except OSError: |
| 439 | return |
| 440 | |
| 441 | alert = Alert() |
| 442 | alert.props.title = _('Keep offline') |
| 443 | |
| 444 | cancel_icon = Icon(icon_name='dialog-cancel') |
| 445 | alert.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), cancel_icon) |
| 446 | cancel_icon.show() |
| 447 | |
| 448 | open_icon = Icon(icon_name='filesave') |
| 449 | alert.add_button(gtk.RESPONSE_OK, _('Show in Journal'), |
| 450 | open_icon) |
| 451 | open_icon.show() |
| 452 | |
| 453 | self._activity.add_alert(alert) |
| 454 | alert.connect('response', self.__success_response_cb) |
| 455 | |
| 456 | def onStatusChange(self, web_progress, request, status, message): |
| 457 | pass |
| 458 | |
| 459 | def onProgressChange(self, web_progress, request, cur_self_progress, |
| 460 | max_self_progress, cur_total_progress, |
| 461 | max_total_progress): |
| 462 | pass |
| 463 | |
| 464 | def onLocationChange(self, web_progress, request, location): |
| 465 | pass |
| 466 | |
| 467 | def onSecurityChange(self, web_progress, request, state): |
| 468 | pass |
| 469 | |
| 470 | def __fail_response_cb(self, alert, response_id): |
| 471 | self._activity.remove_alert(alert) |
| 472 | |
| 473 | def __success_response_cb(self, alert, response_id): |
| 474 | self._activity.remove_alert(alert) |
| 475 | |
| 476 | if response_id is gtk.RESPONSE_OK: |
| 477 | activity.show_object_in_journal(self._jobject.object_id) |
| 478 | |
| 479 | |
| 480 | def _create_zip(self): |
| 481 | bundle = zipfile.ZipFile(self._zip_path, 'w', zipfile.ZIP_DEFLATED) |
| 482 | |
| 483 | bundle.write(os.path.join(self._temp_dir, 'index.html'), 'index.html') |
| 484 | data_path = os.path.join(self._temp_dir, 'data') |
| 485 | for i in os.listdir(data_path): |
| 486 | bundle.write(os.path.join(data_path, i), |
| 487 | os.path.join('data', i)) |
| 488 | bundle.close() |
| 489 | |
| 490 | def _create_journal_object(self): |
| 491 | self._jobject = datastore.create() |
| 492 | self._jobject.metadata['title'] = self._title |
| 493 | self._jobject.metadata['icon-color'] = \ |
| 494 | profile.get_color().to_string() |
| 495 | self._jobject.metadata['mime_type'] = 'application/zip' |
| 496 | self._jobject.metadata['activity'] = 'org.laptop.WebActivity' |
| 497 | self._jobject.file_path = self._zip_path |
| 498 | datastore.write(self._jobject) |