Merge lp:~joergberroth/unav/WebViewCrashHandling into lp:unav

Proposed by JkB
Status: Superseded
Proposed branch: lp:~joergberroth/unav/WebViewCrashHandling
Merge into: lp:unav
Diff against target: 321 lines (+156/-29)
5 files modified
nav/index.html (+1/-0)
qml/Main.qml (+24/-16)
qml/components/NotificationBar.qml (+30/-2)
qml/components/POIQuickAccessGridView.qml (+9/-11)
qml/components/WebProcessMonitor.qml (+92/-0)
To merge this branch: bzr merge lp:~joergberroth/unav/WebViewCrashHandling
Reviewer Review Type Date Requested Status
costales Needs Fixing
Review via email: mp+295984@code.launchpad.net

This proposal has been superseded by a proposal from 2016-06-06.

Commit message

* added WebProcessMonitor.qml from webbrowser-app to manage webview kills
  - notification that map crashed.
  - try to reload webview if it was killed.
  - if a route was active, it will be reloaded again.
* adjusted NotificationBar.qml and some code clean up (NotificationBarTimer handling)

Description of the change

* added WebProcessMonitor.qml from webbrowser-app to manage webview kills
  - notification that map crashed.
  - try to reload webview if it was killed.
  - if a route was active, it will be reloaded again.
* adjusted NotificationBar.qml and some code clean up (NotificationBarTimer handling)

To post a comment you must log in.
70. By JkB

* small format fix

71. By JkB

*add another notification
*wait 500ms before recalculating route
*modified a notifiacation in WebProcessMonitor.qml

72. By JkB

*ensure that endLat/endLng will always be set in Main.qml if route_state changes to "yes"

Revision history for this message
costales (costales) wrote :

It didn't work for me.
I used uNav in the morning.
After ~10 hours, I opened and I saw the map and the red popup.
uNav was freezed ~5 seconds and then, the system killed it.

review: Needs Fixing
73. By JkB

*removed typo in id
*added close() signal

74. By JkB

*merge with trunk

75. By JkB

*removed timer and improved popup handling

76. By JkB

*changed error messages text

77. By JkB

*merge with costales branch

78. By JkB

* modified notification text

Unmerged revisions

78. By JkB

* modified notification text

77. By JkB

*merge with costales branch

76. By JkB

*changed error messages text

75. By JkB

*removed timer and improved popup handling

74. By JkB

*merge with trunk

73. By JkB

*removed typo in id
*added close() signal

72. By JkB

*ensure that endLat/endLng will always be set in Main.qml if route_state changes to "yes"

71. By JkB

*add another notification
*wait 500ms before recalculating route
*modified a notifiacation in WebProcessMonitor.qml

70. By JkB

* small format fix

69. By JkB

* added WebProcessMonitor.qml from webbrowser-app to manage webview kills
  - notification that map crashed.
  - try to reload webview if it was killed.
  - if a route was active, it will be reloaded again.
* adjusted NotificationBar.qml and some code clean up (NotificationBarTimer handling)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nav/index.html'
2--- nav/index.html 2016-05-20 17:23:21 +0000
3+++ nav/index.html 2016-06-05 18:24:36 +0000
4@@ -575,6 +575,7 @@
5 nav.set_route_status('yes');
6 ui.update();
7 qml_set_center_onpos(2);
8+ qml_set_route_status();
9 }
10 </script>
11
12
13=== modified file 'qml/Main.qml'
14--- qml/Main.qml 2016-06-03 13:46:57 +0000
15+++ qml/Main.qml 2016-06-05 18:24:36 +0000
16@@ -149,6 +149,7 @@
17 property int center_onpos: 0 // 0 GPS off, 1 GPS on + not center, 2 GPS on + center
18 property bool favPopup: false
19 property bool onLoadingExecuted: false
20+ property bool forcedReload: false
21
22 property string usContext: "messaging://"
23 // Workaround: as long as map keeps a webcontainer this function handles js events to the webview.
24@@ -367,19 +368,18 @@
25
26 case "http://show_notification/":
27 if (params[1] === "speed_camera_error") {
28- notifiactionBar.text = i18n.tr("Error getting speed cameras!");
29+ notificationBar.text = i18n.tr("Error getting speed cameras!");
30 }
31- switch (params[0]) {
32+ switch (params[0]) {
33 case "info":
34- notifiactionBar.info();
35+ notificationBar.info();
36 break;
37 case "warning":
38- notifiactionBar.warning();
39+ notificationBar.warning();
40 break;
41 case "critical":
42- notifiactionBar.critical();
43+ notificationBar.critical();
44 }
45- notificationBarTimer.start();
46 }
47 request.action = Oxide.NavigationRequest.ActionReject;
48 }
49@@ -422,12 +422,29 @@
50 goThereActionPopover.show();
51 }
52 }
53+
54+ if (mainPageStack.forcedReload === true && mainPageStack.routeState === "yes") {
55+ mainPageStack.forcedReload = false
56+ notificationBar.close()
57+
58+ if ( mainPageStack.endLat !== "null" && mainPageStack.endLng !== "null") {
59+ mainPageStack.center_onpos = 2;
60+ mainPageStack.executeJavaScript("calc2coord(" + mainPageStack.endLat + "," + mainPageStack.endLng + ");")
61+ } else {
62+ notificationBar.text = i18n.tr("Sorry, route info could not be retrieved. Please, re-set the route.")
63+ notificationBar.warning()
64+ }
65+ }
66 }
67 }
68
69 onGeolocationPermissionRequested: { request.allow() }
70 }
71
72+ WebProcessMonitor{
73+ webview: webview
74+ }
75+
76 Connections {
77 target: UriHandler
78 onOpened: {
79@@ -520,17 +537,8 @@
80 }
81 }
82
83- Timer {
84- id: notificationBarTimer
85- interval: 8000
86- repeat: false
87- onTriggered: {
88- notifiactionBar.visible = false
89- }
90- }
91-
92 NotificationBar {
93- id: notifiactionBar
94+ id: notificationBar
95 }
96
97 XmlListModel {
98
99=== modified file 'qml/components/NotificationBar.qml'
100--- qml/components/NotificationBar.qml 2016-05-22 17:20:29 +0000
101+++ qml/components/NotificationBar.qml 2016-06-05 18:24:36 +0000
102@@ -25,30 +25,41 @@
103 signal info()
104 signal warning()
105 signal critical()
106+ signal close()
107+
108+ onClose: {
109+ notificationBar.visible = false
110+ }
111
112 onInfo: {
113+ close()
114 notificationLabel.color = UbuntuColors.slate
115 notificationRectangle.color = "#FFFFFF"
116 notificationRectangle.visible = true;
117 notificationIcon.name = ""
118 notificationLabel.fontSize = "medium"
119 notificationRectangle.height = notificationLabel.height + units.gu(1)
120+ notificationBarTimer.restart()
121 }
122 onWarning: {
123+ close()
124 notificationLabel.color = "#FFFFFF"
125 notificationRectangle.color = UbuntuColors.orange;
126 notificationRectangle.visible = true;
127 notificationLabel.fontSize = "large"
128 notificationIcon.name = "dialog-warning-symbolic"
129 notificationRectangle.height = notificationLabel.height + units.gu(4)
130+ notificationBarTimer.restart()
131 }
132 onCritical: {
133+ close()
134 notificationLabel.color = "#FFFFFF"
135 notificationRectangle.color = UbuntuColors.red
136 notificationRectangle.visible = true;
137 notificationLabel.fontSize = "large"
138 notificationIcon.name = "dialog-error-symbolic"
139 notificationRectangle.height = notificationLabel.height + units.gu(4)
140+ notificationBarTimer.restart()
141 }
142
143 width: parent.width
144@@ -58,6 +69,14 @@
145 top: goThereActionPopover.isShown ? goThereActionPopover.bottom : navigationPage.header.bottom
146 }
147
148+ MouseArea {
149+ anchors.fill: parent
150+ onClicked: {
151+ notificationBarTimer.stop()
152+ notificationBar.visible = false
153+ }
154+ }
155+
156 Icon {
157 id: notificationIcon
158 width: units.gu(3.5)
159@@ -80,9 +99,18 @@
160 right: parent.right
161 verticalCenter: parent.verticalCenter
162 }
163- horizontalAlignment: Text.AlignHCenter
164- maximumLineCount: 3
165+ horizontalAlignment: notificationIcon.visible ? Text.AlignLeft : Text.AlignHCenter
166+ maximumLineCount: 6
167 wrapMode: Text.WordWrap
168 elide: Text.ElideRight
169 }
170+
171+ Timer {
172+ id: notificationBarTimer
173+ interval: 8000
174+ repeat: false
175+ onTriggered: {
176+ notificationBar.close()
177+ }
178+ }
179 }
180
181=== modified file 'qml/components/POIQuickAccessGridView.qml'
182--- qml/components/POIQuickAccessGridView.qml 2016-05-22 18:08:53 +0000
183+++ qml/components/POIQuickAccessGridView.qml 2016-06-05 18:24:36 +0000
184@@ -87,17 +87,15 @@
185 if (status === XmlListModel.Error) {
186 console.log(errorString());
187 source = "";
188- notificationBarTimer.start();
189- notifiactionBar.text = i18n.tr("Error getting results. Please, check your data connection.");
190- notifiactionBar.critical();
191+ notificationBar.text = i18n.tr("Error getting results. Please, check your data connection.");
192+ notificationBar.critical();
193 }
194 if (status === XmlListModel.Ready && count === 0) {
195- notificationBarTimer.start();
196- notifiactionBar.text = i18n.tr("Sorry, no results found nearby.");
197- notifiactionBar.info();
198+ notificationBar.text = i18n.tr("Sorry, no results found nearby.");
199+ notificationBar.info();
200 }
201 if (status === XmlListModel.Ready && count >> 0) {
202- notifiactionBar.visible = false;
203+ notificationBar.close()
204 mainPageStack.executeJavaScript("ui.markers_POI_set(" + JSON.stringify(poiXmlModel.allPOI()) + ")");
205 mainPageStack.center_onpos = 1;
206 goThereActionPopover.hide();
207@@ -170,13 +168,13 @@
208 mainPageStack.addPageToNextColumn(mainPageStack.primaryPage, Qt.resolvedUrl("../PoiQuickAccessPage.qml"))
209 } else {
210 if (mainPageStack.currentLat === 'null' || mainPageStack.currentLng === 'null') {
211- notifiactionBar.text = i18n.tr("Current position unknown. Try again after a position update.");
212- notifiactionBar.info();
213+ notificationBar.text = i18n.tr("Current position unknown. Try again after a position update.");
214+ notificationBar.info();
215 }
216 else {
217 poiXmlModel.clear();
218- notifiactionBar.text = i18n.tr("Searching…");
219- notifiactionBar.info();
220+ notificationBar.text = i18n.tr("Searching…");
221+ notificationBar.info();
222 poiXmlModel.distance = model.distance;
223 poiXmlModel.clause = model.clause;
224 poiXmlModel.search();
225
226=== added file 'qml/components/WebProcessMonitor.qml'
227--- qml/components/WebProcessMonitor.qml 1970-01-01 00:00:00 +0000
228+++ qml/components/WebProcessMonitor.qml 2016-06-05 18:24:36 +0000
229@@ -0,0 +1,92 @@
230+/*
231+ * Copyright 2015 Canonical Ltd.
232+ *
233+ * This file is part of webbrowser-app.
234+ *
235+ * webbrowser-app is free software; you can redistribute it and/or modify
236+ * it under the terms of the GNU General Public License as published by
237+ * the Free Software Foundation; version 3.
238+ *
239+ * webbrowser-app is distributed in the hope that it will be useful,
240+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
241+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
242+ * GNU General Public License for more details.
243+ *
244+ * You should have received a copy of the GNU General Public License
245+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
246+ */
247+
248+import QtQuick 2.4
249+import com.canonical.Oxide 1.9 as Oxide
250+
251+Item {
252+ id: monitor
253+
254+ visible: false
255+
256+ property var webview: null
257+
258+ readonly property bool killed: webview &&
259+ (webview.webProcessStatus === Oxide.WebView.WebProcessKilled)
260+ readonly property bool crashed: webview &&
261+ (webview.webProcessStatus === Oxide.WebView.WebProcessCrashed)
262+
263+ // When the renderer process is killed (most likely by the system’s
264+ // OOM killer), try to reload the page once, and if this results in
265+ // the process being killed again within one minute, then display
266+ // the sad tab.
267+
268+ readonly property int killedRetries: internal.killedRetries
269+
270+ QtObject {
271+ id: internal
272+ property int killedRetries: 0
273+ }
274+
275+ Connections {
276+ target: webview
277+ onWebProcessStatusChanged: {
278+ if (webview.webProcessStatus === Oxide.WebView.WebProcessKilled) {
279+ if (internal.killedRetries == 0) {
280+ // Do not attempt reloading right away, this would result in a crash
281+ delayedReload.restart()
282+ console.log("Webview was killed!")
283+ if (mainPageStack.routeState === "yes" ) {
284+ notificationBar.text = i18n.tr("Something went wrong.")
285+ + "\n" + i18n.tr("Reloading the map and the last active route…")
286+ } else {
287+ notificationBar.text = i18n.tr("Something went wrong.")
288+ + "\n" + i18n.tr("Reloading the map…")
289+ }
290+ notificationBar.critical()
291+ }
292+ }
293+ }
294+ }
295+
296+ Timer {
297+ id: delayedReload
298+ interval: 100
299+ onTriggered: {
300+ monitorTimer.restart()
301+ mainPageStack.onLoadingExecuted = false
302+ mainPageStack.forcedReload = true
303+ navigationPage.buttonsEnabled = false
304+ monitor.webview.reload()
305+ console.log("Trying to reload the webview…")
306+ internal.killedRetries++
307+ }
308+ }
309+
310+ Timer {
311+ id: monitorTimer
312+ interval: 60000 // 1 minute
313+ onTriggered: internal.killedRetries = 0
314+ }
315+
316+ onWebviewChanged: {
317+ internal.killedRetries = 0
318+ delayedReload.stop()
319+ monitorTimer.stop()
320+ }
321+}

Subscribers

People subscribed via source and target branches