Merge lp:~abreu-alexandre/webbrowser-app/xenial-fix-application-name-setup into lp:webbrowser-app/xenial

Proposed by Alexandre Abreu
Status: Needs review
Proposed branch: lp:~abreu-alexandre/webbrowser-app/xenial-fix-application-name-setup
Merge into: lp:webbrowser-app/xenial
Diff against target: 316 lines (+110/-37)
10 files modified
src/app/browserapplication.cpp (+32/-24)
src/app/browserapplication.h (+1/-2)
src/app/config.h.in (+0/-1)
src/app/single-instance-manager.cpp (+39/-3)
src/app/single-instance-manager.h (+1/-1)
src/app/webbrowser/webbrowser-app.cpp (+1/-1)
src/app/webcontainer/webapp-container.cpp (+27/-1)
src/app/webcontainer/webapp-container.h (+1/-0)
tests/autopilot/webapp_container/tests/__init__.py (+4/-0)
tests/unittests/single-instance-manager/tst_SingleInstanceManagerTests.cpp (+4/-4)
To merge this branch: bzr merge lp:~abreu-alexandre/webbrowser-app/xenial-fix-application-name-setup
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+294395@code.launchpad.net

Commit message

Fix container/webbrowser app_id; Properly set applicationname based on package name and app name

Description of the change

Fix container/webbrowser app_id; Properly set applicationname based on package name and app name

To post a comment you must log in.

Unmerged revisions

1418. By Alexandre Abreu

Fix container/webbrowser app_id; Properly set applicationname based on package name and app name

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app/browserapplication.cpp'
2--- src/app/browserapplication.cpp 2016-03-29 11:01:18 +0000
3+++ src/app/browserapplication.cpp 2016-05-11 16:04:27 +0000
4@@ -98,16 +98,6 @@
5 return host;
6 }
7
8-QString BrowserApplication::appId() const
9-{
10- Q_FOREACH(const QString& argument, m_arguments) {
11- if (argument.startsWith("--app-id=")) {
12- return argument.split("--app-id=")[1];
13- }
14- }
15- return QString();
16-}
17-
18 #define MAKE_SINGLETON_FACTORY(type) \
19 static QObject* type##_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) { \
20 Q_UNUSED(engine); \
21@@ -119,36 +109,54 @@
22 MAKE_SINGLETON_FACTORY(MimeDatabase)
23 MAKE_SINGLETON_FACTORY(Direction)
24
25-
26-bool BrowserApplication::initialize(const QString& qmlFileSubPath)
27+bool BrowserApplication::initialize(const QString& qmlFileSubPath
28+ , const QString& appId)
29 {
30 Q_ASSERT(m_window == 0);
31
32+ if (appId.isEmpty()) {
33+ qCritical() << "Cannot initialize the runtime environment: "
34+ "no application id detected.";
35+ return false;
36+ }
37+
38 if (m_arguments.contains("--help") || m_arguments.contains("-h")) {
39 printUsage();
40 return false;
41 }
42
43- // Handle legacy platforms (i.e. current desktop versions, where
44- // applications are not started by the Ubuntu ApplicationManager).
45- if (qgetenv("APP_ID").isEmpty()) {
46- QString id = appId();
47- if (id.isEmpty()) {
48- id = QStringLiteral(APP_ID);
49- }
50- qputenv("APP_ID", id.toUtf8());
51- }
52 // Ensure that application-specific data is written where it ought to.
53- QStringList appIdParts =
54- QString::fromUtf8(qgetenv("APP_ID")).split('_');
55+ QStringList appIdParts = appId.split('_');
56+
57 QCoreApplication::setApplicationName(appIdParts.first());
58 QCoreApplication::setOrganizationDomain(QCoreApplication::applicationName());
59+
60 // Get also the the first two components of the app ID: <package>_<app>,
61 // which is needed by Online Accounts.
62 QString unversionedAppId = QStringList(appIdParts.mid(0, 2)).join('_');
63
64 // Ensure only one instance of the app is running.
65- if (m_singleton.run(m_arguments)) {
66+ // For webapps using the container as a launcher, the predicate that
67+ // is used to determine if this running instance is a duplicate of
68+ // a running one, is based on the current APP_ID.
69+ // The app id is formed as: <package name>_<app name>_<version>
70+
71+ // Where the <package name> is specified in the the manifest.json as
72+ // "appName" and is specific for the whole click package.
73+
74+ // The <app name> portion is based on the desktop file name and is a short
75+ // app name. This name is meaningful when more than one desktop file is
76+ // found in a given click package.
77+
78+ // IMPORTANT:
79+ // 1. When a click application contains more than one desktop file
80+ // the bundle is considered a single app from the point of view of the
81+ // cache and resource file locations. THOSE FILES ARE THEN SHARED between
82+ // the instances.
83+ // 2. To make sure that if more than one desktop file is found in a click package,
84+ // those apps are not considered the same instance, the instance existance predicate
85+ // is based on the <package name> AND the <app name> detailed above.
86+ if (m_singleton.run(m_arguments, appId)) {
87 connect(&m_singleton, SIGNAL(newInstanceLaunched(const QStringList&)),
88 SLOT(onNewInstanceLaunched(const QStringList&)));
89 } else {
90
91=== modified file 'src/app/browserapplication.h'
92--- src/app/browserapplication.h 2016-01-15 09:29:22 +0000
93+++ src/app/browserapplication.h 2016-05-11 16:04:27 +0000
94@@ -45,7 +45,7 @@
95 BrowserApplication(int& argc, char** argv);
96 ~BrowserApplication();
97
98- bool initialize(const QString& qmlFileSubPath);
99+ bool initialize(const QString& qmlFileSubPath, const QString& appId);
100 int run();
101
102 protected:
103@@ -63,7 +63,6 @@
104 void onNewInstanceLaunched(const QStringList& arguments) const;
105
106 private:
107- QString appId() const;
108 QString inspectorPort() const;
109 QString inspectorHost() const;
110
111
112=== modified file 'src/app/config.h.in'
113--- src/app/config.h.in 2015-05-14 05:57:01 +0000
114+++ src/app/config.h.in 2016-05-11 16:04:27 +0000
115@@ -23,7 +23,6 @@
116 #include <QtCore/QDir>
117 #include <QtCore/QString>
118
119-#define APP_ID "webbrowser-app"
120 #define REMOTE_INSPECTOR_PORT 9221
121
122 inline bool isRunningInstalled()
123
124=== modified file 'src/app/single-instance-manager.cpp'
125--- src/app/single-instance-manager.cpp 2016-04-08 13:49:25 +0000
126+++ src/app/single-instance-manager.cpp 2016-05-11 16:04:27 +0000
127@@ -33,12 +33,48 @@
128 #include "single-instance-manager.h"
129
130 namespace {
131+
132 const int kWaitForRunningInstanceToRespondMs = 1000;
133 const int kWaitForRunningInstanceToAckMs = 1000;
134 const int kDataStreamVersion = QDataStream::Qt_5_0;
135 const QString kHeaderToken = QStringLiteral("MESSAGE");
136 const QString kAckToken = QStringLiteral("ACK");
137-}
138+
139+QString getProfilePathFromAppId(const QString& appId)
140+{
141+ QString profilePath =
142+ QStandardPaths::writableLocation(QStandardPaths::DataLocation);
143+
144+ QStringList appIdParts = appId.split('_', QString::SkipEmptyParts);
145+
146+ QString appDesktopName;
147+
148+ // We try to get the "short app name" to try to uniquely identify
149+ // the single instance profile path.
150+
151+ // In cases where you have a single click with multiple apps in it,
152+ // the "app name" as defined in the click manifest.json file will be
153+ // a proper way to distinguish a unique instance, it needs to take
154+ // the desktop name into account.
155+
156+ // At the moment there is no clean way to get those click app name
157+ // paths, see:
158+ // https://launchpad.net/bugs/1555542
159+
160+ if (appIdParts.size() >= 3) {
161+ // Assume that we have a APP_ID that corresponds to:
162+ // <manifest app name>_<desktop app name>_<version>
163+ appDesktopName = appIdParts[1];
164+ } else {
165+ // We either run on desktop or as the webbrowser
166+ appDesktopName = appIdParts.first();
167+ }
168+
169+ return profilePath + QDir::separator() + appDesktopName;
170+}
171+
172+}
173+
174
175 SingleInstanceManager::SingleInstanceManager(QObject* parent)
176 : QObject(parent)
177@@ -54,13 +90,13 @@
178 return false;
179 }
180
181-bool SingleInstanceManager::run(const QStringList& arguments)
182+bool SingleInstanceManager::run(const QStringList& arguments, const QString& appId)
183 {
184 if (m_server.isListening()) {
185 return false;
186 }
187
188- QDir profile(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
189+ QDir profile(getProfilePathFromAppId(appId));
190 if (!profile.exists()) {
191 if (!QDir::root().mkpath(profile.absolutePath())) {
192 qCritical() << "Failed to create profile directory,"
193
194=== modified file 'src/app/single-instance-manager.h'
195--- src/app/single-instance-manager.h 2016-01-15 10:06:31 +0000
196+++ src/app/single-instance-manager.h 2016-05-11 16:04:27 +0000
197@@ -33,7 +33,7 @@
198 public:
199 SingleInstanceManager(QObject* parent=nullptr);
200
201- bool run(const QStringList& arguments);
202+ bool run(const QStringList& arguments, const QString& appId);
203
204 Q_SIGNALS:
205 void newInstanceLaunched(const QStringList& arguments) const;
206
207=== modified file 'src/app/webbrowser/webbrowser-app.cpp'
208--- src/app/webbrowser/webbrowser-app.cpp 2016-02-05 15:20:10 +0000
209+++ src/app/webbrowser/webbrowser-app.cpp 2016-05-11 16:04:27 +0000
210@@ -76,7 +76,7 @@
211 qmlRegisterSingletonType<DownloadsModel>(uri, 0, 1, "DownloadsModel", DownloadsModel_singleton_factory);
212 qmlRegisterType<TextSearchFilterModel>(uri, 0, 1, "TextSearchFilterModel");
213
214- if (BrowserApplication::initialize("webbrowser/webbrowser-app.qml")) {
215+ if (BrowserApplication::initialize("webbrowser/webbrowser-app.qml", QStringLiteral("webbrowser-app"))) {
216 QStringList searchEnginesSearchPaths;
217 searchEnginesSearchPaths << QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/searchengines";
218 searchEnginesSearchPaths << UbuntuBrowserDirectory() + "/webbrowser/searchengines";
219
220=== modified file 'src/app/webcontainer/webapp-container.cpp'
221--- src/app/webcontainer/webapp-container.cpp 2016-02-29 13:32:17 +0000
222+++ src/app/webcontainer/webapp-container.cpp 2016-05-11 16:04:27 +0000
223@@ -92,12 +92,38 @@
224 {
225 }
226
227+QString WebappContainer::appId() const
228+{
229+ Q_FOREACH(const QString& argument, m_arguments) {
230+ if (argument.startsWith("--app-id=")) {
231+ return argument.split("--app-id=")[1];
232+ }
233+ }
234+ return QString();
235+}
236
237 bool WebappContainer::initialize()
238 {
239 earlyEnvironment();
240
241- if (BrowserApplication::initialize("webcontainer/webapp-container.qml")) {
242+ if (qgetenv("APP_ID").isEmpty()) {
243+ QString id = appId();
244+ if (id.isEmpty()) {
245+ qCritical() << "The application has been launched with no "
246+ "explicit or system provided app id. "
247+ "An application id can be set by using the --app-id "
248+ "command line parameter and setting it to a unique "
249+ "application specific value or using the APP_ID environment "
250+ "variable.";
251+ return false;
252+ }
253+ qputenv("APP_ID", id.toUtf8());
254+ }
255+
256+ if (BrowserApplication::initialize(
257+ "webcontainer/webapp-container.qml",
258+ QString::fromUtf8(qgetenv("APP_ID")))) {
259+
260 parseCommandLine();
261 parseExtraConfiguration();
262
263
264=== modified file 'src/app/webcontainer/webapp-container.h'
265--- src/app/webcontainer/webapp-container.h 2016-02-27 21:45:57 +0000
266+++ src/app/webcontainer/webapp-container.h 2016-05-11 16:04:27 +0000
267@@ -54,6 +54,7 @@
268 bool shouldNotValidateCommandLineUrls() const;
269 bool isValidLocalIntentFilterFile(const QString& filename) const;
270 void setupLocalSchemeFilterIfAny(QQmlContext* context, const QString& webappSearchPath);
271+ QString appId() const;
272
273 private:
274 QString m_webappName;
275
276=== modified file 'tests/autopilot/webapp_container/tests/__init__.py'
277--- tests/autopilot/webapp_container/tests/__init__.py 2016-01-22 10:19:34 +0000
278+++ tests/autopilot/webapp_container/tests/__init__.py 2016-05-11 16:04:27 +0000
279@@ -57,6 +57,10 @@
280 args.append(
281 '--desktop_file_hint=/usr/share/applications/'
282 'webbrowser-app.desktop')
283+
284+ if next(filter(lambda e: e.startswith('--appid'), args), None) is None:
285+ args.append('--app-id=running.test')
286+
287 if envvars:
288 for envvar_key in envvars:
289 self.useFixture(fixtures.EnvironmentVariable(
290
291=== modified file 'tests/unittests/single-instance-manager/tst_SingleInstanceManagerTests.cpp'
292--- tests/unittests/single-instance-manager/tst_SingleInstanceManagerTests.cpp 2016-01-18 14:45:12 +0000
293+++ tests/unittests/single-instance-manager/tst_SingleInstanceManagerTests.cpp 2016-05-11 16:04:27 +0000
294@@ -50,18 +50,18 @@
295
296 void test_cannot_run_twice_same_instance()
297 {
298- QVERIFY(singleton->run(QStringList()));
299- QVERIFY(!singleton->run(QStringList()));
300+ QVERIFY(singleton->run(QStringList(), "appid"));
301+ QVERIFY(!singleton->run(QStringList(), "appid"));
302 QVERIFY(newInstanceSpy->isEmpty());
303 }
304
305 void test_arguments_passed_to_already_running_instance()
306 {
307- QVERIFY(singleton->run(QStringList()));
308+ QVERIFY(singleton->run(QStringList(), "appid"));
309 SingleInstanceManager other;
310 QStringList args;
311 args << QStringLiteral("foo") << QStringLiteral("bar") << QStringLiteral("baz");
312- QVERIFY(!other.run(args));
313+ QVERIFY(!other.run(args, "appid"));
314 newInstanceSpy->wait();
315 QCOMPARE(newInstanceSpy->first().at(0).toStringList(), args);
316 }

Subscribers

People subscribed via source and target branches