Merge lp:~osomon/webbrowser-app/remove-formFactor into lp:webbrowser-app

Proposed by Olivier Tilloy
Status: Merged
Approved by: Olivier Tilloy
Approved revision: 1367
Merged at revision: 1361
Proposed branch: lp:~osomon/webbrowser-app/remove-formFactor
Merge into: lp:webbrowser-app
Diff against target: 1105 lines (+475/-141)
22 files modified
README (+0/-5)
debian/control (+1/-0)
src/Ubuntu/Web/UbuntuWebView02.qml (+2/-2)
src/Ubuntu/Web/plugin.cpp (+1/-38)
src/app/BrowserView.qml (+2/-0)
src/app/CMakeLists.txt (+7/-1)
src/app/browserapplication.cpp (+42/-14)
src/app/meminfo.cpp (+137/-0)
src/app/meminfo.h (+65/-0)
src/app/webbrowser/Browser.qml (+69/-31)
src/app/webbrowser/BrowserTab.qml (+3/-0)
src/app/webbrowser/Chrome.qml (+3/-1)
src/app/webbrowser/SettingsPage.qml (+1/-20)
src/app/webbrowser/TabItem.qml (+9/-8)
src/app/webbrowser/TabsBar.qml (+4/-1)
src/app/webbrowser/webbrowser-app.cpp (+2/-0)
src/app/webcontainer/WebApp.qml (+3/-2)
src/app/webcontainer/WebViewImplOxide.qml (+6/-11)
tests/autopilot/webbrowser_app/tests/__init__.py (+2/-7)
tests/unittests/CMakeLists.txt (+1/-0)
tests/unittests/meminfo/CMakeLists.txt (+15/-0)
tests/unittests/meminfo/tst_MemInfoTests.cpp (+100/-0)
To merge this branch: bzr merge lp:~osomon/webbrowser-app/remove-formFactor
Reviewer Review Type Date Requested Status
Alexandre Abreu (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+285539@code.launchpad.net

Commit message

Remove the 'formFactor' context property, and replace all its uses by more meaningful conditions.

Description of the change

Note: as of 2016-02-07, there are 7 applications in the store that import Ubuntu.Web and have at least one reference to the 'formFactor' context property. Those are:

 com.nokia.heremaps 1.0.7
 com.ubuntu.developer.webapps.googleplus 0.7.1
 googleapps.mattirn 1.0.1
 mynewsapps.mattirn 1.0.4
 mywebsites.mattirn 1.0.1
 ubuntu.mattirn 1.0.1
 wikifoundation.mattirn 1.0.2

Canonical is responsible for the first two, we need to update them. I’m going to reach out to mattirn to suggest how to fix his apps so they don’t refer to 'formFactor'.

In any case, I don’t expect any important functionality to suddenly break even if the property was removed without updating those apps.

UPDATE: as of 2016-02-18, the last five apps in the above list (all by mattirn) have been updated, they don’t have references to 'formFactor' any longer. com.ubuntu.developer.webapps.googleplus has also been updated, the last remaining app is com.nokia.heremaps for which I’ve submitted an update (waiting for a review).

To post a comment you must log in.
Revision history for this message
Chris Coulson (chrisccoulson) wrote :

I've added a comment inline to this

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

Verify that a geolocation permission request originates from the webapp’s domain before silently accepting it.

1364. By Olivier Tilloy

When low on memory, the current public tab might have been unloaded, so reload it when exiting incognito mode.

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
Alexandre Abreu (abreu-alexandre) wrote :

Overall looks good, a few questions below

Revision history for this message
Olivier Tilloy (osomon) wrote :

Thanks for your thorough review, I’ve replied to your questions (with more questions!) inline.

Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

See replies

1365. By Olivier Tilloy

Document the value of the lowOnMemory threshold.

Revision history for this message
Olivier Tilloy (osomon) wrote :

Updated.

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

Do not try to load an non existent tab.

1367. By Olivier Tilloy

Raise the threshold for which a system is considered low on memory, from tests run on a MX4.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'README'
--- README 2015-04-01 05:57:42 +0000
+++ README 2016-02-23 11:14:53 +0000
@@ -86,11 +86,6 @@
86 the OpenSearch document description format86 the OpenSearch document description format
87 (http://www.opensearch.org/Specifications/OpenSearch/1.1)87 (http://www.opensearch.org/Specifications/OpenSearch/1.1)
8888
89 - 'allowOpenInBackgroundTab': whether to offer an option to open a link in a
90 new background tab in the contextual menu. Possible values are "true",
91 "false", and "default" (which resolves to true on desktop and false on
92 mobile).
93
94 - restoreSession: whether to restore the previous browsing session at startup89 - restoreSession: whether to restore the previous browsing session at startup
95 (defaults to true)90 (defaults to true)
9691
9792
=== modified file 'debian/control'
--- debian/control 2016-01-28 16:23:17 +0000
+++ debian/control 2016-02-23 11:14:53 +0000
@@ -10,6 +10,7 @@
10 dh-apparmor,10 dh-apparmor,
11 dh-translations,11 dh-translations,
12 hardening-wrapper,12 hardening-wrapper,
13 libapparmor-dev,
13 libevdev-dev,14 libevdev-dev,
14 liboxideqt-qmlplugin (>= 1.9),15 liboxideqt-qmlplugin (>= 1.9),
15 libqt5sql5-sqlite,16 libqt5sql5-sqlite,
1617
=== modified file 'src/Ubuntu/Web/UbuntuWebView02.qml'
--- src/Ubuntu/Web/UbuntuWebView02.qml 2016-01-05 08:35:58 +0000
+++ src/Ubuntu/Web/UbuntuWebView02.qml 2016-02-23 11:14:53 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013-2015 Canonical Ltd.2 * Copyright 2013-2016 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -51,7 +51,7 @@
51 navigationRequestedDelegate(request);51 navigationRequestedDelegate(request);
52 }52 }
5353
54 preferences.passwordEchoEnabled: formFactor === "mobile"54 preferences.passwordEchoEnabled: Qt.inputMethod.visible
5555
56 popupMenu: ItemSelector02 {56 popupMenu: ItemSelector02 {
57 automaticOrientation: false57 automaticOrientation: false
5858
=== modified file 'src/Ubuntu/Web/plugin.cpp'
--- src/Ubuntu/Web/plugin.cpp 2015-12-10 22:01:05 +0000
+++ src/Ubuntu/Web/plugin.cpp 2016-02-23 11:14:53 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013-2015 Canonical Ltd.2 * Copyright 2013-2016 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -40,7 +40,6 @@
4040
41 Q_PROPERTY(QString cacheLocation READ cacheLocation NOTIFY cacheLocationChanged)41 Q_PROPERTY(QString cacheLocation READ cacheLocation NOTIFY cacheLocationChanged)
42 Q_PROPERTY(QString dataLocation READ dataLocation NOTIFY dataLocationChanged)42 Q_PROPERTY(QString dataLocation READ dataLocation NOTIFY dataLocationChanged)
43 Q_PROPERTY(QString formFactor READ formFactor CONSTANT)
44 Q_PROPERTY(qreal screenDiagonal READ screenDiagonal NOTIFY screenDiagonalChanged)43 Q_PROPERTY(qreal screenDiagonal READ screenDiagonal NOTIFY screenDiagonalChanged)
45 Q_PROPERTY(int cacheSizeHint READ cacheSizeHint NOTIFY cacheSizeHintChanged)44 Q_PROPERTY(int cacheSizeHint READ cacheSizeHint NOTIFY cacheSizeHintChanged)
46 Q_PROPERTY(QString webviewDevtoolsDebugHost READ devtoolsHost CONSTANT)45 Q_PROPERTY(QString webviewDevtoolsDebugHost READ devtoolsHost CONSTANT)
@@ -52,7 +51,6 @@
5251
53 QString cacheLocation() const;52 QString cacheLocation() const;
54 QString dataLocation() const;53 QString dataLocation() const;
55 QString formFactor();
56 qreal screenDiagonal() const;54 qreal screenDiagonal() const;
57 int cacheSizeHint() const;55 int cacheSizeHint() const;
58 QString devtoolsHost();56 QString devtoolsHost();
@@ -71,7 +69,6 @@
7169
72private:70private:
73 qreal m_screenDiagonal; // in millimeters71 qreal m_screenDiagonal; // in millimeters
74 QString m_formFactor;
75 QString m_devtoolsHost;72 QString m_devtoolsHost;
76 int m_devtoolsPort;73 int m_devtoolsPort;
77 QStringList m_hostMappingRules;74 QStringList m_hostMappingRules;
@@ -129,40 +126,6 @@
129 return location.absolutePath();126 return location.absolutePath();
130}127}
131128
132QString UbuntuWebPluginContext::formFactor()
133{
134 if (m_formFactor.isEmpty()) {
135 // This implementation only considers two possible form factors: desktop,
136 // and mobile (which includes phones and tablets).
137 // XXX: do we need to consider other form factors, such as tablet?
138 const char* DESKTOP = "desktop";
139 const char* MOBILE = "mobile";
140
141 // The "DESKTOP_MODE" environment variable can be used to force the form
142 // factor to desktop, when set to any valid value other than 0.
143 const char* DESKTOP_MODE_ENV_VAR = "DESKTOP_MODE";
144 if (qEnvironmentVariableIsSet(DESKTOP_MODE_ENV_VAR)) {
145 QByteArray stringValue = qgetenv(DESKTOP_MODE_ENV_VAR);
146 bool ok = false;
147 int value = stringValue.toInt(&ok);
148 if (ok) {
149 m_formFactor = (value == 0) ? MOBILE : DESKTOP;
150 return m_formFactor;
151 }
152 }
153
154 // XXX: Assume that QtUbuntu means mobile, which is currently the case,
155 // but may not remain true forever.
156 QString platform = QGuiApplication::platformName();
157 if ((platform == "ubuntu") || (platform == "ubuntumirclient")) {
158 m_formFactor = MOBILE;
159 } else {
160 m_formFactor = DESKTOP;
161 }
162 }
163 return m_formFactor;
164}
165
166qreal UbuntuWebPluginContext::screenDiagonal() const129qreal UbuntuWebPluginContext::screenDiagonal() const
167{130{
168 return m_screenDiagonal;131 return m_screenDiagonal;
169132
=== modified file 'src/app/BrowserView.qml'
--- src/app/BrowserView.qml 2016-01-12 09:37:08 +0000
+++ src/app/BrowserView.qml 2016-02-23 11:14:53 +0000
@@ -32,6 +32,8 @@
3232
33 property var osk: _osk33 property var osk: _osk
3434
35 property bool hasTouchScreen: false
36
35 // See http://design.canonical.com/2015/05/to-converge-onto-mobile-tablet-and-desktop-think-grid-units/37 // See http://design.canonical.com/2015/05/to-converge-onto-mobile-tablet-and-desktop-think-grid-units/
36 readonly property bool wide: width >= units.gu(90)38 readonly property bool wide: width >= units.gu(90)
3739
3840
=== modified file 'src/app/CMakeLists.txt'
--- src/app/CMakeLists.txt 2016-01-28 18:54:35 +0000
+++ src/app/CMakeLists.txt 2016-02-23 11:14:53 +0000
@@ -7,6 +7,9 @@
7find_package(Qt5Quick REQUIRED)7find_package(Qt5Quick REQUIRED)
8find_package(Qt5Widgets REQUIRED)8find_package(Qt5Widgets REQUIRED)
99
10include(FindPkgConfig)
11pkg_check_modules(LIBAPPARMOR REQUIRED libapparmor)
12
10add_subdirectory(unity8)13add_subdirectory(unity8)
1114
12configure_file(15configure_file(
@@ -19,6 +22,7 @@
19set(COMMONLIB_SRC22set(COMMONLIB_SRC
20 browserapplication.cpp23 browserapplication.cpp
21 favicon-fetcher.cpp24 favicon-fetcher.cpp
25 meminfo.cpp
22 mime-database.cpp26 mime-database.cpp
23 session-storage.cpp27 session-storage.cpp
24 single-instance-manager.cpp28 single-instance-manager.cpp
@@ -28,7 +32,8 @@
28add_library(${COMMONLIB} STATIC ${COMMONLIB_SRC})32add_library(${COMMONLIB} STATIC ${COMMONLIB_SRC})
2933
30include_directories(${unity8_SOURCE_DIR}/libs/UbuntuGestures34include_directories(${unity8_SOURCE_DIR}/libs/UbuntuGestures
31 ${unity8_SOURCE_DIR}/plugins)35 ${unity8_SOURCE_DIR}/plugins
36 ${LIBAPPARMOR_INCLUDE_DIRS})
32target_link_libraries(${COMMONLIB}37target_link_libraries(${COMMONLIB}
33 Qt5::Core38 Qt5::Core
34 Qt5::Gui39 Qt5::Gui
@@ -38,6 +43,7 @@
38 Qt5::Widgets43 Qt5::Widgets
39 UbuntuGesturesQml44 UbuntuGesturesQml
40 InputInfo45 InputInfo
46 ${LIBAPPARMOR_LDFLAGS}
41)47)
4248
43file(GLOB QML_FILES *.qml)49file(GLOB QML_FILES *.qml)
4450
=== modified file 'src/app/browserapplication.cpp'
--- src/app/browserapplication.cpp 2016-01-28 18:54:35 +0000
+++ src/app/browserapplication.cpp 2016-02-23 11:14:53 +0000
@@ -16,9 +16,15 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19// system
20#include <cerrno>
21#include <cstring>
22#include <sys/apparmor.h>
23
19// Qt24// Qt
20#include <QtCore/QMetaObject>25#include <QtCore/QMetaObject>
21#include <QtCore/QtGlobal>26#include <QtCore/QtGlobal>
27#include <QtGui/QTouchDevice>
22#include <QtNetwork/QNetworkInterface>28#include <QtNetwork/QNetworkInterface>
23#include <QtQml/QQmlComponent>29#include <QtQml/QQmlComponent>
24#include <QtQml/QQmlContext>30#include <QtQml/QQmlContext>
@@ -30,6 +36,7 @@
30#include "browserapplication.h"36#include "browserapplication.h"
31#include "config.h"37#include "config.h"
32#include "favicon-fetcher.h"38#include "favicon-fetcher.h"
39#include "meminfo.h"
33#include "mime-database.h"40#include "mime-database.h"
34#include "session-storage.h"41#include "session-storage.h"
35#include "webbrowser-window.h"42#include "webbrowser-window.h"
@@ -100,19 +107,17 @@
100 return QString();107 return QString();
101}108}
102109
103static QObject* MimeDatabase_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine)110#define MAKE_SINGLETON_FACTORY(type) \
104{111 static QObject* type##_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) { \
105 Q_UNUSED(engine);112 Q_UNUSED(engine); \
106 Q_UNUSED(scriptEngine);113 Q_UNUSED(scriptEngine); \
107 return new MimeDatabase();114 return new type(); \
108}115 }
109116
110static QObject* Direction_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine)117MAKE_SINGLETON_FACTORY(MemInfo)
111{118MAKE_SINGLETON_FACTORY(MimeDatabase)
112 Q_UNUSED(engine);119MAKE_SINGLETON_FACTORY(Direction)
113 Q_UNUSED(scriptEngine);120
114 return new Direction();
115}
116121
117bool BrowserApplication::initialize(const QString& qmlFileSubPath)122bool BrowserApplication::initialize(const QString& qmlFileSubPath)
118{123{
@@ -149,6 +154,18 @@
149 return false;154 return false;
150 }155 }
151156
157 bool runningConfined = true;
158 char* label;
159 char* mode;
160 if (aa_getcon(&label, &mode) != -1) {
161 if (strcmp(label, "unconfined") == 0) {
162 runningConfined = false;
163 }
164 free(label);
165 } else if (errno == EINVAL) {
166 runningConfined = false;
167 }
168
152 QString devtoolsPort = inspectorPort();169 QString devtoolsPort = inspectorPort();
153 QString devtoolsHost = inspectorHost();170 QString devtoolsHost = inspectorHost();
154 bool inspectorEnabled = !devtoolsPort.isEmpty();171 bool inspectorEnabled = !devtoolsPort.isEmpty();
@@ -159,6 +176,7 @@
159176
160 const char* uri = "webbrowsercommon.private";177 const char* uri = "webbrowsercommon.private";
161 qmlRegisterType<FaviconFetcher>(uri, 0, 1, "FaviconFetcher");178 qmlRegisterType<FaviconFetcher>(uri, 0, 1, "FaviconFetcher");
179 qmlRegisterSingletonType<MemInfo>(uri, 0, 1, "MemInfo", MemInfo_singleton_factory);
162 qmlRegisterSingletonType<MimeDatabase>(uri, 0, 1, "MimeDatabase", MimeDatabase_singleton_factory);180 qmlRegisterSingletonType<MimeDatabase>(uri, 0, 1, "MimeDatabase", MimeDatabase_singleton_factory);
163 qmlRegisterType<SessionStorage>(uri, 0, 1, "SessionStorage");181 qmlRegisterType<SessionStorage>(uri, 0, 1, "SessionStorage");
164182
@@ -179,6 +197,9 @@
179 qmlEngineCreated(m_engine);197 qmlEngineCreated(m_engine);
180198
181 QQmlContext* context = m_engine->rootContext();199 QQmlContext* context = m_engine->rootContext();
200 context->setContextProperty("__runningConfined", runningConfined);
201 context->setContextProperty("unversionedAppId", unversionedAppId);
202
182 m_component = new QQmlComponent(m_engine);203 m_component = new QQmlComponent(m_engine);
183 m_component->loadUrl(QUrl::fromLocalFile(UbuntuBrowserDirectory() + "/" + qmlFileSubPath));204 m_component->loadUrl(QUrl::fromLocalFile(UbuntuBrowserDirectory() + "/" + qmlFileSubPath));
184 if (!m_component->isReady()) {205 if (!m_component->isReady()) {
@@ -187,7 +208,6 @@
187 }208 }
188 m_webbrowserWindowProxy = new WebBrowserWindow();209 m_webbrowserWindowProxy = new WebBrowserWindow();
189 context->setContextProperty("webbrowserWindowProxy", m_webbrowserWindowProxy);210 context->setContextProperty("webbrowserWindowProxy", m_webbrowserWindowProxy);
190 context->setContextProperty("unversionedAppId", unversionedAppId);
191211
192 QObject* browser = m_component->beginCreate(context);212 QObject* browser = m_component->beginCreate(context);
193 m_window = qobject_cast<QQuickWindow*>(browser);213 m_window = qobject_cast<QQuickWindow*>(browser);
@@ -198,6 +218,14 @@
198 browser->setProperty("developerExtrasEnabled", inspectorEnabled);218 browser->setProperty("developerExtrasEnabled", inspectorEnabled);
199 browser->setProperty("forceFullscreen", m_arguments.contains("--fullscreen"));219 browser->setProperty("forceFullscreen", m_arguments.contains("--fullscreen"));
200220
221 bool hasTouchScreen = false;
222 Q_FOREACH(const QTouchDevice* device, QTouchDevice::devices()) {
223 if (device->type() == QTouchDevice::TouchScreen) {
224 hasTouchScreen = true;
225 }
226 }
227 browser->setProperty("hasTouchScreen", hasTouchScreen);
228
201 return true;229 return true;
202}230}
203231
204232
=== added file 'src/app/meminfo.cpp'
--- src/app/meminfo.cpp 1970-01-01 00:00:00 +0000
+++ src/app/meminfo.cpp 2016-02-23 11:14:53 +0000
@@ -0,0 +1,137 @@
1/*
2 * Copyright 2016 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
19#include "meminfo.h"
20
21// Qt
22#include <QtCore/QByteArray>
23#include <QtCore/QFile>
24#include <QtCore/QRegExp>
25#include <QtCore/QString>
26#include <QtCore/QtGlobal>
27
28MemInfo::MemInfo(QObject* parent)
29 : QObject(parent)
30 , m_total(0)
31 , m_free(0)
32{
33 // Default interval: 5000 ms
34 m_timer.setInterval(5000);
35 connect(&m_timer, SIGNAL(timeout()), SLOT(update()));
36 // Active by default
37 m_timer.start();
38}
39
40MemInfo::~MemInfo()
41{}
42
43const bool MemInfo::active() const
44{
45 return m_timer.isActive();
46}
47
48void MemInfo::setActive(bool active)
49{
50 if (active != m_timer.isActive()) {
51 if (active) {
52 m_timer.start();
53 } else {
54 m_timer.stop();
55 }
56 Q_EMIT activeChanged();
57 }
58}
59
60const int MemInfo::interval() const
61{
62 return m_timer.interval();
63}
64
65void MemInfo::setInterval(int interval)
66{
67 if (interval != m_timer.interval()) {
68 m_timer.setInterval(interval);
69 Q_EMIT intervalChanged();
70 }
71}
72
73const int MemInfo::total() const
74{
75 return m_total;
76}
77
78const int MemInfo::free() const
79{
80 return m_free;
81}
82
83void MemInfo::update()
84{
85#if defined(Q_OS_LINUX)
86 // Inspired by glibtop_get_mem_s()
87 QFile meminfo(QStringLiteral("/proc/meminfo"));
88 if (!meminfo.open(QIODevice::ReadOnly)) {
89 return;
90 }
91 static QRegExp memTotalRegexp(QStringLiteral("MemTotal:\\s*(\\d+) kB\\n"));
92 static QRegExp memFreeRegexp(QStringLiteral("MemFree:\\s*(\\d+) kB\\n"));
93 static QRegExp buffersRegexp(QStringLiteral("Buffers:\\s*(\\d+) kB\\n"));
94 static QRegExp cachedRegexp(QStringLiteral("Cached:\\s*(\\d+) kB\\n"));
95 int parsedTotal = -1;
96 int parsedFree = -1;
97 int parsedBuffers = -1;
98 int parsedCached = -1;
99 while ((parsedTotal == -1) || (parsedFree == -1) ||
100 (parsedBuffers == -1) || (parsedCached == -1)) {
101 QByteArray line = meminfo.readLine();
102 if (line.isEmpty()) {
103 break;
104 }
105 if (memTotalRegexp.exactMatch(line)) {
106 parsedTotal = memTotalRegexp.cap(1).toInt();
107 } else if (memFreeRegexp.exactMatch(line)) {
108 parsedFree = memFreeRegexp.cap(1).toInt();
109 } else if (buffersRegexp.exactMatch(line)) {
110 parsedBuffers = buffersRegexp.cap(1).toInt();
111 } else if (cachedRegexp.exactMatch(line)) {
112 parsedCached = cachedRegexp.cap(1).toInt();
113 }
114 }
115 meminfo.close();
116 if ((parsedTotal != -1) && (parsedFree != -1) &&
117 (parsedBuffers != -1) && (parsedCached != -1)) {
118 bool totalUpdated = false;
119 if (parsedTotal != m_total) {
120 m_total = parsedTotal;
121 totalUpdated = true;
122 }
123 bool freeUpdated = false;
124 int newFree = parsedFree + parsedCached + parsedBuffers;
125 if (newFree != m_free) {
126 m_free = newFree;
127 freeUpdated = true;
128 }
129 if (totalUpdated) {
130 Q_EMIT totalChanged();
131 }
132 if (freeUpdated) {
133 Q_EMIT freeChanged();
134 }
135 }
136#endif // Q_OS_LINUX
137}
0138
=== added file 'src/app/meminfo.h'
--- src/app/meminfo.h 1970-01-01 00:00:00 +0000
+++ src/app/meminfo.h 2016-02-23 11:14:53 +0000
@@ -0,0 +1,65 @@
1/*
2 * Copyright 2016 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
19#ifndef __MEMINFO_H__
20#define __MEMINFO_H__
21
22// Qt
23#include <QtCore/QObject>
24#include <QtCore/QTimer>
25
26class MemInfo : public QObject
27{
28 Q_OBJECT
29
30 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
31 Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY intervalChanged)
32
33 // Expressed in kB
34 Q_PROPERTY(int total READ total NOTIFY totalChanged)
35 Q_PROPERTY(int free READ free NOTIFY freeChanged)
36
37public:
38 MemInfo(QObject* parent=nullptr);
39 ~MemInfo();
40
41 const bool active() const;
42 void setActive(bool active);
43
44 const int interval() const;
45 void setInterval(int interval);
46
47 const int total() const;
48 const int free() const;
49
50Q_SIGNALS:
51 void activeChanged() const;
52 void intervalChanged() const;
53 void totalChanged() const;
54 void freeChanged() const;
55
56private Q_SLOTS:
57 void update();
58
59private:
60 QTimer m_timer;
61 int m_total;
62 int m_free;
63};
64
65#endif // __MEMINFO_H__
066
=== modified file 'src/app/webbrowser/Browser.qml'
--- src/app/webbrowser/Browser.qml 2016-02-15 13:33:11 +0000
+++ src/app/webbrowser/Browser.qml 2016-02-23 11:14:53 +0000
@@ -47,10 +47,6 @@
4747
48 readonly property var tabsModel: incognito ? privateTabsModelLoader.item : publicTabsModel48 readonly property var tabsModel: incognito ? privateTabsModelLoader.item : publicTabsModel
4949
50 // XXX: we might want to tweak this value depending
51 // on the form factor and/or the available memory
52 readonly property int maxLiveWebviews: 2
53
54 // Restore only the n most recent tabs at startup,50 // Restore only the n most recent tabs at startup,
55 // to limit the overhead of instantiating too many51 // to limit the overhead of instantiating too many
56 // tab objects (see http://pad.lv/1376433).52 // tab objects (see http://pad.lv/1376433).
@@ -59,6 +55,10 @@
59 onTabsModelChanged: {55 onTabsModelChanged: {
60 if (incognito && privateTabsModelLoader.item) {56 if (incognito && privateTabsModelLoader.item) {
61 browser.openUrlInNewTab("", true)57 browser.openUrlInNewTab("", true)
58 } else if (!incognito && tabsModel.currentTab) {
59 // If the system is low on memory, the current public tab might
60 // have been unloaded while browsing incognito, so reload it.
61 tabsModel.currentTab.load()
62 }62 }
63 }63 }
6464
@@ -106,6 +106,11 @@
106 deviceFilter: InputInfo.TouchPad106 deviceFilter: InputInfo.TouchPad
107 }107 }
108108
109 InputDeviceModel {
110 id: touchScreenModel
111 deviceFilter: InputInfo.TouchScreen
112 }
113
109 Component {114 Component {
110 id: mediaAccessDialogComponent115 id: mediaAccessDialogComponent
111 MediaAccessDialog { }116 MediaAccessDialog { }
@@ -151,7 +156,6 @@
151156
152 property url homepage: settingsDefaults.homepage157 property url homepage: settingsDefaults.homepage
153 property string searchEngine: settingsDefaults.searchEngine158 property string searchEngine: settingsDefaults.searchEngine
154 property string allowOpenInBackgroundTab: settingsDefaults.allowOpenInBackgroundTab
155 property bool restoreSession: settingsDefaults.restoreSession159 property bool restoreSession: settingsDefaults.restoreSession
156 property int newTabDefaultSection: settingsDefaults.newTabDefaultSection160 property int newTabDefaultSection: settingsDefaults.newTabDefaultSection
157 property string defaultAudioDevice161 property string defaultAudioDevice
@@ -160,7 +164,6 @@
160 function restoreDefaults() {164 function restoreDefaults() {
161 homepage = settingsDefaults.homepage165 homepage = settingsDefaults.homepage
162 searchEngine = settingsDefaults.searchEngine166 searchEngine = settingsDefaults.searchEngine
163 allowOpenInBackgroundTab = settingsDefaults.allowOpenInBackgroundTab
164 restoreSession = settingsDefaults.restoreSession167 restoreSession = settingsDefaults.restoreSession
165 newTabDefaultSection = settingsDefaults.newTabDefaultSection168 newTabDefaultSection = settingsDefaults.newTabDefaultSection
166 defaultAudioDevice = settingsDefaults.defaultAudioDevice169 defaultAudioDevice = settingsDefaults.defaultAudioDevice
@@ -173,7 +176,6 @@
173176
174 readonly property url homepage: "http://start.ubuntu.com"177 readonly property url homepage: "http://start.ubuntu.com"
175 readonly property string searchEngine: "google"178 readonly property string searchEngine: "google"
176 readonly property string allowOpenInBackgroundTab: "default"
177 readonly property bool restoreSession: true179 readonly property bool restoreSession: true
178 readonly property int newTabDefaultSection: 0180 readonly property int newTabDefaultSection: 0
179 readonly property string defaultAudioDevice: ""181 readonly property string defaultAudioDevice: ""
@@ -461,8 +463,9 @@
461 webview: browser.currentWebview463 webview: browser.currentWebview
462 forceHide: browser.fullscreen464 forceHide: browser.fullscreen
463 forceShow: recentView.visible465 forceShow: recentView.visible
464 defaultMode: (formFactor == "desktop") ? Oxide.LocationBarController.ModeShown466 defaultMode: (internal.hasMouse && !internal.hasTouchScreen)
465 : Oxide.LocationBarController.ModeAuto467 ? Oxide.LocationBarController.ModeShown
468 : Oxide.LocationBarController.ModeAuto
466 }469 }
467470
468 Chrome {471 Chrome {
@@ -480,6 +483,8 @@
480483
481 availableHeight: tabContainer.height - height - y484 availableHeight: tabContainer.height - height - y
482485
486 touchEnabled: internal.hasTouchScreen
487
483 property bool hidden: false488 property bool hidden: false
484 y: hidden ? -height : webview ? webview.locationBarController.offset : 0489 y: hidden ? -height : webview ? webview.locationBarController.offset : 0
485 Behavior on y {490 Behavior on y {
@@ -1080,10 +1085,7 @@
1080 }1085 }
1081 Actions.OpenLinkInNewBackgroundTab {1086 Actions.OpenLinkInNewBackgroundTab {
1082 objectName: "OpenLinkInNewBackgroundTabContextualAction"1087 objectName: "OpenLinkInNewBackgroundTabContextualAction"
1083 enabled: contextModel && contextModel.linkUrl.toString() &&1088 enabled: contextModel && contextModel.linkUrl.toString()
1084 ((settings.allowOpenInBackgroundTab === "true") ||
1085 ((settings.allowOpenInBackgroundTab === "default") &&
1086 (formFactor === "desktop")))
1087 onTriggered: browser.openUrlInNewTab(contextModel.linkUrl, false)1089 onTriggered: browser.openUrlInNewTab(contextModel.linkUrl, false)
1088 }1090 }
1089 Actions.BookmarkLink {1091 Actions.BookmarkLink {
@@ -1112,7 +1114,7 @@
1112 }1114 }
1113 Actions.Share {1115 Actions.Share {
1114 objectName: "ShareContextualAction"1116 objectName: "ShareContextualAction"
1115 enabled: (formFactor == "mobile") && contextModel &&1117 enabled: (contentHandlerLoader.status == Loader.Ready) && contextModel &&
1116 (contextModel.linkUrl.toString() || contextModel.selectionText)1118 (contextModel.linkUrl.toString() || contextModel.selectionText)
1117 onTriggered: {1119 onTriggered: {
1118 if (contextModel.linkUrl.toString()) {1120 if (contextModel.linkUrl.toString()) {
@@ -1339,9 +1341,9 @@
1339 color: "white"1341 color: "white"
1340 font.weight: Font.Light1342 font.weight: Font.Light
1341 anchors.centerIn: parent1343 anchors.centerIn: parent
1342 text: (formFactor == "mobile") ?1344 text: bottomEdgeHandle.enabled
1343 i18n.tr("Swipe Up To Exit Full Screen") :1345 ? i18n.tr("Swipe Up To Exit Full Screen")
1344 i18n.tr("Press ESC To Exit Full Screen")1346 : i18n.tr("Press ESC To Exit Full Screen")
1345 }1347 }
13461348
1347 Timer {1349 Timer {
@@ -1453,6 +1455,15 @@
1453 }1455 }
14541456
1455 readonly property bool hasMouse: (miceModel.count + touchPadModel.count) > 01457 readonly property bool hasMouse: (miceModel.count + touchPadModel.count) > 0
1458 readonly property bool hasTouchScreen: touchScreenModel.count > 0
1459
1460 readonly property real freeMemRatio: (MemInfo.total > 0) ? (MemInfo.free / MemInfo.total) : 1.0
1461 // Under that threshold, available memory is considered "low", and the
1462 // browser is going to try and free up memory from unused tabs. This
1463 // value was chosen empirically, it is subject to change to better
1464 // reflect what a system under memory pressure might look like.
1465 readonly property real lowOnMemoryThreshold: 0.3
1466 readonly property bool lowOnMemory: freeMemRatio < lowOnMemoryThreshold
14561467
1457 function getOpenPages() {1468 function getOpenPages() {
1458 var urls = []1469 var urls = []
@@ -1765,11 +1776,12 @@
1765 session.save()1776 session.save()
1766 }1777 }
1767 if (browser.currentWebview) {1778 if (browser.currentWebview) {
1768 // Workaround for a desktop bug where changing volume causes the app to1779 // Workaround for a desktop bug where changing volume causes
1769 // briefly lose focus to notify-osd, and therefore exit fullscreen mode.1780 // the app to briefly lose focus to notify-osd, and therefore
1770 // We prevent this by exiting fullscreen only if the focus remains lost1781 // exit fullscreen mode. We prevent this by exiting fullscreen
1771 // for longer than a certain threshold. See: http://pad.lv/14773081782 // only if the focus remains lost for longer than a certain
1772 if (formFactor == "desktop") exitFullscreenOnLostFocus.start()1783 // threshold. See: https://launchpad.net/bugs/694224.
1784 if (__platformName == "xcb") exitFullscreenOnLostFocus.start()
1773 else browser.currentWebview.fullscreen = false1785 else browser.currentWebview.fullscreen = false
1774 }1786 }
1775 } else exitFullscreenOnLostFocus.stop()1787 } else exitFullscreenOnLostFocus.stop()
@@ -1838,15 +1850,41 @@
1838 }1850 }
18391851
1840 Connections {1852 Connections {
1841 // On mobile, ensure that at most n webviews are instantiated at all1853 target: internal
1842 // times, to reduce memory consumption (see http://pad.lv/1376418).1854 onFreeMemRatioChanged: {
1843 // Note: this works only in narrow mode, where the list of tabs is a1855 if (internal.lowOnMemory) {
1844 // stack. Switching from wide mode to narrow mode will result in1856 // Unload an inactive tab to (hopefully) free up some memory
1845 // undefined behaviour (tabs previously loaded won’t be unloaded).1857 function getCandidate(model) {
1846 target: ((formFactor == "mobile") && !browser.wide) ? tabsModel : null1858 // Naive implementation that only takes into account the
1847 onCurrentTabChanged: {1859 // last time a tab was current. In the future we might
1848 if (tabsModel.count > browser.maxLiveWebviews) {1860 // want to take into account other parameters such as
1849 tabsModel.get(browser.maxLiveWebviews).unload()1861 // whether the tab is currently playing audio/video.
1862 var candidate = null
1863 for (var i = 0; i < model.count; ++i) {
1864 var tab = model.get(i)
1865 if (tab.current || !tab.webview) {
1866 continue
1867 }
1868 if (!candidate || (candidate.lastCurrent > tab.lastCurrent)) {
1869 candidate = tab
1870 }
1871 }
1872 return candidate
1873 }
1874 var candidate = getCandidate(publicTabsModel)
1875 if (candidate) {
1876 console.warn("Unloading background tab (%1) to free up some memory".arg(candidate.url))
1877 candidate.unload()
1878 return
1879 } else if (browser.incognito) {
1880 candidate = getCandidate(privateTabsModelLoader.item)
1881 if (candidate) {
1882 console.warn("Unloading a background incognito tab to free up some memory")
1883 candidate.unload()
1884 return
1885 }
1886 }
1887 console.warn("System low on memory, but unable to pick a tab to unload")
1850 }1888 }
1851 }1889 }
1852 }1890 }
18531891
=== modified file 'src/app/webbrowser/BrowserTab.qml'
--- src/app/webbrowser/BrowserTab.qml 2016-02-11 10:38:44 +0000
+++ src/app/webbrowser/BrowserTab.qml 2016-02-23 11:14:53 +0000
@@ -39,6 +39,7 @@
39 readonly property url icon: webview ? webview.icon : initialIcon39 readonly property url icon: webview ? webview.icon : initialIcon
40 property url preview40 property url preview
41 property bool current: false41 property bool current: false
42 readonly property int lastCurrent: internal.lastCurrent
42 property bool incognito43 property bool incognito
43 visible: false44 visible: false
4445
@@ -126,6 +127,7 @@
126 id: internal127 id: internal
127 property bool hiding: false128 property bool hiding: false
128 property var incubator: null129 property var incubator: null
130 property int lastCurrent: 0
129 }131 }
130132
131 // When current is set to false, delay hiding the tab contents to give it133 // When current is set to false, delay hiding the tab contents to give it
@@ -133,6 +135,7 @@
133 // only if embedders do not set the 'visible' property directly or135 // only if embedders do not set the 'visible' property directly or
134 // indirectly on instances of a BrowserTab.136 // indirectly on instances of a BrowserTab.
135 onCurrentChanged: {137 onCurrentChanged: {
138 internal.lastCurrent = Date.now()
136 if (current) {139 if (current) {
137 internal.hiding = false140 internal.hiding = false
138 z = 1141 z = 1
139142
=== modified file 'src/app/webbrowser/Chrome.qml'
--- src/app/webbrowser/Chrome.qml 2016-01-26 17:44:49 +0000
+++ src/app/webbrowser/Chrome.qml 2016-02-23 11:14:53 +0000
@@ -40,6 +40,7 @@
40 property alias showFaviconInAddressBar: navigationBar.showFaviconInAddressBar40 property alias showFaviconInAddressBar: navigationBar.showFaviconInAddressBar
41 property alias availableHeight: navigationBar.availableHeight41 property alias availableHeight: navigationBar.availableHeight
42 readonly property alias bookmarkTogglePlaceHolder: navigationBar.bookmarkTogglePlaceHolder42 readonly property alias bookmarkTogglePlaceHolder: navigationBar.bookmarkTogglePlaceHolder
43 property bool touchEnabled: true
4344
44 signal switchToTab(int index)45 signal switchToTab(int index)
45 signal requestNewTab(int index, bool makeCurrent)46 signal requestNewTab(int index, bool makeCurrent)
@@ -72,6 +73,7 @@
72 model: tabsModel73 model: tabsModel
73 incognito: chrome.incognito74 incognito: chrome.incognito
74 fgColor: navigationBar.fgColor75 fgColor: navigationBar.fgColor
76 touchEnabled: chrome.touchEnabled
75 onSwitchToTab: chrome.switchToTab(index)77 onSwitchToTab: chrome.switchToTab(index)
76 onRequestNewTab: chrome.requestNewTab(index, makeCurrent)78 onRequestNewTab: chrome.requestNewTab(index, makeCurrent)
77 onTabClosed: chrome.tabClosed(index)79 onTabClosed: chrome.tabClosed(index)
@@ -82,7 +84,7 @@
82 left: parent.left84 left: parent.left
83 right: parent.right85 right: parent.right
84 }86 }
85 height: active ? (formFactor == "desktop" ? units.gu(3) : units.gu(4)) : 087 height: active ? (touchEnabled ? units.gu(4) : units.gu(3)) : 0
86 }88 }
8789
88 NavigationBar {90 NavigationBar {
8991
=== modified file 'src/app/webbrowser/SettingsPage.qml'
--- src/app/webbrowser/SettingsPage.qml 2015-11-30 09:38:08 +0000
+++ src/app/webbrowser/SettingsPage.qml 2016-02-23 11:14:53 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2015 Canonical Ltd.2 * Copyright 2015-2016 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -113,25 +113,6 @@
113 }113 }
114114
115 ListItems.Standard {115 ListItems.Standard {
116 objectName: "backgroundTabs"
117
118 text: i18n.tr("Allow opening new tabs in background")
119 highlightWhenPressed: false
120
121 control: CheckBox {
122 id: allowOpenInBackgroundTabCheckbox
123 onTriggered: settingsObject.allowOpenInBackgroundTab = checked ? 'true' : 'false'
124 }
125
126 Binding {
127 target: allowOpenInBackgroundTabCheckbox
128 property: "checked"
129 value: settingsObject.allowOpenInBackgroundTab === 'true' ||
130 (settingsObject.allowOpenInBackgroundTab === 'default' && formFactor === "desktop")
131 }
132 }
133
134 ListItems.Standard {
135 objectName: "privacy"116 objectName: "privacy"
136117
137 text: i18n.tr("Privacy & permissions")118 text: i18n.tr("Privacy & permissions")
138119
=== modified file 'src/app/webbrowser/TabItem.qml'
--- src/app/webbrowser/TabItem.qml 2016-01-26 17:44:49 +0000
+++ src/app/webbrowser/TabItem.qml 2016-02-23 11:14:53 +0000
@@ -37,6 +37,8 @@
3737
38 property color fgColor: Theme.palette.normal.baseText38 property color fgColor: Theme.palette.normal.baseText
3939
40 property bool touchEnabled: true
41
40 signal selected()42 signal selected()
41 signal closed()43 signal closed()
42 signal contextMenu()44 signal contextMenu()
@@ -47,7 +49,7 @@
47 anchors.rightMargin: tabItem.rightMargin49 anchors.rightMargin: tabItem.rightMargin
48 source: "assets/tab-%1%2.sci".arg((active) ? "active" :50 source: "assets/tab-%1%2.sci".arg((active) ? "active" :
49 (hoverArea.containsMouse ? "hover" : "non-active"))51 (hoverArea.containsMouse ? "hover" : "non-active"))
50 .arg(formFactor == "desktop" ? "-desktop" : "")52 .arg(touchEnabled ? "" : "-desktop")
5153
52 Favicon {54 Favicon {
53 id: favicon55 id: favicon
@@ -121,15 +123,14 @@
121 id: closeButton123 id: closeButton
122 objectName: "closeButton"124 objectName: "closeButton"
123125
124 // On mobile the tap area to close the tab occupies the whole right126 // On touch the tap area to close the tab occupies the whole right
125 // hand side of the tab, while it covers only the close icon in127 // hand side of the tab, while it covers only the close icon in
126 // other form factors128 // other form factors
127 readonly property bool mobile: formFactor == "mobile"129 anchors.fill: touchEnabled ? undefined : closeIcon
128 anchors.fill: mobile ? undefined : closeIcon130 anchors.top: touchEnabled ? parent.top : undefined
129 anchors.top: mobile ? parent.top : undefined131 anchors.bottom: touchEnabled ? parent.bottom : undefined
130 anchors.bottom: mobile ? parent.bottom : undefined132 anchors.right: touchEnabled ? parent.right : undefined
131 anchors.right: mobile ? parent.right : undefined133 width: touchEnabled ? units.gu(4) : closeIcon.width
132 width: mobile ? units.gu(4) : closeIcon.width
133134
134 onClicked: closed()135 onClicked: closed()
135136
136137
=== modified file 'src/app/webbrowser/TabsBar.qml'
--- src/app/webbrowser/TabsBar.qml 2016-01-26 17:44:49 +0000
+++ src/app/webbrowser/TabsBar.qml 2016-02-23 11:14:53 +0000
@@ -34,6 +34,8 @@
3434
35 property color fgColor: Theme.palette.normal.baseText35 property color fgColor: Theme.palette.normal.baseText
3636
37 property bool touchEnabled: true
38
37 signal switchToTab(int index)39 signal switchToTab(int index)
38 signal requestNewTab(int index, bool makeCurrent)40 signal requestNewTab(int index, bool makeCurrent)
39 signal tabClosed(int index)41 signal tabClosed(int index)
@@ -111,7 +113,6 @@
111 anchors {113 anchors {
112 top: parent.top114 top: parent.top
113 bottom: parent.bottom115 bottom: parent.bottom
114 bottomMargin: tabsContainer.verticalGap
115 left: parent.left116 left: parent.left
116 }117 }
117 width: tabWidth * root.model.count118 width: tabWidth * root.model.count
@@ -153,6 +154,8 @@
153 icon: model.icon154 icon: model.icon
154 fgColor: root.fgColor155 fgColor: root.fgColor
155156
157 touchEnabled: root.touchEnabled
158
156 rightMargin: tabDelegate.rightMargin159 rightMargin: tabDelegate.rightMargin
157160
158 onClosed: root.tabClosed(index)161 onClosed: root.tabClosed(index)
159162
=== modified file 'src/app/webbrowser/webbrowser-app.cpp'
--- src/app/webbrowser/webbrowser-app.cpp 2016-01-22 10:23:29 +0000
+++ src/app/webbrowser/webbrowser-app.cpp 2016-02-23 11:14:53 +0000
@@ -82,6 +82,8 @@
82 searchEnginesSearchPaths << UbuntuBrowserDirectory() + "/webbrowser/searchengines";82 searchEnginesSearchPaths << UbuntuBrowserDirectory() + "/webbrowser/searchengines";
83 m_engine->rootContext()->setContextProperty("searchEnginesSearchPaths", searchEnginesSearchPaths);83 m_engine->rootContext()->setContextProperty("searchEnginesSearchPaths", searchEnginesSearchPaths);
8484
85 m_engine->rootContext()->setContextProperty("__platformName", platformName());
86
85 m_window->setProperty("newSession", m_arguments.contains("--new-session"));87 m_window->setProperty("newSession", m_arguments.contains("--new-session"));
8688
87 QVariantList urls;89 QVariantList urls;
8890
=== modified file 'src/app/webcontainer/WebApp.qml'
--- src/app/webcontainer/WebApp.qml 2016-01-08 16:09:01 +0000
+++ src/app/webcontainer/WebApp.qml 2016-02-23 11:14:53 +0000
@@ -250,8 +250,9 @@
250 ChromeController {250 ChromeController {
251 webview: webapp.currentWebview251 webview: webapp.currentWebview
252 forceHide: webapp.chromeless252 forceHide: webapp.chromeless
253 defaultMode: (formFactor == "desktop") ? Oxide.LocationBarController.ModeShown253 defaultMode: webapp.hasTouchScreen
254 : Oxide.LocationBarController.ModeAuto254 ? Oxide.LocationBarController.ModeAuto
255 : Oxide.LocationBarController.ModeShown
255 }256 }
256 }257 }
257258
258259
=== modified file 'src/app/webcontainer/WebViewImplOxide.qml'
--- src/app/webcontainer/WebViewImplOxide.qml 2016-01-08 16:09:01 +0000
+++ src/app/webcontainer/WebViewImplOxide.qml 2016-02-23 11:14:53 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2014-2015 Canonical Ltd.2 * Copyright 2014-2016 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -207,10 +207,6 @@
207 samlRequestUrlPatternReceived(urlPattern)207 samlRequestUrlPatternReceived(urlPattern)
208 }208 }
209209
210 function shouldOpenPopupsInDefaultBrowser() {
211 return formFactor !== "desktop";
212 }
213
214 function isRunningAsANamedWebapp() {210 function isRunningAsANamedWebapp() {
215 return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0211 return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0
216 }212 }
@@ -328,13 +324,12 @@
328 }324 }
329325
330 onGeolocationPermissionRequested: {326 onGeolocationPermissionRequested: {
331 if (formFactor == "desktop") {327 if (__runningConfined && (request.origin == request.embedder)) {
328 // When running confined, querying the location service will trigger
329 // a system prompt (trust store), so no need for a custom one.
330 request.accept()
331 } else {
332 requestGeolocationPermission(request)332 requestGeolocationPermission(request)
333 } else {
334 // On devices where webapps are confined, trying to access the
335 // location service will trigger a system prompt from the trust
336 // store, so we don’t need a custom prompt.
337 request.accept()
338 }333 }
339 }334 }
340335
341336
=== modified file 'tests/autopilot/webbrowser_app/tests/__init__.py'
--- tests/autopilot/webbrowser_app/tests/__init__.py 2016-02-03 11:56:56 +0000
+++ tests/autopilot/webbrowser_app/tests/__init__.py 2016-02-23 11:14:53 +0000
@@ -158,16 +158,11 @@
158 toolbar.click_action("newTabButton")158 toolbar.click_action("newTabButton")
159 tabs_view.visible.wait_for(False)159 tabs_view.visible.wait_for(False)
160160
161 if self.main_window.wide or (model() == 'Desktop'):
162 new_count = count + 1
163 else:
164 max_webviews = self.main_window.maxLiveWebviews
165 new_count = (count + 1) if (count < max_webviews) else max_webviews
166 if (self.main_window.incognito):161 if (self.main_window.incognito):
167 self.assert_number_incognito_webviews_eventually(new_count)162 self.assert_number_incognito_webviews_eventually(count + 1)
168 new_tab_view = self.main_window.get_new_private_tab_view()163 new_tab_view = self.main_window.get_new_private_tab_view()
169 else:164 else:
170 self.assert_number_webviews_eventually(new_count)165 self.assert_number_webviews_eventually(count + 1)
171 new_tab_view = self.main_window.get_new_tab_view()166 new_tab_view = self.main_window.get_new_tab_view()
172167
173 if self.main_window.wide:168 if self.main_window.wide:
174169
=== modified file 'tests/unittests/CMakeLists.txt'
--- tests/unittests/CMakeLists.txt 2016-01-18 14:45:12 +0000
+++ tests/unittests/CMakeLists.txt 2016-02-23 11:14:53 +0000
@@ -22,3 +22,4 @@
22add_subdirectory(text-search-filter-model)22add_subdirectory(text-search-filter-model)
23add_subdirectory(downloads-model)23add_subdirectory(downloads-model)
24add_subdirectory(single-instance-manager)24add_subdirectory(single-instance-manager)
25add_subdirectory(meminfo)
2526
=== added directory 'tests/unittests/meminfo'
=== added file 'tests/unittests/meminfo/CMakeLists.txt'
--- tests/unittests/meminfo/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/unittests/meminfo/CMakeLists.txt 2016-02-23 11:14:53 +0000
@@ -0,0 +1,15 @@
1find_package(Qt5Core REQUIRED)
2find_package(Qt5Test REQUIRED)
3set(TEST tst_MemInfoTests)
4set(SOURCES
5 ${webbrowser-common_SOURCE_DIR}/meminfo.cpp
6 tst_MemInfoTests.cpp
7)
8add_executable(${TEST} ${SOURCES})
9include_directories(${webbrowser-common_SOURCE_DIR})
10target_link_libraries(${TEST}
11 Qt5::Core
12 Qt5::Test
13)
14add_test(${TEST} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} -xunitxml -o ${TEST}.xml)
15set_tests_properties(${TEST} PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
016
=== added file 'tests/unittests/meminfo/tst_MemInfoTests.cpp'
--- tests/unittests/meminfo/tst_MemInfoTests.cpp 1970-01-01 00:00:00 +0000
+++ tests/unittests/meminfo/tst_MemInfoTests.cpp 2016-02-23 11:14:53 +0000
@@ -0,0 +1,100 @@
1/*
2 * Copyright 2016 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
19// Qt
20#include <QtCore/QObject>
21#include <QtTest/QSignalSpy>
22#include <QtTest/QtTest>
23
24// local
25#include "meminfo.h"
26
27class MemInfoTests : public QObject
28{
29 Q_OBJECT
30
31private:
32 MemInfo* meminfo;
33
34private Q_SLOTS:
35 void init()
36 {
37 meminfo = new MemInfo(this);
38 }
39
40 void cleanup()
41 {
42 delete meminfo;
43 }
44
45 void test_active_property()
46 {
47 QVERIFY(meminfo->active());
48 QSignalSpy spy(meminfo, SIGNAL(activeChanged()));
49
50 meminfo->setActive(true);
51 QVERIFY(spy.isEmpty());
52
53 meminfo->setActive(false);
54 QCOMPARE(spy.count(), 1);
55 QVERIFY(!meminfo->active());
56 spy.clear();
57
58 meminfo->setActive(false);
59 QVERIFY(spy.isEmpty());
60
61 meminfo->setActive(true);
62 QCOMPARE(spy.count(), 1);
63 QVERIFY(meminfo->active());
64 }
65
66 void test_interval_property()
67 {
68 QCOMPARE(meminfo->interval(), 5000);
69 QSignalSpy spy(meminfo, SIGNAL(intervalChanged()));
70
71 meminfo->setInterval(5000);
72 QVERIFY(spy.isEmpty());
73
74 meminfo->setInterval(1500);
75 QCOMPARE(spy.count(), 1);
76 QCOMPARE(meminfo->interval(), 1500);
77 }
78
79 void test_initial_values()
80 {
81 QCOMPARE(meminfo->total(), 0);
82 QCOMPARE(meminfo->free(), 0);
83 }
84
85 void test_update()
86 {
87 QSignalSpy totalSpy(meminfo, SIGNAL(totalChanged()));
88 QSignalSpy freeSpy(meminfo, SIGNAL(freeChanged()));
89 meminfo->setInterval(100);
90 totalSpy.wait();
91 freeSpy.wait();
92 QVERIFY(meminfo->total() > 0);
93 QVERIFY(meminfo->free() > 0);
94 QVERIFY(meminfo->total() > meminfo->free());
95 }
96};
97
98QTEST_MAIN(MemInfoTests)
99
100#include "tst_MemInfoTests.moc"

Subscribers

People subscribed via source and target branches

to status/vote changes: