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
1=== modified file 'debian/control'
2--- debian/control 2015-01-19 10:45:25 +0000
3+++ debian/control 2015-01-28 14:25:23 +0000
4@@ -6,7 +6,7 @@
5 debhelper (>= 9),
6 dh-translations,
7 hardening-wrapper,
8- liboxideqt-qmlplugin (>= 1.3),
9+ liboxideqt-qmlplugin (>= 1.4),
10 libqt5sql5-sqlite,
11 python-flake8,
12 python3-all,
13@@ -34,7 +34,7 @@
14 Depends: ${misc:Depends},
15 ${shlibs:Depends},
16 fonts-liberation,
17- liboxideqt-qmlplugin (>= 1.1),
18+ liboxideqt-qmlplugin (>= 1.4),
19 libqt5sql5-sqlite,
20 qml-module-qtquick2 | qtdeclarative5-qtquick2-plugin,
21 qml-module-qtquick-dialogs | qtdeclarative5-dialogs-plugin,
22
23=== modified file 'src/app/webbrowser/Browser.qml'
24--- src/app/webbrowser/Browser.qml 2014-12-17 09:22:40 +0000
25+++ src/app/webbrowser/Browser.qml 2015-01-28 14:25:23 +0000
26@@ -17,7 +17,7 @@
27 */
28
29 import QtQuick 2.0
30-import com.canonical.Oxide 1.0 as Oxide
31+import com.canonical.Oxide 1.4 as Oxide
32 import Ubuntu.Components 1.1
33 import webbrowserapp.private 0.1
34 import webbrowsercommon.private 0.1
35@@ -415,7 +415,18 @@
36 id: newTabViewLoader
37 anchors.fill: parent
38
39- sourceComponent: !parent.url.toString() ? newTabViewComponent : undefined
40+ // Avoid loading the new tab view if the webview is about to load
41+ // content. Since WebView.restoreState is not a notifyable property,
42+ // this can’t be achieved with a simple property binding.
43+ Component.onCompleted: {
44+ if (!parent.url.toString() && !parent.restoreState) {
45+ sourceComponent = newTabViewComponent
46+ }
47+ }
48+ Connections {
49+ target: newTabViewLoader.parent
50+ onUrlChanged: newTabViewLoader.sourceComponent = null
51+ }
52
53 Component {
54 id: newTabViewComponent
55@@ -542,39 +553,39 @@
56 }
57
58 // Those two functions are used to save/restore the current state of a tab.
59- // The current implementation is naive, it only saves/restores the current URL.
60- // In the future, we’ll want to rely on oxide to save and restore a full state
61- // of the corresponding webview as a binary blob, which includes navigation
62- // history, current scroll offset and form data. See http://pad.lv/1353143.
63 function serializeTabState(tab) {
64 var state = {}
65 state.uniqueId = tab.uniqueId
66 state.url = tab.url.toString()
67 state.title = tab.title
68 state.preview = tab.preview.toString()
69+ state.savedState = tab.webview ? tab.webview.currentState : tab.restoreState
70 return state
71 }
72
73 function createTabFromState(state) {
74- var properties = {"initialUrl": state.url, "initialTitle": state.title}
75+ var properties = {'initialUrl': state.url, 'initialTitle': state.title}
76 if ('uniqueId' in state) {
77 properties["uniqueId"] = state.uniqueId
78 }
79 if ('preview' in state) {
80 properties["preview"] = state.preview
81 }
82+ if ('savedState' in state) {
83+ properties['restoreState'] = state.savedState
84+ properties['restoreType'] = Oxide.WebView.RestoreLastSessionExitedCleanly
85+ }
86 return tabComponent.createObject(tabContainer, properties)
87 }
88 }
89 Connections {
90- target: tabsModel
91- onCurrentTabChanged: session.save()
92- onCountChanged: session.save()
93- }
94- Connections {
95- target: browser.currentWebview
96- onUrlChanged: session.save()
97- onTitleChanged: session.save()
98+ target: Qt.application
99+ onStateChanged: {
100+ if (Qt.application.state != Qt.ApplicationActive) {
101+ session.save()
102+ }
103+ }
104+ onAboutToQuit: session.save()
105 }
106
107 // Delay instantiation of the first webview by 1 msec to allow initial
108@@ -596,7 +607,7 @@
109 browser.openUrlInNewTab(browser.homepage, true, false)
110 }
111 tabsModel.currentTab.load()
112- if (!tabsModel.currentTab.url.toString() && (formFactor == "desktop")) {
113+ if (!tabsModel.currentTab.url.toString() && !tabsModel.currentTab.restoreState && (formFactor == "desktop")) {
114 internal.focusAddressBar()
115 }
116 }
117
118=== modified file 'src/app/webbrowser/BrowserTab.qml'
119--- src/app/webbrowser/BrowserTab.qml 2014-12-16 16:25:58 +0000
120+++ src/app/webbrowser/BrowserTab.qml 2015-01-28 14:25:23 +0000
121@@ -17,12 +17,15 @@
122 */
123
124 import QtQuick 2.0
125+import com.canonical.Oxide 1.4 as Oxide
126 import webbrowserapp.private 0.1
127
128 FocusScope {
129 property string uniqueId: this.toString() + "-" + Date.now()
130 property url initialUrl
131 property string initialTitle
132+ property string restoreState
133+ property int restoreType
134 property var request
135 property Component webviewComponent
136 readonly property var webview: (children.length == 1) ? children[0] : null
137@@ -33,7 +36,14 @@
138
139 function load() {
140 if (!webview) {
141- webviewComponent.incubateObject(this, {"url": initialUrl})
142+ var properties = {}
143+ if (restoreState) {
144+ properties['restoreState'] = restoreState
145+ properties['restoreType'] = restoreType
146+ } else {
147+ properties['url'] = initialUrl
148+ }
149+ webviewComponent.incubateObject(this, properties)
150 }
151 }
152
153@@ -41,6 +51,8 @@
154 if (webview) {
155 initialUrl = webview.url
156 initialTitle = webview.title
157+ restoreState = webview.currentState
158+ restoreType = Oxide.WebView.RestoreCurrentSession
159 webview.destroy()
160 }
161 }
162
163=== removed file 'tests/autopilot/webbrowser_app/tests/test_session_save_restore.py'
164--- tests/autopilot/webbrowser_app/tests/test_session_save_restore.py 2014-12-18 18:39:47 +0000
165+++ tests/autopilot/webbrowser_app/tests/test_session_save_restore.py 1970-01-01 00:00:00 +0000
166@@ -1,51 +0,0 @@
167-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
168-#
169-# Copyright 2014 Canonical
170-#
171-# This program is free software: you can redistribute it and/or modify it
172-# under the terms of the GNU General Public License version 3, as published
173-# by the Free Software Foundation.
174-#
175-# This program is distributed in the hope that it will be useful,
176-# but WITHOUT ANY WARRANTY; without even the implied warranty of
177-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
178-# GNU General Public License for more details.
179-#
180-# You should have received a copy of the GNU General Public License
181-# along with this program. If not, see <http://www.gnu.org/licenses/>.
182-
183-from autopilot.matchers import Eventually
184-from testtools.matchers import Equals
185-
186-from webbrowser_app.tests import StartOpenRemotePageTestCaseBase
187-
188-
189-class TestSessionSaveRestore(StartOpenRemotePageTestCaseBase):
190-
191- def create_new_tab(self, url):
192- self.open_tabs_view()
193- self.open_new_tab()
194- new_tab_view = self.main_window.get_new_tab_view()
195- self.main_window.go_to_url(url)
196- new_tab_view.wait_until_destroyed()
197-
198- def test_session_is_saved_and_restored(self):
199- paths = ["/test1", "/test2", "/wait/0"]
200- for path in paths[1:]:
201- self.create_new_tab(self.base_url + path)
202- self.open_tabs_view()
203- tabs_view = self.main_window.get_tabs_view()
204- self.assertThat(tabs_view.count, Eventually(Equals(len(paths))))
205- process = self.app.process
206- process.kill()
207- process.wait(10)
208- self.ARGS = []
209- self.app = self.launch_app()
210- self.open_tabs_view()
211- tabs_view = self.main_window.get_tabs_view()
212- self.assertThat(tabs_view.count, Eventually(Equals(len(paths))))
213- previews = tabs_view.get_ordered_previews()
214- for i in range(len(paths)):
215- self.assertThat(previews[len(paths) - 1 - i].url,
216- Eventually(Equals(self.base_url + paths[i])))
217- self.assert_number_webviews_eventually(1)
218
219=== modified file 'tests/unittests/qml/tst_BrowserTab.qml'
220--- tests/unittests/qml/tst_BrowserTab.qml 2014-12-16 17:24:32 +0000
221+++ tests/unittests/qml/tst_BrowserTab.qml 2015-01-28 14:25:23 +0000
222@@ -35,6 +35,7 @@
223 property string title
224 property url icon
225 property var request
226+ property string currentState
227 }
228 readonly property bool webviewPresent: webview
229 readonly property bool captureTakerPresent: captureTaker != undefined
230@@ -66,10 +67,12 @@
231
232 tab.webview.url = "http://ubuntu.com"
233 tab.webview.title = "Ubuntu"
234+ tab.webview.currentState = "foobar"
235 tab.unload()
236 tryCompare(tab, 'webviewPresent', false)
237 compare(tab.initialUrl, "http://ubuntu.com")
238 compare(tab.initialTitle, "Ubuntu")
239+ compare(tab.restoreState, "foobar")
240
241 tab.destroy()
242 }

Subscribers

People subscribed via source and target branches

to status/vote changes: