Merge lp:~osomon/webbrowser-app/remove-formFactor into lp:webbrowser-app
- remove-formFactor
- Merge into trunk
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 | ||||||||
Related bugs: |
|
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.
googleapps.mattirn 1.0.1
mynewsapps.mattirn 1.0.4
mywebsites.mattirn 1.0.1
ubuntu.mattirn 1.0.1
wikifoundation
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.
Chris Coulson (chrisccoulson) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1362
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1363
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1364
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandre Abreu (abreu-alexandre) wrote : | # |
Overall looks good, a few questions below
Olivier Tilloy (osomon) wrote : | # |
Thanks for your thorough review, I’ve replied to your questions (with more questions!) inline.
Alexandre Abreu (abreu-alexandre) wrote : | # |
See replies
- 1365. By Olivier Tilloy
-
Document the value of the lowOnMemory threshold.
Olivier Tilloy (osomon) wrote : | # |
Updated.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1365
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1367
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'README' | |||
2 | --- README 2015-04-01 05:57:42 +0000 | |||
3 | +++ README 2016-02-23 11:14:53 +0000 | |||
4 | @@ -86,11 +86,6 @@ | |||
5 | 86 | the OpenSearch document description format | 86 | the OpenSearch document description format |
6 | 87 | (http://www.opensearch.org/Specifications/OpenSearch/1.1) | 87 | (http://www.opensearch.org/Specifications/OpenSearch/1.1) |
7 | 88 | 88 | ||
8 | 89 | - 'allowOpenInBackgroundTab': whether to offer an option to open a link in a | ||
9 | 90 | new background tab in the contextual menu. Possible values are "true", | ||
10 | 91 | "false", and "default" (which resolves to true on desktop and false on | ||
11 | 92 | mobile). | ||
12 | 93 | |||
13 | 94 | - restoreSession: whether to restore the previous browsing session at startup | 89 | - restoreSession: whether to restore the previous browsing session at startup |
14 | 95 | (defaults to true) | 90 | (defaults to true) |
15 | 96 | 91 | ||
16 | 97 | 92 | ||
17 | === modified file 'debian/control' | |||
18 | --- debian/control 2016-01-28 16:23:17 +0000 | |||
19 | +++ debian/control 2016-02-23 11:14:53 +0000 | |||
20 | @@ -10,6 +10,7 @@ | |||
21 | 10 | dh-apparmor, | 10 | dh-apparmor, |
22 | 11 | dh-translations, | 11 | dh-translations, |
23 | 12 | hardening-wrapper, | 12 | hardening-wrapper, |
24 | 13 | libapparmor-dev, | ||
25 | 13 | libevdev-dev, | 14 | libevdev-dev, |
26 | 14 | liboxideqt-qmlplugin (>= 1.9), | 15 | liboxideqt-qmlplugin (>= 1.9), |
27 | 15 | libqt5sql5-sqlite, | 16 | libqt5sql5-sqlite, |
28 | 16 | 17 | ||
29 | === modified file 'src/Ubuntu/Web/UbuntuWebView02.qml' | |||
30 | --- src/Ubuntu/Web/UbuntuWebView02.qml 2016-01-05 08:35:58 +0000 | |||
31 | +++ src/Ubuntu/Web/UbuntuWebView02.qml 2016-02-23 11:14:53 +0000 | |||
32 | @@ -1,5 +1,5 @@ | |||
33 | 1 | /* | 1 | /* |
35 | 2 | * Copyright 2013-2015 Canonical Ltd. | 2 | * Copyright 2013-2016 Canonical Ltd. |
36 | 3 | * | 3 | * |
37 | 4 | * This file is part of webbrowser-app. | 4 | * This file is part of webbrowser-app. |
38 | 5 | * | 5 | * |
39 | @@ -51,7 +51,7 @@ | |||
40 | 51 | navigationRequestedDelegate(request); | 51 | navigationRequestedDelegate(request); |
41 | 52 | } | 52 | } |
42 | 53 | 53 | ||
44 | 54 | preferences.passwordEchoEnabled: formFactor === "mobile" | 54 | preferences.passwordEchoEnabled: Qt.inputMethod.visible |
45 | 55 | 55 | ||
46 | 56 | popupMenu: ItemSelector02 { | 56 | popupMenu: ItemSelector02 { |
47 | 57 | automaticOrientation: false | 57 | automaticOrientation: false |
48 | 58 | 58 | ||
49 | === modified file 'src/Ubuntu/Web/plugin.cpp' | |||
50 | --- src/Ubuntu/Web/plugin.cpp 2015-12-10 22:01:05 +0000 | |||
51 | +++ src/Ubuntu/Web/plugin.cpp 2016-02-23 11:14:53 +0000 | |||
52 | @@ -1,5 +1,5 @@ | |||
53 | 1 | /* | 1 | /* |
55 | 2 | * Copyright 2013-2015 Canonical Ltd. | 2 | * Copyright 2013-2016 Canonical Ltd. |
56 | 3 | * | 3 | * |
57 | 4 | * This file is part of webbrowser-app. | 4 | * This file is part of webbrowser-app. |
58 | 5 | * | 5 | * |
59 | @@ -40,7 +40,6 @@ | |||
60 | 40 | 40 | ||
61 | 41 | Q_PROPERTY(QString cacheLocation READ cacheLocation NOTIFY cacheLocationChanged) | 41 | Q_PROPERTY(QString cacheLocation READ cacheLocation NOTIFY cacheLocationChanged) |
62 | 42 | Q_PROPERTY(QString dataLocation READ dataLocation NOTIFY dataLocationChanged) | 42 | Q_PROPERTY(QString dataLocation READ dataLocation NOTIFY dataLocationChanged) |
63 | 43 | Q_PROPERTY(QString formFactor READ formFactor CONSTANT) | ||
64 | 44 | Q_PROPERTY(qreal screenDiagonal READ screenDiagonal NOTIFY screenDiagonalChanged) | 43 | Q_PROPERTY(qreal screenDiagonal READ screenDiagonal NOTIFY screenDiagonalChanged) |
65 | 45 | Q_PROPERTY(int cacheSizeHint READ cacheSizeHint NOTIFY cacheSizeHintChanged) | 44 | Q_PROPERTY(int cacheSizeHint READ cacheSizeHint NOTIFY cacheSizeHintChanged) |
66 | 46 | Q_PROPERTY(QString webviewDevtoolsDebugHost READ devtoolsHost CONSTANT) | 45 | Q_PROPERTY(QString webviewDevtoolsDebugHost READ devtoolsHost CONSTANT) |
67 | @@ -52,7 +51,6 @@ | |||
68 | 52 | 51 | ||
69 | 53 | QString cacheLocation() const; | 52 | QString cacheLocation() const; |
70 | 54 | QString dataLocation() const; | 53 | QString dataLocation() const; |
71 | 55 | QString formFactor(); | ||
72 | 56 | qreal screenDiagonal() const; | 54 | qreal screenDiagonal() const; |
73 | 57 | int cacheSizeHint() const; | 55 | int cacheSizeHint() const; |
74 | 58 | QString devtoolsHost(); | 56 | QString devtoolsHost(); |
75 | @@ -71,7 +69,6 @@ | |||
76 | 71 | 69 | ||
77 | 72 | private: | 70 | private: |
78 | 73 | qreal m_screenDiagonal; // in millimeters | 71 | qreal m_screenDiagonal; // in millimeters |
79 | 74 | QString m_formFactor; | ||
80 | 75 | QString m_devtoolsHost; | 72 | QString m_devtoolsHost; |
81 | 76 | int m_devtoolsPort; | 73 | int m_devtoolsPort; |
82 | 77 | QStringList m_hostMappingRules; | 74 | QStringList m_hostMappingRules; |
83 | @@ -129,40 +126,6 @@ | |||
84 | 129 | return location.absolutePath(); | 126 | return location.absolutePath(); |
85 | 130 | } | 127 | } |
86 | 131 | 128 | ||
87 | 132 | QString UbuntuWebPluginContext::formFactor() | ||
88 | 133 | { | ||
89 | 134 | if (m_formFactor.isEmpty()) { | ||
90 | 135 | // This implementation only considers two possible form factors: desktop, | ||
91 | 136 | // and mobile (which includes phones and tablets). | ||
92 | 137 | // XXX: do we need to consider other form factors, such as tablet? | ||
93 | 138 | const char* DESKTOP = "desktop"; | ||
94 | 139 | const char* MOBILE = "mobile"; | ||
95 | 140 | |||
96 | 141 | // The "DESKTOP_MODE" environment variable can be used to force the form | ||
97 | 142 | // factor to desktop, when set to any valid value other than 0. | ||
98 | 143 | const char* DESKTOP_MODE_ENV_VAR = "DESKTOP_MODE"; | ||
99 | 144 | if (qEnvironmentVariableIsSet(DESKTOP_MODE_ENV_VAR)) { | ||
100 | 145 | QByteArray stringValue = qgetenv(DESKTOP_MODE_ENV_VAR); | ||
101 | 146 | bool ok = false; | ||
102 | 147 | int value = stringValue.toInt(&ok); | ||
103 | 148 | if (ok) { | ||
104 | 149 | m_formFactor = (value == 0) ? MOBILE : DESKTOP; | ||
105 | 150 | return m_formFactor; | ||
106 | 151 | } | ||
107 | 152 | } | ||
108 | 153 | |||
109 | 154 | // XXX: Assume that QtUbuntu means mobile, which is currently the case, | ||
110 | 155 | // but may not remain true forever. | ||
111 | 156 | QString platform = QGuiApplication::platformName(); | ||
112 | 157 | if ((platform == "ubuntu") || (platform == "ubuntumirclient")) { | ||
113 | 158 | m_formFactor = MOBILE; | ||
114 | 159 | } else { | ||
115 | 160 | m_formFactor = DESKTOP; | ||
116 | 161 | } | ||
117 | 162 | } | ||
118 | 163 | return m_formFactor; | ||
119 | 164 | } | ||
120 | 165 | |||
121 | 166 | qreal UbuntuWebPluginContext::screenDiagonal() const | 129 | qreal UbuntuWebPluginContext::screenDiagonal() const |
122 | 167 | { | 130 | { |
123 | 168 | return m_screenDiagonal; | 131 | return m_screenDiagonal; |
124 | 169 | 132 | ||
125 | === modified file 'src/app/BrowserView.qml' | |||
126 | --- src/app/BrowserView.qml 2016-01-12 09:37:08 +0000 | |||
127 | +++ src/app/BrowserView.qml 2016-02-23 11:14:53 +0000 | |||
128 | @@ -32,6 +32,8 @@ | |||
129 | 32 | 32 | ||
130 | 33 | property var osk: _osk | 33 | property var osk: _osk |
131 | 34 | 34 | ||
132 | 35 | property bool hasTouchScreen: false | ||
133 | 36 | |||
134 | 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/ |
135 | 36 | readonly property bool wide: width >= units.gu(90) | 38 | readonly property bool wide: width >= units.gu(90) |
136 | 37 | 39 | ||
137 | 38 | 40 | ||
138 | === modified file 'src/app/CMakeLists.txt' | |||
139 | --- src/app/CMakeLists.txt 2016-01-28 18:54:35 +0000 | |||
140 | +++ src/app/CMakeLists.txt 2016-02-23 11:14:53 +0000 | |||
141 | @@ -7,6 +7,9 @@ | |||
142 | 7 | find_package(Qt5Quick REQUIRED) | 7 | find_package(Qt5Quick REQUIRED) |
143 | 8 | find_package(Qt5Widgets REQUIRED) | 8 | find_package(Qt5Widgets REQUIRED) |
144 | 9 | 9 | ||
145 | 10 | include(FindPkgConfig) | ||
146 | 11 | pkg_check_modules(LIBAPPARMOR REQUIRED libapparmor) | ||
147 | 12 | |||
148 | 10 | add_subdirectory(unity8) | 13 | add_subdirectory(unity8) |
149 | 11 | 14 | ||
150 | 12 | configure_file( | 15 | configure_file( |
151 | @@ -19,6 +22,7 @@ | |||
152 | 19 | set(COMMONLIB_SRC | 22 | set(COMMONLIB_SRC |
153 | 20 | browserapplication.cpp | 23 | browserapplication.cpp |
154 | 21 | favicon-fetcher.cpp | 24 | favicon-fetcher.cpp |
155 | 25 | meminfo.cpp | ||
156 | 22 | mime-database.cpp | 26 | mime-database.cpp |
157 | 23 | session-storage.cpp | 27 | session-storage.cpp |
158 | 24 | single-instance-manager.cpp | 28 | single-instance-manager.cpp |
159 | @@ -28,7 +32,8 @@ | |||
160 | 28 | add_library(${COMMONLIB} STATIC ${COMMONLIB_SRC}) | 32 | add_library(${COMMONLIB} STATIC ${COMMONLIB_SRC}) |
161 | 29 | 33 | ||
162 | 30 | include_directories(${unity8_SOURCE_DIR}/libs/UbuntuGestures | 34 | include_directories(${unity8_SOURCE_DIR}/libs/UbuntuGestures |
164 | 31 | ${unity8_SOURCE_DIR}/plugins) | 35 | ${unity8_SOURCE_DIR}/plugins |
165 | 36 | ${LIBAPPARMOR_INCLUDE_DIRS}) | ||
166 | 32 | target_link_libraries(${COMMONLIB} | 37 | target_link_libraries(${COMMONLIB} |
167 | 33 | Qt5::Core | 38 | Qt5::Core |
168 | 34 | Qt5::Gui | 39 | Qt5::Gui |
169 | @@ -38,6 +43,7 @@ | |||
170 | 38 | Qt5::Widgets | 43 | Qt5::Widgets |
171 | 39 | UbuntuGesturesQml | 44 | UbuntuGesturesQml |
172 | 40 | InputInfo | 45 | InputInfo |
173 | 46 | ${LIBAPPARMOR_LDFLAGS} | ||
174 | 41 | ) | 47 | ) |
175 | 42 | 48 | ||
176 | 43 | file(GLOB QML_FILES *.qml) | 49 | file(GLOB QML_FILES *.qml) |
177 | 44 | 50 | ||
178 | === modified file 'src/app/browserapplication.cpp' | |||
179 | --- src/app/browserapplication.cpp 2016-01-28 18:54:35 +0000 | |||
180 | +++ src/app/browserapplication.cpp 2016-02-23 11:14:53 +0000 | |||
181 | @@ -16,9 +16,15 @@ | |||
182 | 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/>. |
183 | 17 | */ | 17 | */ |
184 | 18 | 18 | ||
185 | 19 | // system | ||
186 | 20 | #include <cerrno> | ||
187 | 21 | #include <cstring> | ||
188 | 22 | #include <sys/apparmor.h> | ||
189 | 23 | |||
190 | 19 | // Qt | 24 | // Qt |
191 | 20 | #include <QtCore/QMetaObject> | 25 | #include <QtCore/QMetaObject> |
192 | 21 | #include <QtCore/QtGlobal> | 26 | #include <QtCore/QtGlobal> |
193 | 27 | #include <QtGui/QTouchDevice> | ||
194 | 22 | #include <QtNetwork/QNetworkInterface> | 28 | #include <QtNetwork/QNetworkInterface> |
195 | 23 | #include <QtQml/QQmlComponent> | 29 | #include <QtQml/QQmlComponent> |
196 | 24 | #include <QtQml/QQmlContext> | 30 | #include <QtQml/QQmlContext> |
197 | @@ -30,6 +36,7 @@ | |||
198 | 30 | #include "browserapplication.h" | 36 | #include "browserapplication.h" |
199 | 31 | #include "config.h" | 37 | #include "config.h" |
200 | 32 | #include "favicon-fetcher.h" | 38 | #include "favicon-fetcher.h" |
201 | 39 | #include "meminfo.h" | ||
202 | 33 | #include "mime-database.h" | 40 | #include "mime-database.h" |
203 | 34 | #include "session-storage.h" | 41 | #include "session-storage.h" |
204 | 35 | #include "webbrowser-window.h" | 42 | #include "webbrowser-window.h" |
205 | @@ -100,19 +107,17 @@ | |||
206 | 100 | return QString(); | 107 | return QString(); |
207 | 101 | } | 108 | } |
208 | 102 | 109 | ||
222 | 103 | static QObject* MimeDatabase_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | 110 | #define MAKE_SINGLETON_FACTORY(type) \ |
223 | 104 | { | 111 | static QObject* type##_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) { \ |
224 | 105 | Q_UNUSED(engine); | 112 | Q_UNUSED(engine); \ |
225 | 106 | Q_UNUSED(scriptEngine); | 113 | Q_UNUSED(scriptEngine); \ |
226 | 107 | return new MimeDatabase(); | 114 | return new type(); \ |
227 | 108 | } | 115 | } |
228 | 109 | 116 | ||
229 | 110 | static QObject* Direction_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | 117 | MAKE_SINGLETON_FACTORY(MemInfo) |
230 | 111 | { | 118 | MAKE_SINGLETON_FACTORY(MimeDatabase) |
231 | 112 | Q_UNUSED(engine); | 119 | MAKE_SINGLETON_FACTORY(Direction) |
232 | 113 | Q_UNUSED(scriptEngine); | 120 | |
220 | 114 | return new Direction(); | ||
221 | 115 | } | ||
233 | 116 | 121 | ||
234 | 117 | bool BrowserApplication::initialize(const QString& qmlFileSubPath) | 122 | bool BrowserApplication::initialize(const QString& qmlFileSubPath) |
235 | 118 | { | 123 | { |
236 | @@ -149,6 +154,18 @@ | |||
237 | 149 | return false; | 154 | return false; |
238 | 150 | } | 155 | } |
239 | 151 | 156 | ||
240 | 157 | bool runningConfined = true; | ||
241 | 158 | char* label; | ||
242 | 159 | char* mode; | ||
243 | 160 | if (aa_getcon(&label, &mode) != -1) { | ||
244 | 161 | if (strcmp(label, "unconfined") == 0) { | ||
245 | 162 | runningConfined = false; | ||
246 | 163 | } | ||
247 | 164 | free(label); | ||
248 | 165 | } else if (errno == EINVAL) { | ||
249 | 166 | runningConfined = false; | ||
250 | 167 | } | ||
251 | 168 | |||
252 | 152 | QString devtoolsPort = inspectorPort(); | 169 | QString devtoolsPort = inspectorPort(); |
253 | 153 | QString devtoolsHost = inspectorHost(); | 170 | QString devtoolsHost = inspectorHost(); |
254 | 154 | bool inspectorEnabled = !devtoolsPort.isEmpty(); | 171 | bool inspectorEnabled = !devtoolsPort.isEmpty(); |
255 | @@ -159,6 +176,7 @@ | |||
256 | 159 | 176 | ||
257 | 160 | const char* uri = "webbrowsercommon.private"; | 177 | const char* uri = "webbrowsercommon.private"; |
258 | 161 | qmlRegisterType<FaviconFetcher>(uri, 0, 1, "FaviconFetcher"); | 178 | qmlRegisterType<FaviconFetcher>(uri, 0, 1, "FaviconFetcher"); |
259 | 179 | qmlRegisterSingletonType<MemInfo>(uri, 0, 1, "MemInfo", MemInfo_singleton_factory); | ||
260 | 162 | qmlRegisterSingletonType<MimeDatabase>(uri, 0, 1, "MimeDatabase", MimeDatabase_singleton_factory); | 180 | qmlRegisterSingletonType<MimeDatabase>(uri, 0, 1, "MimeDatabase", MimeDatabase_singleton_factory); |
261 | 163 | qmlRegisterType<SessionStorage>(uri, 0, 1, "SessionStorage"); | 181 | qmlRegisterType<SessionStorage>(uri, 0, 1, "SessionStorage"); |
262 | 164 | 182 | ||
263 | @@ -179,6 +197,9 @@ | |||
264 | 179 | qmlEngineCreated(m_engine); | 197 | qmlEngineCreated(m_engine); |
265 | 180 | 198 | ||
266 | 181 | QQmlContext* context = m_engine->rootContext(); | 199 | QQmlContext* context = m_engine->rootContext(); |
267 | 200 | context->setContextProperty("__runningConfined", runningConfined); | ||
268 | 201 | context->setContextProperty("unversionedAppId", unversionedAppId); | ||
269 | 202 | |||
270 | 182 | m_component = new QQmlComponent(m_engine); | 203 | m_component = new QQmlComponent(m_engine); |
271 | 183 | m_component->loadUrl(QUrl::fromLocalFile(UbuntuBrowserDirectory() + "/" + qmlFileSubPath)); | 204 | m_component->loadUrl(QUrl::fromLocalFile(UbuntuBrowserDirectory() + "/" + qmlFileSubPath)); |
272 | 184 | if (!m_component->isReady()) { | 205 | if (!m_component->isReady()) { |
273 | @@ -187,7 +208,6 @@ | |||
274 | 187 | } | 208 | } |
275 | 188 | m_webbrowserWindowProxy = new WebBrowserWindow(); | 209 | m_webbrowserWindowProxy = new WebBrowserWindow(); |
276 | 189 | context->setContextProperty("webbrowserWindowProxy", m_webbrowserWindowProxy); | 210 | context->setContextProperty("webbrowserWindowProxy", m_webbrowserWindowProxy); |
277 | 190 | context->setContextProperty("unversionedAppId", unversionedAppId); | ||
278 | 191 | 211 | ||
279 | 192 | QObject* browser = m_component->beginCreate(context); | 212 | QObject* browser = m_component->beginCreate(context); |
280 | 193 | m_window = qobject_cast<QQuickWindow*>(browser); | 213 | m_window = qobject_cast<QQuickWindow*>(browser); |
281 | @@ -198,6 +218,14 @@ | |||
282 | 198 | browser->setProperty("developerExtrasEnabled", inspectorEnabled); | 218 | browser->setProperty("developerExtrasEnabled", inspectorEnabled); |
283 | 199 | browser->setProperty("forceFullscreen", m_arguments.contains("--fullscreen")); | 219 | browser->setProperty("forceFullscreen", m_arguments.contains("--fullscreen")); |
284 | 200 | 220 | ||
285 | 221 | bool hasTouchScreen = false; | ||
286 | 222 | Q_FOREACH(const QTouchDevice* device, QTouchDevice::devices()) { | ||
287 | 223 | if (device->type() == QTouchDevice::TouchScreen) { | ||
288 | 224 | hasTouchScreen = true; | ||
289 | 225 | } | ||
290 | 226 | } | ||
291 | 227 | browser->setProperty("hasTouchScreen", hasTouchScreen); | ||
292 | 228 | |||
293 | 201 | return true; | 229 | return true; |
294 | 202 | } | 230 | } |
295 | 203 | 231 | ||
296 | 204 | 232 | ||
297 | === added file 'src/app/meminfo.cpp' | |||
298 | --- src/app/meminfo.cpp 1970-01-01 00:00:00 +0000 | |||
299 | +++ src/app/meminfo.cpp 2016-02-23 11:14:53 +0000 | |||
300 | @@ -0,0 +1,137 @@ | |||
301 | 1 | /* | ||
302 | 2 | * Copyright 2016 Canonical Ltd. | ||
303 | 3 | * | ||
304 | 4 | * This file is part of webbrowser-app. | ||
305 | 5 | * | ||
306 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
307 | 7 | * it under the terms of the GNU General Public License as published by | ||
308 | 8 | * the Free Software Foundation; version 3. | ||
309 | 9 | * | ||
310 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
311 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
312 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
313 | 13 | * GNU General Public License for more details. | ||
314 | 14 | * | ||
315 | 15 | * You should have received a copy of the GNU General Public License | ||
316 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
317 | 17 | */ | ||
318 | 18 | |||
319 | 19 | #include "meminfo.h" | ||
320 | 20 | |||
321 | 21 | // Qt | ||
322 | 22 | #include <QtCore/QByteArray> | ||
323 | 23 | #include <QtCore/QFile> | ||
324 | 24 | #include <QtCore/QRegExp> | ||
325 | 25 | #include <QtCore/QString> | ||
326 | 26 | #include <QtCore/QtGlobal> | ||
327 | 27 | |||
328 | 28 | MemInfo::MemInfo(QObject* parent) | ||
329 | 29 | : QObject(parent) | ||
330 | 30 | , m_total(0) | ||
331 | 31 | , m_free(0) | ||
332 | 32 | { | ||
333 | 33 | // Default interval: 5000 ms | ||
334 | 34 | m_timer.setInterval(5000); | ||
335 | 35 | connect(&m_timer, SIGNAL(timeout()), SLOT(update())); | ||
336 | 36 | // Active by default | ||
337 | 37 | m_timer.start(); | ||
338 | 38 | } | ||
339 | 39 | |||
340 | 40 | MemInfo::~MemInfo() | ||
341 | 41 | {} | ||
342 | 42 | |||
343 | 43 | const bool MemInfo::active() const | ||
344 | 44 | { | ||
345 | 45 | return m_timer.isActive(); | ||
346 | 46 | } | ||
347 | 47 | |||
348 | 48 | void MemInfo::setActive(bool active) | ||
349 | 49 | { | ||
350 | 50 | if (active != m_timer.isActive()) { | ||
351 | 51 | if (active) { | ||
352 | 52 | m_timer.start(); | ||
353 | 53 | } else { | ||
354 | 54 | m_timer.stop(); | ||
355 | 55 | } | ||
356 | 56 | Q_EMIT activeChanged(); | ||
357 | 57 | } | ||
358 | 58 | } | ||
359 | 59 | |||
360 | 60 | const int MemInfo::interval() const | ||
361 | 61 | { | ||
362 | 62 | return m_timer.interval(); | ||
363 | 63 | } | ||
364 | 64 | |||
365 | 65 | void MemInfo::setInterval(int interval) | ||
366 | 66 | { | ||
367 | 67 | if (interval != m_timer.interval()) { | ||
368 | 68 | m_timer.setInterval(interval); | ||
369 | 69 | Q_EMIT intervalChanged(); | ||
370 | 70 | } | ||
371 | 71 | } | ||
372 | 72 | |||
373 | 73 | const int MemInfo::total() const | ||
374 | 74 | { | ||
375 | 75 | return m_total; | ||
376 | 76 | } | ||
377 | 77 | |||
378 | 78 | const int MemInfo::free() const | ||
379 | 79 | { | ||
380 | 80 | return m_free; | ||
381 | 81 | } | ||
382 | 82 | |||
383 | 83 | void MemInfo::update() | ||
384 | 84 | { | ||
385 | 85 | #if defined(Q_OS_LINUX) | ||
386 | 86 | // Inspired by glibtop_get_mem_s() | ||
387 | 87 | QFile meminfo(QStringLiteral("/proc/meminfo")); | ||
388 | 88 | if (!meminfo.open(QIODevice::ReadOnly)) { | ||
389 | 89 | return; | ||
390 | 90 | } | ||
391 | 91 | static QRegExp memTotalRegexp(QStringLiteral("MemTotal:\\s*(\\d+) kB\\n")); | ||
392 | 92 | static QRegExp memFreeRegexp(QStringLiteral("MemFree:\\s*(\\d+) kB\\n")); | ||
393 | 93 | static QRegExp buffersRegexp(QStringLiteral("Buffers:\\s*(\\d+) kB\\n")); | ||
394 | 94 | static QRegExp cachedRegexp(QStringLiteral("Cached:\\s*(\\d+) kB\\n")); | ||
395 | 95 | int parsedTotal = -1; | ||
396 | 96 | int parsedFree = -1; | ||
397 | 97 | int parsedBuffers = -1; | ||
398 | 98 | int parsedCached = -1; | ||
399 | 99 | while ((parsedTotal == -1) || (parsedFree == -1) || | ||
400 | 100 | (parsedBuffers == -1) || (parsedCached == -1)) { | ||
401 | 101 | QByteArray line = meminfo.readLine(); | ||
402 | 102 | if (line.isEmpty()) { | ||
403 | 103 | break; | ||
404 | 104 | } | ||
405 | 105 | if (memTotalRegexp.exactMatch(line)) { | ||
406 | 106 | parsedTotal = memTotalRegexp.cap(1).toInt(); | ||
407 | 107 | } else if (memFreeRegexp.exactMatch(line)) { | ||
408 | 108 | parsedFree = memFreeRegexp.cap(1).toInt(); | ||
409 | 109 | } else if (buffersRegexp.exactMatch(line)) { | ||
410 | 110 | parsedBuffers = buffersRegexp.cap(1).toInt(); | ||
411 | 111 | } else if (cachedRegexp.exactMatch(line)) { | ||
412 | 112 | parsedCached = cachedRegexp.cap(1).toInt(); | ||
413 | 113 | } | ||
414 | 114 | } | ||
415 | 115 | meminfo.close(); | ||
416 | 116 | if ((parsedTotal != -1) && (parsedFree != -1) && | ||
417 | 117 | (parsedBuffers != -1) && (parsedCached != -1)) { | ||
418 | 118 | bool totalUpdated = false; | ||
419 | 119 | if (parsedTotal != m_total) { | ||
420 | 120 | m_total = parsedTotal; | ||
421 | 121 | totalUpdated = true; | ||
422 | 122 | } | ||
423 | 123 | bool freeUpdated = false; | ||
424 | 124 | int newFree = parsedFree + parsedCached + parsedBuffers; | ||
425 | 125 | if (newFree != m_free) { | ||
426 | 126 | m_free = newFree; | ||
427 | 127 | freeUpdated = true; | ||
428 | 128 | } | ||
429 | 129 | if (totalUpdated) { | ||
430 | 130 | Q_EMIT totalChanged(); | ||
431 | 131 | } | ||
432 | 132 | if (freeUpdated) { | ||
433 | 133 | Q_EMIT freeChanged(); | ||
434 | 134 | } | ||
435 | 135 | } | ||
436 | 136 | #endif // Q_OS_LINUX | ||
437 | 137 | } | ||
438 | 0 | 138 | ||
439 | === added file 'src/app/meminfo.h' | |||
440 | --- src/app/meminfo.h 1970-01-01 00:00:00 +0000 | |||
441 | +++ src/app/meminfo.h 2016-02-23 11:14:53 +0000 | |||
442 | @@ -0,0 +1,65 @@ | |||
443 | 1 | /* | ||
444 | 2 | * Copyright 2016 Canonical Ltd. | ||
445 | 3 | * | ||
446 | 4 | * This file is part of webbrowser-app. | ||
447 | 5 | * | ||
448 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
449 | 7 | * it under the terms of the GNU General Public License as published by | ||
450 | 8 | * the Free Software Foundation; version 3. | ||
451 | 9 | * | ||
452 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
453 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
454 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
455 | 13 | * GNU General Public License for more details. | ||
456 | 14 | * | ||
457 | 15 | * You should have received a copy of the GNU General Public License | ||
458 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
459 | 17 | */ | ||
460 | 18 | |||
461 | 19 | #ifndef __MEMINFO_H__ | ||
462 | 20 | #define __MEMINFO_H__ | ||
463 | 21 | |||
464 | 22 | // Qt | ||
465 | 23 | #include <QtCore/QObject> | ||
466 | 24 | #include <QtCore/QTimer> | ||
467 | 25 | |||
468 | 26 | class MemInfo : public QObject | ||
469 | 27 | { | ||
470 | 28 | Q_OBJECT | ||
471 | 29 | |||
472 | 30 | Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) | ||
473 | 31 | Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY intervalChanged) | ||
474 | 32 | |||
475 | 33 | // Expressed in kB | ||
476 | 34 | Q_PROPERTY(int total READ total NOTIFY totalChanged) | ||
477 | 35 | Q_PROPERTY(int free READ free NOTIFY freeChanged) | ||
478 | 36 | |||
479 | 37 | public: | ||
480 | 38 | MemInfo(QObject* parent=nullptr); | ||
481 | 39 | ~MemInfo(); | ||
482 | 40 | |||
483 | 41 | const bool active() const; | ||
484 | 42 | void setActive(bool active); | ||
485 | 43 | |||
486 | 44 | const int interval() const; | ||
487 | 45 | void setInterval(int interval); | ||
488 | 46 | |||
489 | 47 | const int total() const; | ||
490 | 48 | const int free() const; | ||
491 | 49 | |||
492 | 50 | Q_SIGNALS: | ||
493 | 51 | void activeChanged() const; | ||
494 | 52 | void intervalChanged() const; | ||
495 | 53 | void totalChanged() const; | ||
496 | 54 | void freeChanged() const; | ||
497 | 55 | |||
498 | 56 | private Q_SLOTS: | ||
499 | 57 | void update(); | ||
500 | 58 | |||
501 | 59 | private: | ||
502 | 60 | QTimer m_timer; | ||
503 | 61 | int m_total; | ||
504 | 62 | int m_free; | ||
505 | 63 | }; | ||
506 | 64 | |||
507 | 65 | #endif // __MEMINFO_H__ | ||
508 | 0 | 66 | ||
509 | === modified file 'src/app/webbrowser/Browser.qml' | |||
510 | --- src/app/webbrowser/Browser.qml 2016-02-15 13:33:11 +0000 | |||
511 | +++ src/app/webbrowser/Browser.qml 2016-02-23 11:14:53 +0000 | |||
512 | @@ -47,10 +47,6 @@ | |||
513 | 47 | 47 | ||
514 | 48 | readonly property var tabsModel: incognito ? privateTabsModelLoader.item : publicTabsModel | 48 | readonly property var tabsModel: incognito ? privateTabsModelLoader.item : publicTabsModel |
515 | 49 | 49 | ||
516 | 50 | // XXX: we might want to tweak this value depending | ||
517 | 51 | // on the form factor and/or the available memory | ||
518 | 52 | readonly property int maxLiveWebviews: 2 | ||
519 | 53 | |||
520 | 54 | // Restore only the n most recent tabs at startup, | 50 | // Restore only the n most recent tabs at startup, |
521 | 55 | // to limit the overhead of instantiating too many | 51 | // to limit the overhead of instantiating too many |
522 | 56 | // tab objects (see http://pad.lv/1376433). | 52 | // tab objects (see http://pad.lv/1376433). |
523 | @@ -59,6 +55,10 @@ | |||
524 | 59 | onTabsModelChanged: { | 55 | onTabsModelChanged: { |
525 | 60 | if (incognito && privateTabsModelLoader.item) { | 56 | if (incognito && privateTabsModelLoader.item) { |
526 | 61 | browser.openUrlInNewTab("", true) | 57 | browser.openUrlInNewTab("", true) |
527 | 58 | } else if (!incognito && tabsModel.currentTab) { | ||
528 | 59 | // If the system is low on memory, the current public tab might | ||
529 | 60 | // have been unloaded while browsing incognito, so reload it. | ||
530 | 61 | tabsModel.currentTab.load() | ||
531 | 62 | } | 62 | } |
532 | 63 | } | 63 | } |
533 | 64 | 64 | ||
534 | @@ -106,6 +106,11 @@ | |||
535 | 106 | deviceFilter: InputInfo.TouchPad | 106 | deviceFilter: InputInfo.TouchPad |
536 | 107 | } | 107 | } |
537 | 108 | 108 | ||
538 | 109 | InputDeviceModel { | ||
539 | 110 | id: touchScreenModel | ||
540 | 111 | deviceFilter: InputInfo.TouchScreen | ||
541 | 112 | } | ||
542 | 113 | |||
543 | 109 | Component { | 114 | Component { |
544 | 110 | id: mediaAccessDialogComponent | 115 | id: mediaAccessDialogComponent |
545 | 111 | MediaAccessDialog { } | 116 | MediaAccessDialog { } |
546 | @@ -151,7 +156,6 @@ | |||
547 | 151 | 156 | ||
548 | 152 | property url homepage: settingsDefaults.homepage | 157 | property url homepage: settingsDefaults.homepage |
549 | 153 | property string searchEngine: settingsDefaults.searchEngine | 158 | property string searchEngine: settingsDefaults.searchEngine |
550 | 154 | property string allowOpenInBackgroundTab: settingsDefaults.allowOpenInBackgroundTab | ||
551 | 155 | property bool restoreSession: settingsDefaults.restoreSession | 159 | property bool restoreSession: settingsDefaults.restoreSession |
552 | 156 | property int newTabDefaultSection: settingsDefaults.newTabDefaultSection | 160 | property int newTabDefaultSection: settingsDefaults.newTabDefaultSection |
553 | 157 | property string defaultAudioDevice | 161 | property string defaultAudioDevice |
554 | @@ -160,7 +164,6 @@ | |||
555 | 160 | function restoreDefaults() { | 164 | function restoreDefaults() { |
556 | 161 | homepage = settingsDefaults.homepage | 165 | homepage = settingsDefaults.homepage |
557 | 162 | searchEngine = settingsDefaults.searchEngine | 166 | searchEngine = settingsDefaults.searchEngine |
558 | 163 | allowOpenInBackgroundTab = settingsDefaults.allowOpenInBackgroundTab | ||
559 | 164 | restoreSession = settingsDefaults.restoreSession | 167 | restoreSession = settingsDefaults.restoreSession |
560 | 165 | newTabDefaultSection = settingsDefaults.newTabDefaultSection | 168 | newTabDefaultSection = settingsDefaults.newTabDefaultSection |
561 | 166 | defaultAudioDevice = settingsDefaults.defaultAudioDevice | 169 | defaultAudioDevice = settingsDefaults.defaultAudioDevice |
562 | @@ -173,7 +176,6 @@ | |||
563 | 173 | 176 | ||
564 | 174 | readonly property url homepage: "http://start.ubuntu.com" | 177 | readonly property url homepage: "http://start.ubuntu.com" |
565 | 175 | readonly property string searchEngine: "google" | 178 | readonly property string searchEngine: "google" |
566 | 176 | readonly property string allowOpenInBackgroundTab: "default" | ||
567 | 177 | readonly property bool restoreSession: true | 179 | readonly property bool restoreSession: true |
568 | 178 | readonly property int newTabDefaultSection: 0 | 180 | readonly property int newTabDefaultSection: 0 |
569 | 179 | readonly property string defaultAudioDevice: "" | 181 | readonly property string defaultAudioDevice: "" |
570 | @@ -461,8 +463,9 @@ | |||
571 | 461 | webview: browser.currentWebview | 463 | webview: browser.currentWebview |
572 | 462 | forceHide: browser.fullscreen | 464 | forceHide: browser.fullscreen |
573 | 463 | forceShow: recentView.visible | 465 | forceShow: recentView.visible |
576 | 464 | defaultMode: (formFactor == "desktop") ? Oxide.LocationBarController.ModeShown | 466 | defaultMode: (internal.hasMouse && !internal.hasTouchScreen) |
577 | 465 | : Oxide.LocationBarController.ModeAuto | 467 | ? Oxide.LocationBarController.ModeShown |
578 | 468 | : Oxide.LocationBarController.ModeAuto | ||
579 | 466 | } | 469 | } |
580 | 467 | 470 | ||
581 | 468 | Chrome { | 471 | Chrome { |
582 | @@ -480,6 +483,8 @@ | |||
583 | 480 | 483 | ||
584 | 481 | availableHeight: tabContainer.height - height - y | 484 | availableHeight: tabContainer.height - height - y |
585 | 482 | 485 | ||
586 | 486 | touchEnabled: internal.hasTouchScreen | ||
587 | 487 | |||
588 | 483 | property bool hidden: false | 488 | property bool hidden: false |
589 | 484 | y: hidden ? -height : webview ? webview.locationBarController.offset : 0 | 489 | y: hidden ? -height : webview ? webview.locationBarController.offset : 0 |
590 | 485 | Behavior on y { | 490 | Behavior on y { |
591 | @@ -1080,10 +1085,7 @@ | |||
592 | 1080 | } | 1085 | } |
593 | 1081 | Actions.OpenLinkInNewBackgroundTab { | 1086 | Actions.OpenLinkInNewBackgroundTab { |
594 | 1082 | objectName: "OpenLinkInNewBackgroundTabContextualAction" | 1087 | objectName: "OpenLinkInNewBackgroundTabContextualAction" |
599 | 1083 | enabled: contextModel && contextModel.linkUrl.toString() && | 1088 | enabled: contextModel && contextModel.linkUrl.toString() |
596 | 1084 | ((settings.allowOpenInBackgroundTab === "true") || | ||
597 | 1085 | ((settings.allowOpenInBackgroundTab === "default") && | ||
598 | 1086 | (formFactor === "desktop"))) | ||
600 | 1087 | onTriggered: browser.openUrlInNewTab(contextModel.linkUrl, false) | 1089 | onTriggered: browser.openUrlInNewTab(contextModel.linkUrl, false) |
601 | 1088 | } | 1090 | } |
602 | 1089 | Actions.BookmarkLink { | 1091 | Actions.BookmarkLink { |
603 | @@ -1112,7 +1114,7 @@ | |||
604 | 1112 | } | 1114 | } |
605 | 1113 | Actions.Share { | 1115 | Actions.Share { |
606 | 1114 | objectName: "ShareContextualAction" | 1116 | objectName: "ShareContextualAction" |
608 | 1115 | enabled: (formFactor == "mobile") && contextModel && | 1117 | enabled: (contentHandlerLoader.status == Loader.Ready) && contextModel && |
609 | 1116 | (contextModel.linkUrl.toString() || contextModel.selectionText) | 1118 | (contextModel.linkUrl.toString() || contextModel.selectionText) |
610 | 1117 | onTriggered: { | 1119 | onTriggered: { |
611 | 1118 | if (contextModel.linkUrl.toString()) { | 1120 | if (contextModel.linkUrl.toString()) { |
612 | @@ -1339,9 +1341,9 @@ | |||
613 | 1339 | color: "white" | 1341 | color: "white" |
614 | 1340 | font.weight: Font.Light | 1342 | font.weight: Font.Light |
615 | 1341 | anchors.centerIn: parent | 1343 | anchors.centerIn: parent |
619 | 1342 | text: (formFactor == "mobile") ? | 1344 | text: bottomEdgeHandle.enabled |
620 | 1343 | i18n.tr("Swipe Up To Exit Full Screen") : | 1345 | ? i18n.tr("Swipe Up To Exit Full Screen") |
621 | 1344 | i18n.tr("Press ESC To Exit Full Screen") | 1346 | : i18n.tr("Press ESC To Exit Full Screen") |
622 | 1345 | } | 1347 | } |
623 | 1346 | 1348 | ||
624 | 1347 | Timer { | 1349 | Timer { |
625 | @@ -1453,6 +1455,15 @@ | |||
626 | 1453 | } | 1455 | } |
627 | 1454 | 1456 | ||
628 | 1455 | readonly property bool hasMouse: (miceModel.count + touchPadModel.count) > 0 | 1457 | readonly property bool hasMouse: (miceModel.count + touchPadModel.count) > 0 |
629 | 1458 | readonly property bool hasTouchScreen: touchScreenModel.count > 0 | ||
630 | 1459 | |||
631 | 1460 | readonly property real freeMemRatio: (MemInfo.total > 0) ? (MemInfo.free / MemInfo.total) : 1.0 | ||
632 | 1461 | // Under that threshold, available memory is considered "low", and the | ||
633 | 1462 | // browser is going to try and free up memory from unused tabs. This | ||
634 | 1463 | // value was chosen empirically, it is subject to change to better | ||
635 | 1464 | // reflect what a system under memory pressure might look like. | ||
636 | 1465 | readonly property real lowOnMemoryThreshold: 0.3 | ||
637 | 1466 | readonly property bool lowOnMemory: freeMemRatio < lowOnMemoryThreshold | ||
638 | 1456 | 1467 | ||
639 | 1457 | function getOpenPages() { | 1468 | function getOpenPages() { |
640 | 1458 | var urls = [] | 1469 | var urls = [] |
641 | @@ -1765,11 +1776,12 @@ | |||
642 | 1765 | session.save() | 1776 | session.save() |
643 | 1766 | } | 1777 | } |
644 | 1767 | if (browser.currentWebview) { | 1778 | if (browser.currentWebview) { |
650 | 1768 | // Workaround for a desktop bug where changing volume causes the app to | 1779 | // Workaround for a desktop bug where changing volume causes |
651 | 1769 | // briefly lose focus to notify-osd, and therefore exit fullscreen mode. | 1780 | // the app to briefly lose focus to notify-osd, and therefore |
652 | 1770 | // We prevent this by exiting fullscreen only if the focus remains lost | 1781 | // exit fullscreen mode. We prevent this by exiting fullscreen |
653 | 1771 | // for longer than a certain threshold. See: http://pad.lv/1477308 | 1782 | // only if the focus remains lost for longer than a certain |
654 | 1772 | if (formFactor == "desktop") exitFullscreenOnLostFocus.start() | 1783 | // threshold. See: https://launchpad.net/bugs/694224. |
655 | 1784 | if (__platformName == "xcb") exitFullscreenOnLostFocus.start() | ||
656 | 1773 | else browser.currentWebview.fullscreen = false | 1785 | else browser.currentWebview.fullscreen = false |
657 | 1774 | } | 1786 | } |
658 | 1775 | } else exitFullscreenOnLostFocus.stop() | 1787 | } else exitFullscreenOnLostFocus.stop() |
659 | @@ -1838,15 +1850,41 @@ | |||
660 | 1838 | } | 1850 | } |
661 | 1839 | 1851 | ||
662 | 1840 | Connections { | 1852 | Connections { |
672 | 1841 | // On mobile, ensure that at most n webviews are instantiated at all | 1853 | target: internal |
673 | 1842 | // times, to reduce memory consumption (see http://pad.lv/1376418). | 1854 | onFreeMemRatioChanged: { |
674 | 1843 | // Note: this works only in narrow mode, where the list of tabs is a | 1855 | if (internal.lowOnMemory) { |
675 | 1844 | // stack. Switching from wide mode to narrow mode will result in | 1856 | // Unload an inactive tab to (hopefully) free up some memory |
676 | 1845 | // undefined behaviour (tabs previously loaded won’t be unloaded). | 1857 | function getCandidate(model) { |
677 | 1846 | target: ((formFactor == "mobile") && !browser.wide) ? tabsModel : null | 1858 | // Naive implementation that only takes into account the |
678 | 1847 | onCurrentTabChanged: { | 1859 | // last time a tab was current. In the future we might |
679 | 1848 | if (tabsModel.count > browser.maxLiveWebviews) { | 1860 | // want to take into account other parameters such as |
680 | 1849 | tabsModel.get(browser.maxLiveWebviews).unload() | 1861 | // whether the tab is currently playing audio/video. |
681 | 1862 | var candidate = null | ||
682 | 1863 | for (var i = 0; i < model.count; ++i) { | ||
683 | 1864 | var tab = model.get(i) | ||
684 | 1865 | if (tab.current || !tab.webview) { | ||
685 | 1866 | continue | ||
686 | 1867 | } | ||
687 | 1868 | if (!candidate || (candidate.lastCurrent > tab.lastCurrent)) { | ||
688 | 1869 | candidate = tab | ||
689 | 1870 | } | ||
690 | 1871 | } | ||
691 | 1872 | return candidate | ||
692 | 1873 | } | ||
693 | 1874 | var candidate = getCandidate(publicTabsModel) | ||
694 | 1875 | if (candidate) { | ||
695 | 1876 | console.warn("Unloading background tab (%1) to free up some memory".arg(candidate.url)) | ||
696 | 1877 | candidate.unload() | ||
697 | 1878 | return | ||
698 | 1879 | } else if (browser.incognito) { | ||
699 | 1880 | candidate = getCandidate(privateTabsModelLoader.item) | ||
700 | 1881 | if (candidate) { | ||
701 | 1882 | console.warn("Unloading a background incognito tab to free up some memory") | ||
702 | 1883 | candidate.unload() | ||
703 | 1884 | return | ||
704 | 1885 | } | ||
705 | 1886 | } | ||
706 | 1887 | console.warn("System low on memory, but unable to pick a tab to unload") | ||
707 | 1850 | } | 1888 | } |
708 | 1851 | } | 1889 | } |
709 | 1852 | } | 1890 | } |
710 | 1853 | 1891 | ||
711 | === modified file 'src/app/webbrowser/BrowserTab.qml' | |||
712 | --- src/app/webbrowser/BrowserTab.qml 2016-02-11 10:38:44 +0000 | |||
713 | +++ src/app/webbrowser/BrowserTab.qml 2016-02-23 11:14:53 +0000 | |||
714 | @@ -39,6 +39,7 @@ | |||
715 | 39 | readonly property url icon: webview ? webview.icon : initialIcon | 39 | readonly property url icon: webview ? webview.icon : initialIcon |
716 | 40 | property url preview | 40 | property url preview |
717 | 41 | property bool current: false | 41 | property bool current: false |
718 | 42 | readonly property int lastCurrent: internal.lastCurrent | ||
719 | 42 | property bool incognito | 43 | property bool incognito |
720 | 43 | visible: false | 44 | visible: false |
721 | 44 | 45 | ||
722 | @@ -126,6 +127,7 @@ | |||
723 | 126 | id: internal | 127 | id: internal |
724 | 127 | property bool hiding: false | 128 | property bool hiding: false |
725 | 128 | property var incubator: null | 129 | property var incubator: null |
726 | 130 | property int lastCurrent: 0 | ||
727 | 129 | } | 131 | } |
728 | 130 | 132 | ||
729 | 131 | // When current is set to false, delay hiding the tab contents to give it | 133 | // When current is set to false, delay hiding the tab contents to give it |
730 | @@ -133,6 +135,7 @@ | |||
731 | 133 | // only if embedders do not set the 'visible' property directly or | 135 | // only if embedders do not set the 'visible' property directly or |
732 | 134 | // indirectly on instances of a BrowserTab. | 136 | // indirectly on instances of a BrowserTab. |
733 | 135 | onCurrentChanged: { | 137 | onCurrentChanged: { |
734 | 138 | internal.lastCurrent = Date.now() | ||
735 | 136 | if (current) { | 139 | if (current) { |
736 | 137 | internal.hiding = false | 140 | internal.hiding = false |
737 | 138 | z = 1 | 141 | z = 1 |
738 | 139 | 142 | ||
739 | === modified file 'src/app/webbrowser/Chrome.qml' | |||
740 | --- src/app/webbrowser/Chrome.qml 2016-01-26 17:44:49 +0000 | |||
741 | +++ src/app/webbrowser/Chrome.qml 2016-02-23 11:14:53 +0000 | |||
742 | @@ -40,6 +40,7 @@ | |||
743 | 40 | property alias showFaviconInAddressBar: navigationBar.showFaviconInAddressBar | 40 | property alias showFaviconInAddressBar: navigationBar.showFaviconInAddressBar |
744 | 41 | property alias availableHeight: navigationBar.availableHeight | 41 | property alias availableHeight: navigationBar.availableHeight |
745 | 42 | readonly property alias bookmarkTogglePlaceHolder: navigationBar.bookmarkTogglePlaceHolder | 42 | readonly property alias bookmarkTogglePlaceHolder: navigationBar.bookmarkTogglePlaceHolder |
746 | 43 | property bool touchEnabled: true | ||
747 | 43 | 44 | ||
748 | 44 | signal switchToTab(int index) | 45 | signal switchToTab(int index) |
749 | 45 | signal requestNewTab(int index, bool makeCurrent) | 46 | signal requestNewTab(int index, bool makeCurrent) |
750 | @@ -72,6 +73,7 @@ | |||
751 | 72 | model: tabsModel | 73 | model: tabsModel |
752 | 73 | incognito: chrome.incognito | 74 | incognito: chrome.incognito |
753 | 74 | fgColor: navigationBar.fgColor | 75 | fgColor: navigationBar.fgColor |
754 | 76 | touchEnabled: chrome.touchEnabled | ||
755 | 75 | onSwitchToTab: chrome.switchToTab(index) | 77 | onSwitchToTab: chrome.switchToTab(index) |
756 | 76 | onRequestNewTab: chrome.requestNewTab(index, makeCurrent) | 78 | onRequestNewTab: chrome.requestNewTab(index, makeCurrent) |
757 | 77 | onTabClosed: chrome.tabClosed(index) | 79 | onTabClosed: chrome.tabClosed(index) |
758 | @@ -82,7 +84,7 @@ | |||
759 | 82 | left: parent.left | 84 | left: parent.left |
760 | 83 | right: parent.right | 85 | right: parent.right |
761 | 84 | } | 86 | } |
763 | 85 | height: active ? (formFactor == "desktop" ? units.gu(3) : units.gu(4)) : 0 | 87 | height: active ? (touchEnabled ? units.gu(4) : units.gu(3)) : 0 |
764 | 86 | } | 88 | } |
765 | 87 | 89 | ||
766 | 88 | NavigationBar { | 90 | NavigationBar { |
767 | 89 | 91 | ||
768 | === modified file 'src/app/webbrowser/SettingsPage.qml' | |||
769 | --- src/app/webbrowser/SettingsPage.qml 2015-11-30 09:38:08 +0000 | |||
770 | +++ src/app/webbrowser/SettingsPage.qml 2016-02-23 11:14:53 +0000 | |||
771 | @@ -1,5 +1,5 @@ | |||
772 | 1 | /* | 1 | /* |
774 | 2 | * Copyright 2015 Canonical Ltd. | 2 | * Copyright 2015-2016 Canonical Ltd. |
775 | 3 | * | 3 | * |
776 | 4 | * This file is part of webbrowser-app. | 4 | * This file is part of webbrowser-app. |
777 | 5 | * | 5 | * |
778 | @@ -113,25 +113,6 @@ | |||
779 | 113 | } | 113 | } |
780 | 114 | 114 | ||
781 | 115 | ListItems.Standard { | 115 | ListItems.Standard { |
782 | 116 | objectName: "backgroundTabs" | ||
783 | 117 | |||
784 | 118 | text: i18n.tr("Allow opening new tabs in background") | ||
785 | 119 | highlightWhenPressed: false | ||
786 | 120 | |||
787 | 121 | control: CheckBox { | ||
788 | 122 | id: allowOpenInBackgroundTabCheckbox | ||
789 | 123 | onTriggered: settingsObject.allowOpenInBackgroundTab = checked ? 'true' : 'false' | ||
790 | 124 | } | ||
791 | 125 | |||
792 | 126 | Binding { | ||
793 | 127 | target: allowOpenInBackgroundTabCheckbox | ||
794 | 128 | property: "checked" | ||
795 | 129 | value: settingsObject.allowOpenInBackgroundTab === 'true' || | ||
796 | 130 | (settingsObject.allowOpenInBackgroundTab === 'default' && formFactor === "desktop") | ||
797 | 131 | } | ||
798 | 132 | } | ||
799 | 133 | |||
800 | 134 | ListItems.Standard { | ||
801 | 135 | objectName: "privacy" | 116 | objectName: "privacy" |
802 | 136 | 117 | ||
803 | 137 | text: i18n.tr("Privacy & permissions") | 118 | text: i18n.tr("Privacy & permissions") |
804 | 138 | 119 | ||
805 | === modified file 'src/app/webbrowser/TabItem.qml' | |||
806 | --- src/app/webbrowser/TabItem.qml 2016-01-26 17:44:49 +0000 | |||
807 | +++ src/app/webbrowser/TabItem.qml 2016-02-23 11:14:53 +0000 | |||
808 | @@ -37,6 +37,8 @@ | |||
809 | 37 | 37 | ||
810 | 38 | property color fgColor: Theme.palette.normal.baseText | 38 | property color fgColor: Theme.palette.normal.baseText |
811 | 39 | 39 | ||
812 | 40 | property bool touchEnabled: true | ||
813 | 41 | |||
814 | 40 | signal selected() | 42 | signal selected() |
815 | 41 | signal closed() | 43 | signal closed() |
816 | 42 | signal contextMenu() | 44 | signal contextMenu() |
817 | @@ -47,7 +49,7 @@ | |||
818 | 47 | anchors.rightMargin: tabItem.rightMargin | 49 | anchors.rightMargin: tabItem.rightMargin |
819 | 48 | source: "assets/tab-%1%2.sci".arg((active) ? "active" : | 50 | source: "assets/tab-%1%2.sci".arg((active) ? "active" : |
820 | 49 | (hoverArea.containsMouse ? "hover" : "non-active")) | 51 | (hoverArea.containsMouse ? "hover" : "non-active")) |
822 | 50 | .arg(formFactor == "desktop" ? "-desktop" : "") | 52 | .arg(touchEnabled ? "" : "-desktop") |
823 | 51 | 53 | ||
824 | 52 | Favicon { | 54 | Favicon { |
825 | 53 | id: favicon | 55 | id: favicon |
826 | @@ -121,15 +123,14 @@ | |||
827 | 121 | id: closeButton | 123 | id: closeButton |
828 | 122 | objectName: "closeButton" | 124 | objectName: "closeButton" |
829 | 123 | 125 | ||
831 | 124 | // On mobile the tap area to close the tab occupies the whole right | 126 | // On touch the tap area to close the tab occupies the whole right |
832 | 125 | // hand side of the tab, while it covers only the close icon in | 127 | // hand side of the tab, while it covers only the close icon in |
833 | 126 | // other form factors | 128 | // other form factors |
840 | 127 | readonly property bool mobile: formFactor == "mobile" | 129 | anchors.fill: touchEnabled ? undefined : closeIcon |
841 | 128 | anchors.fill: mobile ? undefined : closeIcon | 130 | anchors.top: touchEnabled ? parent.top : undefined |
842 | 129 | anchors.top: mobile ? parent.top : undefined | 131 | anchors.bottom: touchEnabled ? parent.bottom : undefined |
843 | 130 | anchors.bottom: mobile ? parent.bottom : undefined | 132 | anchors.right: touchEnabled ? parent.right : undefined |
844 | 131 | anchors.right: mobile ? parent.right : undefined | 133 | width: touchEnabled ? units.gu(4) : closeIcon.width |
839 | 132 | width: mobile ? units.gu(4) : closeIcon.width | ||
845 | 133 | 134 | ||
846 | 134 | onClicked: closed() | 135 | onClicked: closed() |
847 | 135 | 136 | ||
848 | 136 | 137 | ||
849 | === modified file 'src/app/webbrowser/TabsBar.qml' | |||
850 | --- src/app/webbrowser/TabsBar.qml 2016-01-26 17:44:49 +0000 | |||
851 | +++ src/app/webbrowser/TabsBar.qml 2016-02-23 11:14:53 +0000 | |||
852 | @@ -34,6 +34,8 @@ | |||
853 | 34 | 34 | ||
854 | 35 | property color fgColor: Theme.palette.normal.baseText | 35 | property color fgColor: Theme.palette.normal.baseText |
855 | 36 | 36 | ||
856 | 37 | property bool touchEnabled: true | ||
857 | 38 | |||
858 | 37 | signal switchToTab(int index) | 39 | signal switchToTab(int index) |
859 | 38 | signal requestNewTab(int index, bool makeCurrent) | 40 | signal requestNewTab(int index, bool makeCurrent) |
860 | 39 | signal tabClosed(int index) | 41 | signal tabClosed(int index) |
861 | @@ -111,7 +113,6 @@ | |||
862 | 111 | anchors { | 113 | anchors { |
863 | 112 | top: parent.top | 114 | top: parent.top |
864 | 113 | bottom: parent.bottom | 115 | bottom: parent.bottom |
865 | 114 | bottomMargin: tabsContainer.verticalGap | ||
866 | 115 | left: parent.left | 116 | left: parent.left |
867 | 116 | } | 117 | } |
868 | 117 | width: tabWidth * root.model.count | 118 | width: tabWidth * root.model.count |
869 | @@ -153,6 +154,8 @@ | |||
870 | 153 | icon: model.icon | 154 | icon: model.icon |
871 | 154 | fgColor: root.fgColor | 155 | fgColor: root.fgColor |
872 | 155 | 156 | ||
873 | 157 | touchEnabled: root.touchEnabled | ||
874 | 158 | |||
875 | 156 | rightMargin: tabDelegate.rightMargin | 159 | rightMargin: tabDelegate.rightMargin |
876 | 157 | 160 | ||
877 | 158 | onClosed: root.tabClosed(index) | 161 | onClosed: root.tabClosed(index) |
878 | 159 | 162 | ||
879 | === modified file 'src/app/webbrowser/webbrowser-app.cpp' | |||
880 | --- src/app/webbrowser/webbrowser-app.cpp 2016-01-22 10:23:29 +0000 | |||
881 | +++ src/app/webbrowser/webbrowser-app.cpp 2016-02-23 11:14:53 +0000 | |||
882 | @@ -82,6 +82,8 @@ | |||
883 | 82 | searchEnginesSearchPaths << UbuntuBrowserDirectory() + "/webbrowser/searchengines"; | 82 | searchEnginesSearchPaths << UbuntuBrowserDirectory() + "/webbrowser/searchengines"; |
884 | 83 | m_engine->rootContext()->setContextProperty("searchEnginesSearchPaths", searchEnginesSearchPaths); | 83 | m_engine->rootContext()->setContextProperty("searchEnginesSearchPaths", searchEnginesSearchPaths); |
885 | 84 | 84 | ||
886 | 85 | m_engine->rootContext()->setContextProperty("__platformName", platformName()); | ||
887 | 86 | |||
888 | 85 | m_window->setProperty("newSession", m_arguments.contains("--new-session")); | 87 | m_window->setProperty("newSession", m_arguments.contains("--new-session")); |
889 | 86 | 88 | ||
890 | 87 | QVariantList urls; | 89 | QVariantList urls; |
891 | 88 | 90 | ||
892 | === modified file 'src/app/webcontainer/WebApp.qml' | |||
893 | --- src/app/webcontainer/WebApp.qml 2016-01-08 16:09:01 +0000 | |||
894 | +++ src/app/webcontainer/WebApp.qml 2016-02-23 11:14:53 +0000 | |||
895 | @@ -250,8 +250,9 @@ | |||
896 | 250 | ChromeController { | 250 | ChromeController { |
897 | 251 | webview: webapp.currentWebview | 251 | webview: webapp.currentWebview |
898 | 252 | forceHide: webapp.chromeless | 252 | forceHide: webapp.chromeless |
901 | 253 | defaultMode: (formFactor == "desktop") ? Oxide.LocationBarController.ModeShown | 253 | defaultMode: webapp.hasTouchScreen |
902 | 254 | : Oxide.LocationBarController.ModeAuto | 254 | ? Oxide.LocationBarController.ModeAuto |
903 | 255 | : Oxide.LocationBarController.ModeShown | ||
904 | 255 | } | 256 | } |
905 | 256 | } | 257 | } |
906 | 257 | 258 | ||
907 | 258 | 259 | ||
908 | === modified file 'src/app/webcontainer/WebViewImplOxide.qml' | |||
909 | --- src/app/webcontainer/WebViewImplOxide.qml 2016-01-08 16:09:01 +0000 | |||
910 | +++ src/app/webcontainer/WebViewImplOxide.qml 2016-02-23 11:14:53 +0000 | |||
911 | @@ -1,5 +1,5 @@ | |||
912 | 1 | /* | 1 | /* |
914 | 2 | * Copyright 2014-2015 Canonical Ltd. | 2 | * Copyright 2014-2016 Canonical Ltd. |
915 | 3 | * | 3 | * |
916 | 4 | * This file is part of webbrowser-app. | 4 | * This file is part of webbrowser-app. |
917 | 5 | * | 5 | * |
918 | @@ -207,10 +207,6 @@ | |||
919 | 207 | samlRequestUrlPatternReceived(urlPattern) | 207 | samlRequestUrlPatternReceived(urlPattern) |
920 | 208 | } | 208 | } |
921 | 209 | 209 | ||
922 | 210 | function shouldOpenPopupsInDefaultBrowser() { | ||
923 | 211 | return formFactor !== "desktop"; | ||
924 | 212 | } | ||
925 | 213 | |||
926 | 214 | function isRunningAsANamedWebapp() { | 210 | function isRunningAsANamedWebapp() { |
927 | 215 | return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0 | 211 | return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0 |
928 | 216 | } | 212 | } |
929 | @@ -328,13 +324,12 @@ | |||
930 | 328 | } | 324 | } |
931 | 329 | 325 | ||
932 | 330 | onGeolocationPermissionRequested: { | 326 | onGeolocationPermissionRequested: { |
934 | 331 | if (formFactor == "desktop") { | 327 | if (__runningConfined && (request.origin == request.embedder)) { |
935 | 328 | // When running confined, querying the location service will trigger | ||
936 | 329 | // a system prompt (trust store), so no need for a custom one. | ||
937 | 330 | request.accept() | ||
938 | 331 | } else { | ||
939 | 332 | requestGeolocationPermission(request) | 332 | requestGeolocationPermission(request) |
940 | 333 | } else { | ||
941 | 334 | // On devices where webapps are confined, trying to access the | ||
942 | 335 | // location service will trigger a system prompt from the trust | ||
943 | 336 | // store, so we don’t need a custom prompt. | ||
944 | 337 | request.accept() | ||
945 | 338 | } | 333 | } |
946 | 339 | } | 334 | } |
947 | 340 | 335 | ||
948 | 341 | 336 | ||
949 | === modified file 'tests/autopilot/webbrowser_app/tests/__init__.py' | |||
950 | --- tests/autopilot/webbrowser_app/tests/__init__.py 2016-02-03 11:56:56 +0000 | |||
951 | +++ tests/autopilot/webbrowser_app/tests/__init__.py 2016-02-23 11:14:53 +0000 | |||
952 | @@ -158,16 +158,11 @@ | |||
953 | 158 | toolbar.click_action("newTabButton") | 158 | toolbar.click_action("newTabButton") |
954 | 159 | tabs_view.visible.wait_for(False) | 159 | tabs_view.visible.wait_for(False) |
955 | 160 | 160 | ||
956 | 161 | if self.main_window.wide or (model() == 'Desktop'): | ||
957 | 162 | new_count = count + 1 | ||
958 | 163 | else: | ||
959 | 164 | max_webviews = self.main_window.maxLiveWebviews | ||
960 | 165 | new_count = (count + 1) if (count < max_webviews) else max_webviews | ||
961 | 166 | if (self.main_window.incognito): | 161 | if (self.main_window.incognito): |
963 | 167 | self.assert_number_incognito_webviews_eventually(new_count) | 162 | self.assert_number_incognito_webviews_eventually(count + 1) |
964 | 168 | new_tab_view = self.main_window.get_new_private_tab_view() | 163 | new_tab_view = self.main_window.get_new_private_tab_view() |
965 | 169 | else: | 164 | else: |
967 | 170 | self.assert_number_webviews_eventually(new_count) | 165 | self.assert_number_webviews_eventually(count + 1) |
968 | 171 | new_tab_view = self.main_window.get_new_tab_view() | 166 | new_tab_view = self.main_window.get_new_tab_view() |
969 | 172 | 167 | ||
970 | 173 | if self.main_window.wide: | 168 | if self.main_window.wide: |
971 | 174 | 169 | ||
972 | === modified file 'tests/unittests/CMakeLists.txt' | |||
973 | --- tests/unittests/CMakeLists.txt 2016-01-18 14:45:12 +0000 | |||
974 | +++ tests/unittests/CMakeLists.txt 2016-02-23 11:14:53 +0000 | |||
975 | @@ -22,3 +22,4 @@ | |||
976 | 22 | add_subdirectory(text-search-filter-model) | 22 | add_subdirectory(text-search-filter-model) |
977 | 23 | add_subdirectory(downloads-model) | 23 | add_subdirectory(downloads-model) |
978 | 24 | add_subdirectory(single-instance-manager) | 24 | add_subdirectory(single-instance-manager) |
979 | 25 | add_subdirectory(meminfo) | ||
980 | 25 | 26 | ||
981 | === added directory 'tests/unittests/meminfo' | |||
982 | === added file 'tests/unittests/meminfo/CMakeLists.txt' | |||
983 | --- tests/unittests/meminfo/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
984 | +++ tests/unittests/meminfo/CMakeLists.txt 2016-02-23 11:14:53 +0000 | |||
985 | @@ -0,0 +1,15 @@ | |||
986 | 1 | find_package(Qt5Core REQUIRED) | ||
987 | 2 | find_package(Qt5Test REQUIRED) | ||
988 | 3 | set(TEST tst_MemInfoTests) | ||
989 | 4 | set(SOURCES | ||
990 | 5 | ${webbrowser-common_SOURCE_DIR}/meminfo.cpp | ||
991 | 6 | tst_MemInfoTests.cpp | ||
992 | 7 | ) | ||
993 | 8 | add_executable(${TEST} ${SOURCES}) | ||
994 | 9 | include_directories(${webbrowser-common_SOURCE_DIR}) | ||
995 | 10 | target_link_libraries(${TEST} | ||
996 | 11 | Qt5::Core | ||
997 | 12 | Qt5::Test | ||
998 | 13 | ) | ||
999 | 14 | add_test(${TEST} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} -xunitxml -o ${TEST}.xml) | ||
1000 | 15 | set_tests_properties(${TEST} PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal") | ||
1001 | 0 | 16 | ||
1002 | === added file 'tests/unittests/meminfo/tst_MemInfoTests.cpp' | |||
1003 | --- tests/unittests/meminfo/tst_MemInfoTests.cpp 1970-01-01 00:00:00 +0000 | |||
1004 | +++ tests/unittests/meminfo/tst_MemInfoTests.cpp 2016-02-23 11:14:53 +0000 | |||
1005 | @@ -0,0 +1,100 @@ | |||
1006 | 1 | /* | ||
1007 | 2 | * Copyright 2016 Canonical Ltd. | ||
1008 | 3 | * | ||
1009 | 4 | * This file is part of webbrowser-app. | ||
1010 | 5 | * | ||
1011 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
1012 | 7 | * it under the terms of the GNU General Public License as published by | ||
1013 | 8 | * the Free Software Foundation; version 3. | ||
1014 | 9 | * | ||
1015 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
1016 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1017 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1018 | 13 | * GNU General Public License for more details. | ||
1019 | 14 | * | ||
1020 | 15 | * You should have received a copy of the GNU General Public License | ||
1021 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1022 | 17 | */ | ||
1023 | 18 | |||
1024 | 19 | // Qt | ||
1025 | 20 | #include <QtCore/QObject> | ||
1026 | 21 | #include <QtTest/QSignalSpy> | ||
1027 | 22 | #include <QtTest/QtTest> | ||
1028 | 23 | |||
1029 | 24 | // local | ||
1030 | 25 | #include "meminfo.h" | ||
1031 | 26 | |||
1032 | 27 | class MemInfoTests : public QObject | ||
1033 | 28 | { | ||
1034 | 29 | Q_OBJECT | ||
1035 | 30 | |||
1036 | 31 | private: | ||
1037 | 32 | MemInfo* meminfo; | ||
1038 | 33 | |||
1039 | 34 | private Q_SLOTS: | ||
1040 | 35 | void init() | ||
1041 | 36 | { | ||
1042 | 37 | meminfo = new MemInfo(this); | ||
1043 | 38 | } | ||
1044 | 39 | |||
1045 | 40 | void cleanup() | ||
1046 | 41 | { | ||
1047 | 42 | delete meminfo; | ||
1048 | 43 | } | ||
1049 | 44 | |||
1050 | 45 | void test_active_property() | ||
1051 | 46 | { | ||
1052 | 47 | QVERIFY(meminfo->active()); | ||
1053 | 48 | QSignalSpy spy(meminfo, SIGNAL(activeChanged())); | ||
1054 | 49 | |||
1055 | 50 | meminfo->setActive(true); | ||
1056 | 51 | QVERIFY(spy.isEmpty()); | ||
1057 | 52 | |||
1058 | 53 | meminfo->setActive(false); | ||
1059 | 54 | QCOMPARE(spy.count(), 1); | ||
1060 | 55 | QVERIFY(!meminfo->active()); | ||
1061 | 56 | spy.clear(); | ||
1062 | 57 | |||
1063 | 58 | meminfo->setActive(false); | ||
1064 | 59 | QVERIFY(spy.isEmpty()); | ||
1065 | 60 | |||
1066 | 61 | meminfo->setActive(true); | ||
1067 | 62 | QCOMPARE(spy.count(), 1); | ||
1068 | 63 | QVERIFY(meminfo->active()); | ||
1069 | 64 | } | ||
1070 | 65 | |||
1071 | 66 | void test_interval_property() | ||
1072 | 67 | { | ||
1073 | 68 | QCOMPARE(meminfo->interval(), 5000); | ||
1074 | 69 | QSignalSpy spy(meminfo, SIGNAL(intervalChanged())); | ||
1075 | 70 | |||
1076 | 71 | meminfo->setInterval(5000); | ||
1077 | 72 | QVERIFY(spy.isEmpty()); | ||
1078 | 73 | |||
1079 | 74 | meminfo->setInterval(1500); | ||
1080 | 75 | QCOMPARE(spy.count(), 1); | ||
1081 | 76 | QCOMPARE(meminfo->interval(), 1500); | ||
1082 | 77 | } | ||
1083 | 78 | |||
1084 | 79 | void test_initial_values() | ||
1085 | 80 | { | ||
1086 | 81 | QCOMPARE(meminfo->total(), 0); | ||
1087 | 82 | QCOMPARE(meminfo->free(), 0); | ||
1088 | 83 | } | ||
1089 | 84 | |||
1090 | 85 | void test_update() | ||
1091 | 86 | { | ||
1092 | 87 | QSignalSpy totalSpy(meminfo, SIGNAL(totalChanged())); | ||
1093 | 88 | QSignalSpy freeSpy(meminfo, SIGNAL(freeChanged())); | ||
1094 | 89 | meminfo->setInterval(100); | ||
1095 | 90 | totalSpy.wait(); | ||
1096 | 91 | freeSpy.wait(); | ||
1097 | 92 | QVERIFY(meminfo->total() > 0); | ||
1098 | 93 | QVERIFY(meminfo->free() > 0); | ||
1099 | 94 | QVERIFY(meminfo->total() > meminfo->free()); | ||
1100 | 95 | } | ||
1101 | 96 | }; | ||
1102 | 97 | |||
1103 | 98 | QTEST_MAIN(MemInfoTests) | ||
1104 | 99 | |||
1105 | 100 | #include "tst_MemInfoTests.moc" |
I've added a comment inline to this