Merge lp:~osomon/webbrowser-app/save-restore-state into lp:webbrowser-app

Proposed by Olivier Tilloy
Status: Merged
Approved by: Olivier Tilloy
Approved revision: 834
Merged at revision: 886
Proposed branch: lp:~osomon/webbrowser-app/save-restore-state
Merge into: lp:webbrowser-app
Diff against target: 242 lines (+45/-70)
5 files modified
debian/control (+2/-2)
src/app/webbrowser/Browser.qml (+27/-16)
src/app/webbrowser/BrowserTab.qml (+13/-1)
tests/autopilot/webbrowser_app/tests/test_session_save_restore.py (+0/-51)
tests/unittests/qml/tst_BrowserTab.qml (+3/-0)
To merge this branch: bzr merge lp:~osomon/webbrowser-app/save-restore-state
Reviewer Review Type Date Requested Status
Michael Vogt (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+242678@code.launchpad.net

Commit message

Use the new restoreState API in oxide 1.4 to properly save and restore navigation state across sessions.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
826. By Olivier Tilloy

Merge the latest changes from trunk,
and resolve a conflict.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
827. By Olivier Tilloy

Merge the latest changes from trunk,
and resolve a conflict.

828. By Olivier Tilloy

Remove a not very useful comment.

829. By Olivier Tilloy

Rename the 'blob' property to 'savedState', which is much more explicit.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
830. By Olivier Tilloy

Merge the latest changes from trunk,
and resolve a couple of conflicts.

831. By Olivier Tilloy

Fix BrowserTab unit tests.

832. By Olivier Tilloy

Revert accidental change introduced when merging latest trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
833. By Olivier Tilloy

Merge the latest changes from trunk, and resolve a conflict.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
834. By Olivier Tilloy

Bump the required oxide version in the build dependencies as well, since unit tests require oxide 1.4.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Vogt (mvo) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2015-01-19 10:45:25 +0000
+++ debian/control 2015-01-28 14:25:23 +0000
@@ -6,7 +6,7 @@
6 debhelper (>= 9),6 debhelper (>= 9),
7 dh-translations,7 dh-translations,
8 hardening-wrapper,8 hardening-wrapper,
9 liboxideqt-qmlplugin (>= 1.3),9 liboxideqt-qmlplugin (>= 1.4),
10 libqt5sql5-sqlite,10 libqt5sql5-sqlite,
11 python-flake8,11 python-flake8,
12 python3-all,12 python3-all,
@@ -34,7 +34,7 @@
34Depends: ${misc:Depends},34Depends: ${misc:Depends},
35 ${shlibs:Depends},35 ${shlibs:Depends},
36 fonts-liberation,36 fonts-liberation,
37 liboxideqt-qmlplugin (>= 1.1),37 liboxideqt-qmlplugin (>= 1.4),
38 libqt5sql5-sqlite,38 libqt5sql5-sqlite,
39 qml-module-qtquick2 | qtdeclarative5-qtquick2-plugin,39 qml-module-qtquick2 | qtdeclarative5-qtquick2-plugin,
40 qml-module-qtquick-dialogs | qtdeclarative5-dialogs-plugin,40 qml-module-qtquick-dialogs | qtdeclarative5-dialogs-plugin,
4141
=== modified file 'src/app/webbrowser/Browser.qml'
--- src/app/webbrowser/Browser.qml 2014-12-17 09:22:40 +0000
+++ src/app/webbrowser/Browser.qml 2015-01-28 14:25:23 +0000
@@ -17,7 +17,7 @@
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.0
20import com.canonical.Oxide 1.0 as Oxide20import com.canonical.Oxide 1.4 as Oxide
21import Ubuntu.Components 1.121import Ubuntu.Components 1.1
22import webbrowserapp.private 0.122import webbrowserapp.private 0.1
23import webbrowsercommon.private 0.123import webbrowsercommon.private 0.1
@@ -415,7 +415,18 @@
415 id: newTabViewLoader415 id: newTabViewLoader
416 anchors.fill: parent416 anchors.fill: parent
417417
418 sourceComponent: !parent.url.toString() ? newTabViewComponent : undefined418 // Avoid loading the new tab view if the webview is about to load
419 // content. Since WebView.restoreState is not a notifyable property,
420 // this can’t be achieved with a simple property binding.
421 Component.onCompleted: {
422 if (!parent.url.toString() && !parent.restoreState) {
423 sourceComponent = newTabViewComponent
424 }
425 }
426 Connections {
427 target: newTabViewLoader.parent
428 onUrlChanged: newTabViewLoader.sourceComponent = null
429 }
419430
420 Component {431 Component {
421 id: newTabViewComponent432 id: newTabViewComponent
@@ -542,39 +553,39 @@
542 }553 }
543554
544 // Those two functions are used to save/restore the current state of a tab.555 // Those two functions are used to save/restore the current state of a tab.
545 // The current implementation is naive, it only saves/restores the current URL.
546 // In the future, we’ll want to rely on oxide to save and restore a full state
547 // of the corresponding webview as a binary blob, which includes navigation
548 // history, current scroll offset and form data. See http://pad.lv/1353143.
549 function serializeTabState(tab) {556 function serializeTabState(tab) {
550 var state = {}557 var state = {}
551 state.uniqueId = tab.uniqueId558 state.uniqueId = tab.uniqueId
552 state.url = tab.url.toString()559 state.url = tab.url.toString()
553 state.title = tab.title560 state.title = tab.title
554 state.preview = tab.preview.toString()561 state.preview = tab.preview.toString()
562 state.savedState = tab.webview ? tab.webview.currentState : tab.restoreState
555 return state563 return state
556 }564 }
557565
558 function createTabFromState(state) {566 function createTabFromState(state) {
559 var properties = {"initialUrl": state.url, "initialTitle": state.title}567 var properties = {'initialUrl': state.url, 'initialTitle': state.title}
560 if ('uniqueId' in state) {568 if ('uniqueId' in state) {
561 properties["uniqueId"] = state.uniqueId569 properties["uniqueId"] = state.uniqueId
562 }570 }
563 if ('preview' in state) {571 if ('preview' in state) {
564 properties["preview"] = state.preview572 properties["preview"] = state.preview
565 }573 }
574 if ('savedState' in state) {
575 properties['restoreState'] = state.savedState
576 properties['restoreType'] = Oxide.WebView.RestoreLastSessionExitedCleanly
577 }
566 return tabComponent.createObject(tabContainer, properties)578 return tabComponent.createObject(tabContainer, properties)
567 }579 }
568 }580 }
569 Connections {581 Connections {
570 target: tabsModel582 target: Qt.application
571 onCurrentTabChanged: session.save()583 onStateChanged: {
572 onCountChanged: session.save()584 if (Qt.application.state != Qt.ApplicationActive) {
573 }585 session.save()
574 Connections {586 }
575 target: browser.currentWebview587 }
576 onUrlChanged: session.save()588 onAboutToQuit: session.save()
577 onTitleChanged: session.save()
578 }589 }
579590
580 // Delay instantiation of the first webview by 1 msec to allow initial591 // Delay instantiation of the first webview by 1 msec to allow initial
@@ -596,7 +607,7 @@
596 browser.openUrlInNewTab(browser.homepage, true, false)607 browser.openUrlInNewTab(browser.homepage, true, false)
597 }608 }
598 tabsModel.currentTab.load()609 tabsModel.currentTab.load()
599 if (!tabsModel.currentTab.url.toString() && (formFactor == "desktop")) {610 if (!tabsModel.currentTab.url.toString() && !tabsModel.currentTab.restoreState && (formFactor == "desktop")) {
600 internal.focusAddressBar()611 internal.focusAddressBar()
601 }612 }
602 }613 }
603614
=== modified file 'src/app/webbrowser/BrowserTab.qml'
--- src/app/webbrowser/BrowserTab.qml 2014-12-16 16:25:58 +0000
+++ src/app/webbrowser/BrowserTab.qml 2015-01-28 14:25:23 +0000
@@ -17,12 +17,15 @@
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.0
20import com.canonical.Oxide 1.4 as Oxide
20import webbrowserapp.private 0.121import webbrowserapp.private 0.1
2122
22FocusScope {23FocusScope {
23 property string uniqueId: this.toString() + "-" + Date.now()24 property string uniqueId: this.toString() + "-" + Date.now()
24 property url initialUrl25 property url initialUrl
25 property string initialTitle26 property string initialTitle
27 property string restoreState
28 property int restoreType
26 property var request29 property var request
27 property Component webviewComponent30 property Component webviewComponent
28 readonly property var webview: (children.length == 1) ? children[0] : null31 readonly property var webview: (children.length == 1) ? children[0] : null
@@ -33,7 +36,14 @@
3336
34 function load() {37 function load() {
35 if (!webview) {38 if (!webview) {
36 webviewComponent.incubateObject(this, {"url": initialUrl})39 var properties = {}
40 if (restoreState) {
41 properties['restoreState'] = restoreState
42 properties['restoreType'] = restoreType
43 } else {
44 properties['url'] = initialUrl
45 }
46 webviewComponent.incubateObject(this, properties)
37 }47 }
38 }48 }
3949
@@ -41,6 +51,8 @@
41 if (webview) {51 if (webview) {
42 initialUrl = webview.url52 initialUrl = webview.url
43 initialTitle = webview.title53 initialTitle = webview.title
54 restoreState = webview.currentState
55 restoreType = Oxide.WebView.RestoreCurrentSession
44 webview.destroy()56 webview.destroy()
45 }57 }
46 }58 }
4759
=== removed file 'tests/autopilot/webbrowser_app/tests/test_session_save_restore.py'
--- tests/autopilot/webbrowser_app/tests/test_session_save_restore.py 2014-12-18 18:39:47 +0000
+++ tests/autopilot/webbrowser_app/tests/test_session_save_restore.py 1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright 2014 Canonical
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17from autopilot.matchers import Eventually
18from testtools.matchers import Equals
19
20from webbrowser_app.tests import StartOpenRemotePageTestCaseBase
21
22
23class TestSessionSaveRestore(StartOpenRemotePageTestCaseBase):
24
25 def create_new_tab(self, url):
26 self.open_tabs_view()
27 self.open_new_tab()
28 new_tab_view = self.main_window.get_new_tab_view()
29 self.main_window.go_to_url(url)
30 new_tab_view.wait_until_destroyed()
31
32 def test_session_is_saved_and_restored(self):
33 paths = ["/test1", "/test2", "/wait/0"]
34 for path in paths[1:]:
35 self.create_new_tab(self.base_url + path)
36 self.open_tabs_view()
37 tabs_view = self.main_window.get_tabs_view()
38 self.assertThat(tabs_view.count, Eventually(Equals(len(paths))))
39 process = self.app.process
40 process.kill()
41 process.wait(10)
42 self.ARGS = []
43 self.app = self.launch_app()
44 self.open_tabs_view()
45 tabs_view = self.main_window.get_tabs_view()
46 self.assertThat(tabs_view.count, Eventually(Equals(len(paths))))
47 previews = tabs_view.get_ordered_previews()
48 for i in range(len(paths)):
49 self.assertThat(previews[len(paths) - 1 - i].url,
50 Eventually(Equals(self.base_url + paths[i])))
51 self.assert_number_webviews_eventually(1)
520
=== modified file 'tests/unittests/qml/tst_BrowserTab.qml'
--- tests/unittests/qml/tst_BrowserTab.qml 2014-12-16 17:24:32 +0000
+++ tests/unittests/qml/tst_BrowserTab.qml 2015-01-28 14:25:23 +0000
@@ -35,6 +35,7 @@
35 property string title35 property string title
36 property url icon36 property url icon
37 property var request37 property var request
38 property string currentState
38 }39 }
39 readonly property bool webviewPresent: webview40 readonly property bool webviewPresent: webview
40 readonly property bool captureTakerPresent: captureTaker != undefined41 readonly property bool captureTakerPresent: captureTaker != undefined
@@ -66,10 +67,12 @@
6667
67 tab.webview.url = "http://ubuntu.com"68 tab.webview.url = "http://ubuntu.com"
68 tab.webview.title = "Ubuntu"69 tab.webview.title = "Ubuntu"
70 tab.webview.currentState = "foobar"
69 tab.unload()71 tab.unload()
70 tryCompare(tab, 'webviewPresent', false)72 tryCompare(tab, 'webviewPresent', false)
71 compare(tab.initialUrl, "http://ubuntu.com")73 compare(tab.initialUrl, "http://ubuntu.com")
72 compare(tab.initialTitle, "Ubuntu")74 compare(tab.initialTitle, "Ubuntu")
75 compare(tab.restoreState, "foobar")
7376
74 tab.destroy()77 tab.destroy()
75 }78 }

Subscribers

People subscribed via source and target branches

to status/vote changes: