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
=== modified file 'nav/index.html'
--- nav/index.html 2016-05-20 17:23:21 +0000
+++ nav/index.html 2016-06-05 18:24:36 +0000
@@ -575,6 +575,7 @@
575 nav.set_route_status('yes');575 nav.set_route_status('yes');
576 ui.update();576 ui.update();
577 qml_set_center_onpos(2);577 qml_set_center_onpos(2);
578 qml_set_route_status();
578 }579 }
579 </script>580 </script>
580581
581582
=== modified file 'qml/Main.qml'
--- qml/Main.qml 2016-06-03 13:46:57 +0000
+++ qml/Main.qml 2016-06-05 18:24:36 +0000
@@ -149,6 +149,7 @@
149 property int center_onpos: 0 // 0 GPS off, 1 GPS on + not center, 2 GPS on + center149 property int center_onpos: 0 // 0 GPS off, 1 GPS on + not center, 2 GPS on + center
150 property bool favPopup: false150 property bool favPopup: false
151 property bool onLoadingExecuted: false151 property bool onLoadingExecuted: false
152 property bool forcedReload: false
152153
153 property string usContext: "messaging://"154 property string usContext: "messaging://"
154 // Workaround: as long as map keeps a webcontainer this function handles js events to the webview.155 // Workaround: as long as map keeps a webcontainer this function handles js events to the webview.
@@ -367,19 +368,18 @@
367 368
368 case "http://show_notification/":369 case "http://show_notification/":
369 if (params[1] === "speed_camera_error") {370 if (params[1] === "speed_camera_error") {
370 notifiactionBar.text = i18n.tr("Error getting speed cameras!");371 notificationBar.text = i18n.tr("Error getting speed cameras!");
371 }372 }
372 switch (params[0]) {373 switch (params[0]) {
373 case "info":374 case "info":
374 notifiactionBar.info();375 notificationBar.info();
375 break;376 break;
376 case "warning":377 case "warning":
377 notifiactionBar.warning();378 notificationBar.warning();
378 break;379 break;
379 case "critical":380 case "critical":
380 notifiactionBar.critical();381 notificationBar.critical();
381 }382 }
382 notificationBarTimer.start();
383 }383 }
384 request.action = Oxide.NavigationRequest.ActionReject;384 request.action = Oxide.NavigationRequest.ActionReject;
385 }385 }
@@ -422,12 +422,29 @@
422 goThereActionPopover.show();422 goThereActionPopover.show();
423 }423 }
424 }424 }
425
426 if (mainPageStack.forcedReload === true && mainPageStack.routeState === "yes") {
427 mainPageStack.forcedReload = false
428 notificationBar.close()
429
430 if ( mainPageStack.endLat !== "null" && mainPageStack.endLng !== "null") {
431 mainPageStack.center_onpos = 2;
432 mainPageStack.executeJavaScript("calc2coord(" + mainPageStack.endLat + "," + mainPageStack.endLng + ");")
433 } else {
434 notificationBar.text = i18n.tr("Sorry, route info could not be retrieved. Please, re-set the route.")
435 notificationBar.warning()
436 }
437 }
425 }438 }
426 }439 }
427440
428 onGeolocationPermissionRequested: { request.allow() }441 onGeolocationPermissionRequested: { request.allow() }
429 }442 }
430443
444 WebProcessMonitor{
445 webview: webview
446 }
447
431 Connections {448 Connections {
432 target: UriHandler449 target: UriHandler
433 onOpened: {450 onOpened: {
@@ -520,17 +537,8 @@
520 }537 }
521 }538 }
522539
523 Timer {
524 id: notificationBarTimer
525 interval: 8000
526 repeat: false
527 onTriggered: {
528 notifiactionBar.visible = false
529 }
530 }
531
532 NotificationBar {540 NotificationBar {
533 id: notifiactionBar541 id: notificationBar
534 }542 }
535543
536 XmlListModel {544 XmlListModel {
537545
=== modified file 'qml/components/NotificationBar.qml'
--- qml/components/NotificationBar.qml 2016-05-22 17:20:29 +0000
+++ qml/components/NotificationBar.qml 2016-06-05 18:24:36 +0000
@@ -25,30 +25,41 @@
25 signal info()25 signal info()
26 signal warning()26 signal warning()
27 signal critical()27 signal critical()
28 signal close()
29
30 onClose: {
31 notificationBar.visible = false
32 }
2833
29 onInfo: {34 onInfo: {
35 close()
30 notificationLabel.color = UbuntuColors.slate36 notificationLabel.color = UbuntuColors.slate
31 notificationRectangle.color = "#FFFFFF"37 notificationRectangle.color = "#FFFFFF"
32 notificationRectangle.visible = true;38 notificationRectangle.visible = true;
33 notificationIcon.name = ""39 notificationIcon.name = ""
34 notificationLabel.fontSize = "medium"40 notificationLabel.fontSize = "medium"
35 notificationRectangle.height = notificationLabel.height + units.gu(1)41 notificationRectangle.height = notificationLabel.height + units.gu(1)
42 notificationBarTimer.restart()
36 }43 }
37 onWarning: {44 onWarning: {
45 close()
38 notificationLabel.color = "#FFFFFF"46 notificationLabel.color = "#FFFFFF"
39 notificationRectangle.color = UbuntuColors.orange;47 notificationRectangle.color = UbuntuColors.orange;
40 notificationRectangle.visible = true;48 notificationRectangle.visible = true;
41 notificationLabel.fontSize = "large"49 notificationLabel.fontSize = "large"
42 notificationIcon.name = "dialog-warning-symbolic"50 notificationIcon.name = "dialog-warning-symbolic"
43 notificationRectangle.height = notificationLabel.height + units.gu(4)51 notificationRectangle.height = notificationLabel.height + units.gu(4)
52 notificationBarTimer.restart()
44 }53 }
45 onCritical: {54 onCritical: {
55 close()
46 notificationLabel.color = "#FFFFFF"56 notificationLabel.color = "#FFFFFF"
47 notificationRectangle.color = UbuntuColors.red57 notificationRectangle.color = UbuntuColors.red
48 notificationRectangle.visible = true;58 notificationRectangle.visible = true;
49 notificationLabel.fontSize = "large"59 notificationLabel.fontSize = "large"
50 notificationIcon.name = "dialog-error-symbolic"60 notificationIcon.name = "dialog-error-symbolic"
51 notificationRectangle.height = notificationLabel.height + units.gu(4)61 notificationRectangle.height = notificationLabel.height + units.gu(4)
62 notificationBarTimer.restart()
52 }63 }
5364
54 width: parent.width65 width: parent.width
@@ -58,6 +69,14 @@
58 top: goThereActionPopover.isShown ? goThereActionPopover.bottom : navigationPage.header.bottom69 top: goThereActionPopover.isShown ? goThereActionPopover.bottom : navigationPage.header.bottom
59 }70 }
6071
72 MouseArea {
73 anchors.fill: parent
74 onClicked: {
75 notificationBarTimer.stop()
76 notificationBar.visible = false
77 }
78 }
79
61 Icon {80 Icon {
62 id: notificationIcon81 id: notificationIcon
63 width: units.gu(3.5)82 width: units.gu(3.5)
@@ -80,9 +99,18 @@
80 right: parent.right99 right: parent.right
81 verticalCenter: parent.verticalCenter100 verticalCenter: parent.verticalCenter
82 }101 }
83 horizontalAlignment: Text.AlignHCenter102 horizontalAlignment: notificationIcon.visible ? Text.AlignLeft : Text.AlignHCenter
84 maximumLineCount: 3103 maximumLineCount: 6
85 wrapMode: Text.WordWrap104 wrapMode: Text.WordWrap
86 elide: Text.ElideRight105 elide: Text.ElideRight
87 }106 }
107
108 Timer {
109 id: notificationBarTimer
110 interval: 8000
111 repeat: false
112 onTriggered: {
113 notificationBar.close()
114 }
115 }
88}116}
89117
=== modified file 'qml/components/POIQuickAccessGridView.qml'
--- qml/components/POIQuickAccessGridView.qml 2016-05-22 18:08:53 +0000
+++ qml/components/POIQuickAccessGridView.qml 2016-06-05 18:24:36 +0000
@@ -87,17 +87,15 @@
87 if (status === XmlListModel.Error) {87 if (status === XmlListModel.Error) {
88 console.log(errorString());88 console.log(errorString());
89 source = "";89 source = "";
90 notificationBarTimer.start();90 notificationBar.text = i18n.tr("Error getting results. Please, check your data connection.");
91 notifiactionBar.text = i18n.tr("Error getting results. Please, check your data connection.");91 notificationBar.critical();
92 notifiactionBar.critical();
93 }92 }
94 if (status === XmlListModel.Ready && count === 0) {93 if (status === XmlListModel.Ready && count === 0) {
95 notificationBarTimer.start();94 notificationBar.text = i18n.tr("Sorry, no results found nearby.");
96 notifiactionBar.text = i18n.tr("Sorry, no results found nearby.");95 notificationBar.info();
97 notifiactionBar.info();
98 }96 }
99 if (status === XmlListModel.Ready && count >> 0) {97 if (status === XmlListModel.Ready && count >> 0) {
100 notifiactionBar.visible = false;98 notificationBar.close()
101 mainPageStack.executeJavaScript("ui.markers_POI_set(" + JSON.stringify(poiXmlModel.allPOI()) + ")");99 mainPageStack.executeJavaScript("ui.markers_POI_set(" + JSON.stringify(poiXmlModel.allPOI()) + ")");
102 mainPageStack.center_onpos = 1;100 mainPageStack.center_onpos = 1;
103 goThereActionPopover.hide();101 goThereActionPopover.hide();
@@ -170,13 +168,13 @@
170 mainPageStack.addPageToNextColumn(mainPageStack.primaryPage, Qt.resolvedUrl("../PoiQuickAccessPage.qml"))168 mainPageStack.addPageToNextColumn(mainPageStack.primaryPage, Qt.resolvedUrl("../PoiQuickAccessPage.qml"))
171 } else {169 } else {
172 if (mainPageStack.currentLat === 'null' || mainPageStack.currentLng === 'null') {170 if (mainPageStack.currentLat === 'null' || mainPageStack.currentLng === 'null') {
173 notifiactionBar.text = i18n.tr("Current position unknown. Try again after a position update.");171 notificationBar.text = i18n.tr("Current position unknown. Try again after a position update.");
174 notifiactionBar.info();172 notificationBar.info();
175 }173 }
176 else {174 else {
177 poiXmlModel.clear();175 poiXmlModel.clear();
178 notifiactionBar.text = i18n.tr("Searching…");176 notificationBar.text = i18n.tr("Searching…");
179 notifiactionBar.info();177 notificationBar.info();
180 poiXmlModel.distance = model.distance;178 poiXmlModel.distance = model.distance;
181 poiXmlModel.clause = model.clause;179 poiXmlModel.clause = model.clause;
182 poiXmlModel.search();180 poiXmlModel.search();
183181
=== added file 'qml/components/WebProcessMonitor.qml'
--- qml/components/WebProcessMonitor.qml 1970-01-01 00:00:00 +0000
+++ qml/components/WebProcessMonitor.qml 2016-06-05 18:24:36 +0000
@@ -0,0 +1,92 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.4
20import com.canonical.Oxide 1.9 as Oxide
21
22Item {
23 id: monitor
24
25 visible: false
26
27 property var webview: null
28
29 readonly property bool killed: webview &&
30 (webview.webProcessStatus === Oxide.WebView.WebProcessKilled)
31 readonly property bool crashed: webview &&
32 (webview.webProcessStatus === Oxide.WebView.WebProcessCrashed)
33
34 // When the renderer process is killed (most likely by the system’s
35 // OOM killer), try to reload the page once, and if this results in
36 // the process being killed again within one minute, then display
37 // the sad tab.
38
39 readonly property int killedRetries: internal.killedRetries
40
41 QtObject {
42 id: internal
43 property int killedRetries: 0
44 }
45
46 Connections {
47 target: webview
48 onWebProcessStatusChanged: {
49 if (webview.webProcessStatus === Oxide.WebView.WebProcessKilled) {
50 if (internal.killedRetries == 0) {
51 // Do not attempt reloading right away, this would result in a crash
52 delayedReload.restart()
53 console.log("Webview was killed!")
54 if (mainPageStack.routeState === "yes" ) {
55 notificationBar.text = i18n.tr("Something went wrong.")
56 + "\n" + i18n.tr("Reloading the map and the last active route…")
57 } else {
58 notificationBar.text = i18n.tr("Something went wrong.")
59 + "\n" + i18n.tr("Reloading the map…")
60 }
61 notificationBar.critical()
62 }
63 }
64 }
65 }
66
67 Timer {
68 id: delayedReload
69 interval: 100
70 onTriggered: {
71 monitorTimer.restart()
72 mainPageStack.onLoadingExecuted = false
73 mainPageStack.forcedReload = true
74 navigationPage.buttonsEnabled = false
75 monitor.webview.reload()
76 console.log("Trying to reload the webview…")
77 internal.killedRetries++
78 }
79 }
80
81 Timer {
82 id: monitorTimer
83 interval: 60000 // 1 minute
84 onTriggered: internal.killedRetries = 0
85 }
86
87 onWebviewChanged: {
88 internal.killedRetries = 0
89 delayedReload.stop()
90 monitorTimer.stop()
91 }
92}

Subscribers

People subscribed via source and target branches