Merge lp:~mardy/webapps-core/saml-1614126 into lp:webapps-core

Proposed by Alberto Mardegan
Status: Needs review
Proposed branch: lp:~mardy/webapps-core/saml-1614126
Merge into: lp:webapps-core
Diff against target: 5136 lines (+3844/-484)
62 files modified
webapp-googleplus/lib/AlertDialog.qml (+6/-3)
webapp-googleplus/lib/BeforeUnloadDialog.qml (+7/-3)
webapp-googleplus/lib/ConfirmDialog.qml (+7/-3)
webapp-googleplus/lib/ContentHandler.qml (+35/-0)
webapp-googleplus/lib/Downloader.qml (+26/-32)
webapp-googleplus/lib/FileExtensionMapper.js (+27/-7)
webapp-googleplus/lib/MimeTypeMapper.js (+49/-15)
webapp-googleplus/lib/ModalDialog.qml (+4/-4)
webapp-googleplus/lib/PromptDialog.qml (+8/-5)
webapp-googleplus/lib/WebViewImpl.qml (+50/-34)
webapp-googleplus/lib/actions/Back.qml (+2/-2)
webapp-googleplus/lib/actions/Bookmark.qml (+2/-2)
webapp-googleplus/lib/actions/BookmarkLink.qml (+2/-2)
webapp-googleplus/lib/actions/ClearHistory.qml (+2/-2)
webapp-googleplus/lib/actions/Copy.qml (+2/-2)
webapp-googleplus/lib/actions/CopyImage.qml (+2/-2)
webapp-googleplus/lib/actions/CopyLink.qml (+2/-2)
webapp-googleplus/lib/actions/Cut.qml (+23/-0)
webapp-googleplus/lib/actions/Erase.qml (+23/-0)
webapp-googleplus/lib/actions/FindInPage.qml (+27/-0)
webapp-googleplus/lib/actions/Forward.qml (+2/-2)
webapp-googleplus/lib/actions/GoTo.qml (+2/-2)
webapp-googleplus/lib/actions/NewTab.qml (+2/-2)
webapp-googleplus/lib/actions/OpenImageInNewTab.qml (+2/-2)
webapp-googleplus/lib/actions/OpenLinkInBrowser.qml (+23/-0)
webapp-googleplus/lib/actions/OpenLinkInNewBackgroundTab.qml (+23/-0)
webapp-googleplus/lib/actions/OpenLinkInNewTab.qml (+2/-2)
webapp-googleplus/lib/actions/OpenLinkInNewWindow.qml (+23/-0)
webapp-googleplus/lib/actions/OpenLinkInPrivateWindow.qml (+23/-0)
webapp-googleplus/lib/actions/OpenVideoInNewTab.qml (+23/-0)
webapp-googleplus/lib/actions/Paste.qml (+23/-0)
webapp-googleplus/lib/actions/Redo.qml (+23/-0)
webapp-googleplus/lib/actions/Reload.qml (+2/-2)
webapp-googleplus/lib/actions/SaveImage.qml (+2/-2)
webapp-googleplus/lib/actions/SaveLink.qml (+23/-0)
webapp-googleplus/lib/actions/SaveVideo.qml (+23/-0)
webapp-googleplus/lib/actions/SelectAll.qml (+23/-0)
webapp-googleplus/lib/actions/Share.qml (+24/-0)
webapp-googleplus/lib/actions/Undo.qml (+23/-0)
webapp-googleplus/lib/webcontainer/AccountChooserDialog.qml (+124/-0)
webapp-googleplus/lib/webcontainer/AccountErrorScreen.qml (+54/-0)
webapp-googleplus/lib/webcontainer/AccountItem.qml (+31/-0)
webapp-googleplus/lib/webcontainer/AccountsLogic.qml (+231/-0)
webapp-googleplus/lib/webcontainer/AccountsPage.qml (+137/-0)
webapp-googleplus/lib/webcontainer/AccountsSplashScreen.qml (+89/-0)
webapp-googleplus/lib/webcontainer/Chrome.qml (+160/-0)
webapp-googleplus/lib/webcontainer/ContentDownloadDialog.qml (+45/-27)
webapp-googleplus/lib/webcontainer/ContentPickerDialog.qml (+9/-27)
webapp-googleplus/lib/webcontainer/ContextMenuMobile.qml (+162/-0)
webapp-googleplus/lib/webcontainer/ContextMenuWide.qml (+158/-0)
webapp-googleplus/lib/webcontainer/OnlineAccountsController.qml (+66/-0)
webapp-googleplus/lib/webcontainer/PopupWindowController.qml (+266/-0)
webapp-googleplus/lib/webcontainer/PopupWindowOverlay.qml (+248/-0)
webapp-googleplus/lib/webcontainer/SadPage.qml (+56/-0)
webapp-googleplus/lib/webcontainer/SplashScreen.qml (+65/-0)
webapp-googleplus/lib/webcontainer/WebApp.qml (+323/-0)
webapp-googleplus/lib/webcontainer/WebViewImplOxide.qml (+297/-0)
webapp-googleplus/lib/webcontainer/WebappContainerWebview.qml (+139/-0)
webapp-googleplus/lib/webcontainer/WebappWebview.qml (+234/-0)
webapp-googleplus/lib/webcontainer/webapp-container.qml (+336/-0)
webapp-googleplus/manifest.json (+1/-1)
webapp-googleplus/webview-override.qml (+16/-295)
To merge this branch: bzr merge lp:~mardy/webapps-core/saml-1614126
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+312254@code.launchpad.net

Commit message

Fix Google+ authentication and "unsupported browser" message

Update the classes copied from webbrowser-app, change the User-Agent.

Description of the change

Fix Google+ authentication and "unsupported browser" message

Update the classes copied from webbrowser-app, change the User-Agent.

To post a comment you must log in.
lp:~mardy/webapps-core/saml-1614126 updated
147. By Alberto Mardegan

Bump version number

Unmerged revisions

147. By Alberto Mardegan

Bump version number

146. By Alberto Mardegan

Specify user agent for Google plus

Works around https://bugs.launchpad.net/ubuntu/+source/webbrowser-app/+bug/1644585

145. By Alberto Mardegan

Update webcontainer components

144. By Alberto Mardegan

Reuse webview from the webapp container

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'webapp-googleplus/lib/AlertDialog.qml'
2--- webapp-googleplus/lib/AlertDialog.qml 2015-03-13 16:35:21 +0000
3+++ webapp-googleplus/lib/AlertDialog.qml 2016-12-02 07:06:20 +0000
4@@ -1,5 +1,5 @@
5 /*
6- * Copyright 2013-2014 Canonical Ltd.
7+ * Copyright 2013-2016 Canonical Ltd.
8 *
9 * This file is part of webbrowser-app.
10 *
11@@ -16,14 +16,17 @@
12 * along with this program. If not, see <http://www.gnu.org/licenses/>.
13 */
14
15-import QtQuick 2.0
16-import Ubuntu.Components 1.1
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19
20 ModalDialog {
21+ objectName: "alertDialog"
22 title: i18n.tr("JavaScript Alert")
23
24 Button {
25 text: i18n.tr("OK")
26+ color: theme.palette.normal.positive
27+ objectName: "okButton"
28 onClicked: model.accept()
29 }
30 }
31
32=== modified file 'webapp-googleplus/lib/BeforeUnloadDialog.qml'
33--- webapp-googleplus/lib/BeforeUnloadDialog.qml 2015-03-13 16:35:21 +0000
34+++ webapp-googleplus/lib/BeforeUnloadDialog.qml 2016-12-02 07:06:20 +0000
35@@ -1,5 +1,5 @@
36 /*
37- * Copyright 2014 Canonical Ltd.
38+ * Copyright 2014-2016 Canonical Ltd.
39 *
40 * This file is part of webbrowser-app.
41 *
42@@ -16,18 +16,22 @@
43 * along with this program. If not, see <http://www.gnu.org/licenses/>.
44 */
45
46-import QtQuick 2.0
47-import Ubuntu.Components 1.1
48+import QtQuick 2.4
49+import Ubuntu.Components 1.3
50
51 ModalDialog {
52+ objectName: "beforeUnloadDialog"
53 title: i18n.tr("Confirm Navigation")
54
55 Button {
56 text: i18n.tr("Leave")
57+ color: theme.palette.normal.negative
58+ objectName: "leaveButton"
59 onClicked: model.accept()
60 }
61
62 Button {
63+ objectName: "stayButton"
64 text: i18n.tr("Stay")
65 onClicked: model.reject()
66 }
67
68=== modified file 'webapp-googleplus/lib/ConfirmDialog.qml'
69--- webapp-googleplus/lib/ConfirmDialog.qml 2015-03-13 16:35:21 +0000
70+++ webapp-googleplus/lib/ConfirmDialog.qml 2016-12-02 07:06:20 +0000
71@@ -1,5 +1,5 @@
72 /*
73- * Copyright 2013-2014 Canonical Ltd.
74+ * Copyright 2013-2016 Canonical Ltd.
75 *
76 * This file is part of webbrowser-app.
77 *
78@@ -16,18 +16,22 @@
79 * along with this program. If not, see <http://www.gnu.org/licenses/>.
80 */
81
82-import QtQuick 2.0
83-import Ubuntu.Components 1.1
84+import QtQuick 2.4
85+import Ubuntu.Components 1.3
86
87 ModalDialog {
88+ objectName: "confirmDialog"
89 title: i18n.tr("JavaScript Confirmation")
90
91 Button {
92 text: i18n.tr("OK")
93+ color: theme.palette.normal.positive
94+ objectName: "okButton"
95 onClicked: model.accept()
96 }
97
98 Button {
99+ objectName: "cancelButton"
100 text: i18n.tr("Cancel")
101 onClicked: model.reject()
102 }
103
104=== added file 'webapp-googleplus/lib/ContentHandler.qml'
105--- webapp-googleplus/lib/ContentHandler.qml 1970-01-01 00:00:00 +0000
106+++ webapp-googleplus/lib/ContentHandler.qml 2016-12-02 07:06:20 +0000
107@@ -0,0 +1,35 @@
108+/*
109+ * Copyright 2015 Canonical Ltd.
110+ *
111+ * This file is part of webbrowser-app.
112+ *
113+ * webbrowser-app is free software; you can redistribute it and/or modify
114+ * it under the terms of the GNU General Public License as published by
115+ * the Free Software Foundation; version 3.
116+ *
117+ * webbrowser-app is distributed in the hope that it will be useful,
118+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
119+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120+ * GNU General Public License for more details.
121+ *
122+ * You should have received a copy of the GNU General Public License
123+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
124+ */
125+
126+import QtQuick 2.4
127+import Ubuntu.Content 1.3
128+import "MimeTypeMapper.js" as MimeTypeMapper
129+
130+Item {
131+ signal exportFromDownloads(var transfer, var mimetypeFilter, bool multiSelect)
132+
133+ Connections {
134+ target: ContentHub
135+ onExportRequested: {
136+ exportFromDownloads(transfer,
137+ MimeTypeMapper.mimeTypeRegexForContentType(transfer.contentType),
138+ transfer.selectionType === ContentTransfer.Multiple)
139+
140+ }
141+ }
142+}
143
144=== modified file 'webapp-googleplus/lib/Downloader.qml'
145--- webapp-googleplus/lib/Downloader.qml 2015-03-13 16:35:21 +0000
146+++ webapp-googleplus/lib/Downloader.qml 2016-12-02 07:06:20 +0000
147@@ -1,5 +1,5 @@
148 /*
149- * Copyright 2014 Canonical Ltd.
150+ * Copyright 2014-2016 Canonical Ltd.
151 *
152 * This file is part of webbrowser-app.
153 *
154@@ -16,62 +16,52 @@
155 * along with this program. If not, see <http://www.gnu.org/licenses/>.
156 */
157
158-import QtQuick 2.0
159-import Ubuntu.Components 1.1
160-import Ubuntu.Components.Popups 1.0
161-import Ubuntu.DownloadManager 0.1
162-import Ubuntu.Content 0.1
163+import QtQuick 2.4
164+import Ubuntu.Components 1.3
165+import Ubuntu.Components.Popups 1.3
166+import Ubuntu.DownloadManager 1.2
167+import Ubuntu.Content 1.3
168 import "MimeTypeMapper.js" as MimeTypeMapper
169 import "FileExtensionMapper.js" as FileExtensionMapper
170
171 Item {
172 id: downloadItem
173
174- Component {
175- id: downloadDialog
176- ContentDownloadDialog { }
177- }
178+ property string filename
179+ property string mimeType
180+
181+ signal showDownloadDialog(string downloadId, var contentType, var downloader, string filename, string mimeType)
182
183 Component {
184 id: metadataComponent
185- Metadata {
186- showInIndicator: true
187- }
188+ Metadata {}
189 }
190
191 Component {
192 id: downloadComponent
193 SingleDownload {
194+ id: downloader
195 autoStart: false
196 property var contentType
197+ property string url
198+
199 onDownloadIdChanged: {
200- PopupUtils.open(downloadDialog, downloadItem, {"contentType" : contentType, "downloadId" : downloadId})
201- }
202-
203- onFinished: {
204- metadata.destroy()
205- destroy()
206+ showDownloadDialog(downloadId, contentType, downloader, downloadItem.filename, downloadItem.mimeType)
207 }
208 }
209 }
210
211 function download(url, contentType, headers, metadata) {
212- var singleDownload = downloadComponent.createObject(downloadItem)
213- singleDownload.contentType = contentType
214- if (headers) {
215- singleDownload.headers = headers
216+ var properties = {'contentType': contentType, 'metadata': metadata, 'url': url}
217+ if (headers) {
218+ properties['headers'] = headers
219 }
220- singleDownload.metadata = metadata
221+ var singleDownload = downloadComponent.createObject(downloadItem, properties)
222 singleDownload.download(url)
223 }
224
225- function downloadPicture(url, headers) {
226- var metadata = metadataComponent.createObject(downloadItem)
227- download(url, ContentType.Pictures, headers, metadata)
228- }
229-
230- function downloadMimeType(url, mimeType, headers, filename) {
231- var metadata = metadataComponent.createObject(downloadItem)
232+ function downloadMimeType(url, mimeType, headers, filename, incognito) {
233+ var metadata = metadataComponent.createObject(downloadItem, {"showInIndicator": !incognito})
234 var contentType = MimeTypeMapper.mimeTypeToContentType(mimeType)
235 if (contentType == ContentType.Unknown && filename) {
236 // If we can't determine the content type from the mime-type
237@@ -86,12 +76,16 @@
238 contentType = ContentType.Music
239 metadata.extract = true
240 }
241+ if (!filename) {
242+ filename = url.toString().split("/").pop()
243+ }
244 metadata.title = filename
245+ downloadItem.filename = filename
246+ downloadItem.mimeType = mimeType
247 download(url, contentType, headers, metadata)
248 }
249
250 function is7digital(url) {
251 return url.toString().search(/[^\/]+:\/\/[^\/]*7digital.com\//) !== -1
252 }
253-
254 }
255
256=== modified file 'webapp-googleplus/lib/FileExtensionMapper.js'
257--- webapp-googleplus/lib/FileExtensionMapper.js 2015-03-13 16:35:21 +0000
258+++ webapp-googleplus/lib/FileExtensionMapper.js 2016-12-02 07:06:20 +0000
259@@ -1,5 +1,5 @@
260 /*
261- * Copyright 2014 Canonical Ltd.
262+ * Copyright 2014-2015 Canonical Ltd.
263 *
264 * This file is part of webbrowser-app.
265 *
266@@ -15,15 +15,19 @@
267 * You should have received a copy of the GNU General Public License
268 * along with this program. If not, see <http://www.gnu.org/licenses/>.
269 */
270+'use strict';
271+
272+function getExtension(filename) {
273+ var filenameParts = filename.split(".");
274+ if (filenameParts.length === 1 || (filenameParts[0] === "" && filenameParts.length === 2)) {
275+ return ""
276+ }
277+ return filenameParts.pop().toLowerCase();
278+}
279
280 // Constructed from /etc/mime.types
281 function filenameToContentType(filename) {
282- var filenameParts = filename.split(".");
283- if(filenameParts.length === 1 || (filenameParts[0] === "" && filenameParts.length === 2)) {
284- return ContentType.Unknown;
285- }
286- var ext = filenameParts.pop().toLowerCase();
287- switch(ext) {
288+ switch(getExtension(filename)) {
289 case "art":
290 case "bmp":
291 case "cdr":
292@@ -156,6 +160,8 @@
293 case "cxx":
294 case "d":
295 case "diff":
296+ case "doc":
297+ case "docx":
298 case "etx":
299 case "gcd":
300 case "h":
301@@ -176,6 +182,9 @@
302 case "ly":
303 case "mml":
304 case "moc":
305+ case "odp":
306+ case "ods":
307+ case "odt":
308 case "p":
309 case "pas":
310 case "patch":
311@@ -183,6 +192,8 @@
312 case "pl":
313 case "pm":
314 case "pot":
315+ case "ppt":
316+ case "pptx":
317 case "py":
318 case "rtx":
319 case "scala":
320@@ -205,7 +216,16 @@
321 case "wml":
322 case "wmls":
323 case "wsc":
324+ case "xls":
325+ case "xlsx":
326 return ContentType.Documents;
327+ case "epub":
328+ case "mobi":
329+ case "lit":
330+ case "fb2":
331+ case "azw":
332+ case "tpz":
333+ return ContentType.EBooks;
334 default:
335 return ContentType.Unknown;
336 }
337
338=== modified file 'webapp-googleplus/lib/MimeTypeMapper.js'
339--- webapp-googleplus/lib/MimeTypeMapper.js 2015-03-13 16:35:21 +0000
340+++ webapp-googleplus/lib/MimeTypeMapper.js 2016-12-02 07:06:20 +0000
341@@ -1,5 +1,5 @@
342 /*
343- * Copyright 2014 Canonical Ltd.
344+ * Copyright 2014-2015 Canonical Ltd.
345 *
346 * This file is part of webbrowser-app.
347 *
348@@ -18,20 +18,54 @@
349
350
351 function mimeTypeToContentType(mimeType) {
352- if(mimeType.search("image/") === 0) {
353- return ContentType.Pictures;
354- } else if(mimeType.search("audio/") === 0) {
355- return ContentType.Music;
356- } else if(mimeType.search("video/") === 0) {
357- return ContentType.Videos;
358- } else if(mimeType.search("text/x-vcard") === 0) {
359- return ContentType.Contacts;
360- } else if(mimeType.search("text/") === 0
361- || mimeType.search("application/pdf") === 0
362- || mimeType.search("application/x-pdf") === 0
363- || mimeType.search("application/vnd.pdf") === 0) {
364- return ContentType.Documents;
365+ if (mimeType.search("image/") === 0) {
366+ return ContentType.Pictures
367+ } else if (mimeType.search("audio/") === 0) {
368+ return ContentType.Music
369+ } else if (mimeType.search("video/") === 0) {
370+ return ContentType.Videos
371+ } else if (mimeType.search("text/x-vcard") === 0
372+ || mimeType.search("text/vcard") === 0) {
373+ return ContentType.Contacts
374+ } else if (mimeType.search("application/epub[+]zip") === 0
375+ || mimeType.search("application/vnd\.amazon\.ebook") === 0
376+ || mimeType.search("application/x-mobipocket-ebook") === 0
377+ || mimeType.search("application/x-fictionbook+xml") === 0
378+ || mimeType.search("application/x-ms-reader") === 0) {
379+ return ContentType.EBooks
380+ } else if (mimeType.search("text/") === 0
381+ || mimeType.search("application/pdf") === 0
382+ || mimeType.search("application/x-pdf") === 0
383+ || mimeType.search("application/vnd\.pdf") === 0
384+ || mimeType.search("application/vnd\.oasis\.opendocument") === 0
385+ || mimeType.search("application/msword") === 0
386+ || mimeType.search("application/vnd\.openxmlformats-officedocument\.wordprocessingml\.document") === 0
387+ || mimeType.search("application/vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet") === 0
388+ || mimeType.search("application/vnd\.openxmlformats-officedocument\.presentationml\.presentation") === 0
389+ || mimeType.search("application/vnd\.ms-excel") === 0
390+ || mimeType.search("application/vnd\.ms-powerpoint") === 0) {
391+ return ContentType.Documents
392 } else {
393- return ContentType.Unknown;
394+ return ContentType.Unknown
395+ }
396+}
397+
398+function mimeTypeRegexForContentType(contentType) {
399+ switch (contentType) {
400+ case ContentType.Pictures:
401+ return /image\/.*/;
402+ case ContentType.Music:
403+ return /audio\/.*/;
404+ case ContentType.Videos:
405+ return /video\/.*/;
406+ case ContentType.Contacts:
407+ return /text\/(x-vcard|vcard)/;
408+ case ContentType.EBooks:
409+ return /application\/(epub.*|vnd.amazon.ebook|x-mobipocket-ebook|x-fictionbook+xml|x-ms-reader)/;
410+ case ContentType.Documents:
411+ return /(text\/.*|application\/pdf|application\/x-pdf|application\/vnd\.pdf|application\/vnd\.oasis\.opendocument.*|application\/msword|application\/vnd\.openxmlformats-officedocument\.wordprocessingml\.document|application\/vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet|application\/vnd\.openxmlformats-officedocument\.presentationml\.presentation|application\/vnd\.ms-excel|application\/vnd\.ms-powerpoint)/;
412+ case ContentType.Unknown:
413+ case ContentType.All:
414+ return /.*/;
415 }
416 }
417
418=== modified file 'webapp-googleplus/lib/ModalDialog.qml'
419--- webapp-googleplus/lib/ModalDialog.qml 2015-03-13 16:35:21 +0000
420+++ webapp-googleplus/lib/ModalDialog.qml 2016-12-02 07:06:20 +0000
421@@ -1,5 +1,5 @@
422 /*
423- * Copyright 2014 Canonical Ltd.
424+ * Copyright 2014-2015 Canonical Ltd.
425 *
426 * This file is part of webbrowser-app.
427 *
428@@ -16,9 +16,9 @@
429 * along with this program. If not, see <http://www.gnu.org/licenses/>.
430 */
431
432-import QtQuick 2.0
433-import Ubuntu.Components 1.1
434-import Ubuntu.Components.Popups 1.0 as Popups
435+import QtQuick 2.4
436+import Ubuntu.Components 1.3
437+import Ubuntu.Components.Popups 1.3 as Popups
438
439 Popups.Dialog {
440 text: model.message
441
442=== modified file 'webapp-googleplus/lib/PromptDialog.qml'
443--- webapp-googleplus/lib/PromptDialog.qml 2015-03-13 16:35:21 +0000
444+++ webapp-googleplus/lib/PromptDialog.qml 2016-12-02 07:06:20 +0000
445@@ -1,5 +1,5 @@
446 /*
447- * Copyright 2013-2014 Canonical Ltd.
448+ * Copyright 2013-2016 Canonical Ltd.
449 *
450 * This file is part of webbrowser-app.
451 *
452@@ -16,27 +16,30 @@
453 * along with this program. If not, see <http://www.gnu.org/licenses/>.
454 */
455
456-import QtQuick 2.0
457-import Ubuntu.Components 1.1
458+import QtQuick 2.4
459+import Ubuntu.Components 1.3
460
461 ModalDialog {
462+ objectName: "promptDialog"
463 title: i18n.tr("JavaScript Prompt")
464
465 TextField {
466 id: input
467+ objectName: "inputTextField"
468 text: model.defaultValue
469 onAccepted: model.accept(input.text)
470 }
471
472 Button {
473 text: i18n.tr("OK")
474- color: "green"
475+ color: theme.palette.normal.positive
476+ objectName: "okButton"
477 onClicked: model.accept(input.text)
478 }
479
480 Button {
481+ objectName: "cancelButton"
482 text: i18n.tr("Cancel")
483- color: UbuntuColors.coolGrey
484 onClicked: model.reject()
485 }
486
487
488=== modified file 'webapp-googleplus/lib/WebViewImpl.qml'
489--- webapp-googleplus/lib/WebViewImpl.qml 2016-02-10 15:23:59 +0000
490+++ webapp-googleplus/lib/WebViewImpl.qml 2016-12-02 07:06:20 +0000
491@@ -1,5 +1,5 @@
492 /*
493- * Copyright 2013-2014 Canonical Ltd.
494+ * Copyright 2013-2016 Canonical Ltd.
495 *
496 * This file is part of webbrowser-app.
497 *
498@@ -16,53 +16,76 @@
499 * along with this program. If not, see <http://www.gnu.org/licenses/>.
500 */
501
502-import QtQuick 2.0
503-import Ubuntu.Components 1.1
504-import Ubuntu.Components.Popups 1.0
505+import QtQuick 2.4
506+import Ubuntu.Components 1.3
507+import Ubuntu.Components.Popups 1.3
508 import Ubuntu.Web 0.2
509-import "../actions" as Actions
510+import webbrowsercommon.private 0.1
511+import "actions" as Actions
512
513 WebView {
514 id: webview
515
516 property var currentWebview: webview
517- property var certificateError
518- // Invalid certificates the user has explicitly allowed for this session
519- property var allowedCertificates: []
520
521 /*experimental.certificateVerificationDialog: CertificateVerificationDialog {}
522- experimental.authenticationDialog: AuthenticationDialog {}
523 experimental.proxyAuthenticationDialog: ProxyAuthenticationDialog {}*/
524 alertDialog: AlertDialog {}
525 confirmDialog: ConfirmDialog {}
526 promptDialog: PromptDialog {}
527 beforeUnloadDialog: BeforeUnloadDialog {}
528- filePicker: contentPickerLoader.item || filePickerLoader.item
529+
530+ signal showDownloadDialog(string downloadId, var contentType, var downloader, string filename, string mimeType)
531+
532+ QtObject {
533+ id: internal
534+
535+ readonly property var downloadMimeTypesBlacklist: [
536+ "application/x-shockwave-flash", // http://launchpad.net/bugs/1379806
537+ ]
538+ }
539+
540+ onFullscreenRequested: webview.fullscreen = fullscreen
541
542 onDownloadRequested: {
543+ if (!request.suggestedFilename && request.mimeType &&
544+ internal.downloadMimeTypesBlacklist.indexOf(request.mimeType) > -1) {
545+ return
546+ }
547+
548 if (downloadLoader.status == Loader.Ready) {
549 var headers = { }
550- if(request.cookies.length > 0) {
551+ if (request.cookies.length > 0) {
552 headers["Cookie"] = request.cookies.join(";")
553 }
554- if(request.referrer) {
555+ if (request.referrer) {
556 headers["Referer"] = request.referrer
557 }
558 headers["User-Agent"] = webview.context.userAgent
559- downloadLoader.item.downloadMimeType(request.url, request.mimeType, headers, request.suggestedFilename)
560+ // Work around https://launchpad.net/bugs/1487090 by guessing the mime type
561+ // from the suggested filename or URL if oxide hasn’t provided one, or if
562+ // the server has provided the generic application/octet-stream mime type.
563+ var mimeType = request.mimeType
564+ if (!mimeType || mimeType == "application/octet-stream") {
565+ mimeType = MimeDatabase.filenameToMimeType(request.suggestedFilename)
566+ }
567+ if (!mimeType) {
568+ var scheme = request.url.toString().split('://').shift().toLowerCase()
569+ var filename = request.url.toString().split('/').pop().split('?').shift()
570+ if ((scheme == "file") || (filename.indexOf('.') > -1)) {
571+ mimeType = MimeDatabase.filenameToMimeType(filename)
572+ }
573+ }
574+ downloadLoader.item.downloadMimeType(request.url, mimeType, headers, request.suggestedFilename, incognito)
575+ } else {
576+ // Desktop form factor case
577+ Qt.openUrlExternally(request.url)
578 }
579 }
580
581- Loader {
582- id: contentPickerLoader
583- source: "ContentPickerDialog.qml"
584- asynchronous: true
585- }
586-
587- Loader {
588- id: filePickerLoader
589- source: "FilePickerDialog.qml"
590- asynchronous: true
591+ onHttpAuthenticationRequested: {
592+ PopupUtils.open(Qt.resolvedUrl("HttpAuthenticationDialog.qml"),
593+ webview.currentWebview, {"request": request})
594 }
595
596 Loader {
597@@ -71,9 +94,10 @@
598 asynchronous: true
599 }
600
601- selectionActions: ActionList {
602- Actions.Copy {
603- onTriggered: copy()
604+ Connections {
605+ target: downloadLoader.item
606+ onShowDownloadDialog: {
607+ showDownloadDialog(downloadId, contentType, downloader, filename, mimeType)
608 }
609 }
610
611@@ -83,12 +107,4 @@
612 // TODO: we might want to store the answer to avoid requesting
613 // the permission everytime the user visits this site.
614 }
615-
616- onCertificateError: {
617- if(webview.allowedCertificates.indexOf(error.certificate.fingerprintSHA1) != -1) {
618- error.allow()
619- } else {
620- certificateError = error
621- }
622- }
623 }
624
625=== renamed directory 'webapp-googleplus/actions' => 'webapp-googleplus/lib/actions'
626=== modified file 'webapp-googleplus/lib/actions/Back.qml'
627--- webapp-googleplus/actions/Back.qml 2015-03-13 16:35:21 +0000
628+++ webapp-googleplus/lib/actions/Back.qml 2016-12-02 07:06:20 +0000
629@@ -1,5 +1,5 @@
630 /*
631- * Copyright 2013-2014 Canonical Ltd.
632+ * Copyright 2013-2015 Canonical Ltd.
633 *
634 * This file is part of webbrowser-app.
635 *
636@@ -16,7 +16,7 @@
637 * along with this program. If not, see <http://www.gnu.org/licenses/>.
638 */
639
640-import Ubuntu.Components 1.1
641+import Ubuntu.Components 1.3
642 import Ubuntu.Unity.Action 1.1 as UnityActions
643
644 UnityActions.Action {
645
646=== modified file 'webapp-googleplus/lib/actions/Bookmark.qml'
647--- webapp-googleplus/actions/Bookmark.qml 2015-03-13 16:35:21 +0000
648+++ webapp-googleplus/lib/actions/Bookmark.qml 2016-12-02 07:06:20 +0000
649@@ -1,5 +1,5 @@
650 /*
651- * Copyright 2013-2014 Canonical Ltd.
652+ * Copyright 2013-2015 Canonical Ltd.
653 *
654 * This file is part of webbrowser-app.
655 *
656@@ -16,7 +16,7 @@
657 * along with this program. If not, see <http://www.gnu.org/licenses/>.
658 */
659
660-import Ubuntu.Components 1.1
661+import Ubuntu.Components 1.3
662 import Ubuntu.Unity.Action 1.1 as UnityActions
663
664 UnityActions.Action {
665
666=== modified file 'webapp-googleplus/lib/actions/BookmarkLink.qml'
667--- webapp-googleplus/actions/BookmarkLink.qml 2015-03-13 16:35:21 +0000
668+++ webapp-googleplus/lib/actions/BookmarkLink.qml 2016-12-02 07:06:20 +0000
669@@ -1,5 +1,5 @@
670 /*
671- * Copyright 2013-2014 Canonical Ltd.
672+ * Copyright 2013-2015 Canonical Ltd.
673 *
674 * This file is part of webbrowser-app.
675 *
676@@ -16,7 +16,7 @@
677 * along with this program. If not, see <http://www.gnu.org/licenses/>.
678 */
679
680-import Ubuntu.Components 1.1
681+import Ubuntu.Components 1.3
682
683 Action {
684 text: i18n.tr("Bookmark link")
685
686=== modified file 'webapp-googleplus/lib/actions/ClearHistory.qml'
687--- webapp-googleplus/actions/ClearHistory.qml 2015-03-13 16:35:21 +0000
688+++ webapp-googleplus/lib/actions/ClearHistory.qml 2016-12-02 07:06:20 +0000
689@@ -1,5 +1,5 @@
690 /*
691- * Copyright 2013-2014 Canonical Ltd.
692+ * Copyright 2013-2015 Canonical Ltd.
693 *
694 * This file is part of webbrowser-app.
695 *
696@@ -16,7 +16,7 @@
697 * along with this program. If not, see <http://www.gnu.org/licenses/>.
698 */
699
700-import Ubuntu.Components 1.1
701+import Ubuntu.Components 1.3
702 import Ubuntu.Unity.Action 1.1 as UnityActions
703
704 UnityActions.Action {
705
706=== modified file 'webapp-googleplus/lib/actions/Copy.qml'
707--- webapp-googleplus/actions/Copy.qml 2015-03-13 16:35:21 +0000
708+++ webapp-googleplus/lib/actions/Copy.qml 2016-12-02 07:06:20 +0000
709@@ -1,5 +1,5 @@
710 /*
711- * Copyright 2013-2014 Canonical Ltd.
712+ * Copyright 2013-2015 Canonical Ltd.
713 *
714 * This file is part of webbrowser-app.
715 *
716@@ -16,7 +16,7 @@
717 * along with this program. If not, see <http://www.gnu.org/licenses/>.
718 */
719
720-import Ubuntu.Components 1.1
721+import Ubuntu.Components 1.3
722
723 Action {
724 text: i18n.tr("Copy")
725
726=== modified file 'webapp-googleplus/lib/actions/CopyImage.qml'
727--- webapp-googleplus/actions/CopyImage.qml 2015-03-13 16:35:21 +0000
728+++ webapp-googleplus/lib/actions/CopyImage.qml 2016-12-02 07:06:20 +0000
729@@ -1,5 +1,5 @@
730 /*
731- * Copyright 2013-2014 Canonical Ltd.
732+ * Copyright 2013-2015 Canonical Ltd.
733 *
734 * This file is part of webbrowser-app.
735 *
736@@ -16,7 +16,7 @@
737 * along with this program. If not, see <http://www.gnu.org/licenses/>.
738 */
739
740-import Ubuntu.Components 1.1
741+import Ubuntu.Components 1.3
742
743 Action {
744 text: i18n.tr("Copy image")
745
746=== modified file 'webapp-googleplus/lib/actions/CopyLink.qml'
747--- webapp-googleplus/actions/CopyLink.qml 2015-03-13 16:35:21 +0000
748+++ webapp-googleplus/lib/actions/CopyLink.qml 2016-12-02 07:06:20 +0000
749@@ -1,5 +1,5 @@
750 /*
751- * Copyright 2013-2014 Canonical Ltd.
752+ * Copyright 2013-2015 Canonical Ltd.
753 *
754 * This file is part of webbrowser-app.
755 *
756@@ -16,7 +16,7 @@
757 * along with this program. If not, see <http://www.gnu.org/licenses/>.
758 */
759
760-import Ubuntu.Components 1.1
761+import Ubuntu.Components 1.3
762
763 Action {
764 text: i18n.tr("Copy link")
765
766=== added file 'webapp-googleplus/lib/actions/Cut.qml'
767--- webapp-googleplus/lib/actions/Cut.qml 1970-01-01 00:00:00 +0000
768+++ webapp-googleplus/lib/actions/Cut.qml 2016-12-02 07:06:20 +0000
769@@ -0,0 +1,23 @@
770+/*
771+ * Copyright 2015 Canonical Ltd.
772+ *
773+ * This file is part of webbrowser-app.
774+ *
775+ * webbrowser-app is free software; you can redistribute it and/or modify
776+ * it under the terms of the GNU General Public License as published by
777+ * the Free Software Foundation; version 3.
778+ *
779+ * webbrowser-app is distributed in the hope that it will be useful,
780+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
781+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
782+ * GNU General Public License for more details.
783+ *
784+ * You should have received a copy of the GNU General Public License
785+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
786+ */
787+
788+import Ubuntu.Components 1.3
789+
790+Action {
791+ text: i18n.tr("Cut")
792+}
793
794=== added file 'webapp-googleplus/lib/actions/Erase.qml'
795--- webapp-googleplus/lib/actions/Erase.qml 1970-01-01 00:00:00 +0000
796+++ webapp-googleplus/lib/actions/Erase.qml 2016-12-02 07:06:20 +0000
797@@ -0,0 +1,23 @@
798+/*
799+ * Copyright 2015 Canonical Ltd.
800+ *
801+ * This file is part of webbrowser-app.
802+ *
803+ * webbrowser-app is free software; you can redistribute it and/or modify
804+ * it under the terms of the GNU General Public License as published by
805+ * the Free Software Foundation; version 3.
806+ *
807+ * webbrowser-app is distributed in the hope that it will be useful,
808+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
809+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
810+ * GNU General Public License for more details.
811+ *
812+ * You should have received a copy of the GNU General Public License
813+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
814+ */
815+
816+import Ubuntu.Components 1.3
817+
818+Action {
819+ text: i18n.tr("Erase")
820+}
821
822=== added file 'webapp-googleplus/lib/actions/FindInPage.qml'
823--- webapp-googleplus/lib/actions/FindInPage.qml 1970-01-01 00:00:00 +0000
824+++ webapp-googleplus/lib/actions/FindInPage.qml 2016-12-02 07:06:20 +0000
825@@ -0,0 +1,27 @@
826+/*
827+ * Copyright 2015 Canonical Ltd.
828+ *
829+ * This file is part of webbrowser-app.
830+ *
831+ * webbrowser-app is free software; you can redistribute it and/or modify
832+ * it under the terms of the GNU General Public License as published by
833+ * the Free Software Foundation; version 3.
834+ *
835+ * webbrowser-app is distributed in the hope that it will be useful,
836+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
837+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
838+ * GNU General Public License for more details.
839+ *
840+ * You should have received a copy of the GNU General Public License
841+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
842+ */
843+
844+import Ubuntu.Components 1.3
845+import Ubuntu.Unity.Action 1.1 as UnityActions
846+
847+UnityActions.Action {
848+ text: i18n.tr("Find in page")
849+ // TRANSLATORS: This is a free-form list of keywords associated to the 'Find in Page' action.
850+ // Keywords may actually be sentences, and must be separated by semi-colons.
851+ keywords: i18n.tr("Search in Page")
852+}
853
854=== modified file 'webapp-googleplus/lib/actions/Forward.qml'
855--- webapp-googleplus/actions/Forward.qml 2015-03-13 16:35:21 +0000
856+++ webapp-googleplus/lib/actions/Forward.qml 2016-12-02 07:06:20 +0000
857@@ -1,5 +1,5 @@
858 /*
859- * Copyright 2013-2014 Canonical Ltd.
860+ * Copyright 2013-2015 Canonical Ltd.
861 *
862 * This file is part of webbrowser-app.
863 *
864@@ -16,7 +16,7 @@
865 * along with this program. If not, see <http://www.gnu.org/licenses/>.
866 */
867
868-import Ubuntu.Components 1.1
869+import Ubuntu.Components 1.3
870 import Ubuntu.Unity.Action 1.1 as UnityActions
871
872 UnityActions.Action {
873
874=== modified file 'webapp-googleplus/lib/actions/GoTo.qml'
875--- webapp-googleplus/actions/GoTo.qml 2015-03-13 16:35:21 +0000
876+++ webapp-googleplus/lib/actions/GoTo.qml 2016-12-02 07:06:20 +0000
877@@ -1,5 +1,5 @@
878 /*
879- * Copyright 2013-2014 Canonical Ltd.
880+ * Copyright 2013-2015 Canonical Ltd.
881 *
882 * This file is part of webbrowser-app.
883 *
884@@ -16,7 +16,7 @@
885 * along with this program. If not, see <http://www.gnu.org/licenses/>.
886 */
887
888-import Ubuntu.Components 1.1
889+import Ubuntu.Components 1.3
890 import Ubuntu.Unity.Action 1.1 as UnityActions
891
892 UnityActions.Action {
893
894=== modified file 'webapp-googleplus/lib/actions/NewTab.qml'
895--- webapp-googleplus/actions/NewTab.qml 2015-03-13 16:35:21 +0000
896+++ webapp-googleplus/lib/actions/NewTab.qml 2016-12-02 07:06:20 +0000
897@@ -1,5 +1,5 @@
898 /*
899- * Copyright 2013-2014 Canonical Ltd.
900+ * Copyright 2013-2015 Canonical Ltd.
901 *
902 * This file is part of webbrowser-app.
903 *
904@@ -16,7 +16,7 @@
905 * along with this program. If not, see <http://www.gnu.org/licenses/>.
906 */
907
908-import Ubuntu.Components 1.1
909+import Ubuntu.Components 1.3
910 import Ubuntu.Unity.Action 1.1 as UnityActions
911
912 UnityActions.Action {
913
914=== modified file 'webapp-googleplus/lib/actions/OpenImageInNewTab.qml'
915--- webapp-googleplus/actions/OpenImageInNewTab.qml 2015-03-13 16:35:21 +0000
916+++ webapp-googleplus/lib/actions/OpenImageInNewTab.qml 2016-12-02 07:06:20 +0000
917@@ -1,5 +1,5 @@
918 /*
919- * Copyright 2013-2014 Canonical Ltd.
920+ * Copyright 2013-2015 Canonical Ltd.
921 *
922 * This file is part of webbrowser-app.
923 *
924@@ -16,7 +16,7 @@
925 * along with this program. If not, see <http://www.gnu.org/licenses/>.
926 */
927
928-import Ubuntu.Components 1.1
929+import Ubuntu.Components 1.3
930
931 Action {
932 text: i18n.tr("Open image in new tab")
933
934=== added file 'webapp-googleplus/lib/actions/OpenLinkInBrowser.qml'
935--- webapp-googleplus/lib/actions/OpenLinkInBrowser.qml 1970-01-01 00:00:00 +0000
936+++ webapp-googleplus/lib/actions/OpenLinkInBrowser.qml 2016-12-02 07:06:20 +0000
937@@ -0,0 +1,23 @@
938+/*
939+ * Copyright 2015 Canonical Ltd.
940+ *
941+ * This file is part of webbrowser-app.
942+ *
943+ * webbrowser-app is free software; you can redistribute it and/or modify
944+ * it under the terms of the GNU General Public License as published by
945+ * the Free Software Foundation; version 3.
946+ *
947+ * webbrowser-app is distributed in the hope that it will be useful,
948+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
949+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
950+ * GNU General Public License for more details.
951+ *
952+ * You should have received a copy of the GNU General Public License
953+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
954+ */
955+
956+import Ubuntu.Components 1.3
957+
958+Action {
959+ text: i18n.tr("Open link in default browser")
960+}
961
962=== added file 'webapp-googleplus/lib/actions/OpenLinkInNewBackgroundTab.qml'
963--- webapp-googleplus/lib/actions/OpenLinkInNewBackgroundTab.qml 1970-01-01 00:00:00 +0000
964+++ webapp-googleplus/lib/actions/OpenLinkInNewBackgroundTab.qml 2016-12-02 07:06:20 +0000
965@@ -0,0 +1,23 @@
966+/*
967+ * Copyright 2014-2015 Canonical Ltd.
968+ *
969+ * This file is part of webbrowser-app.
970+ *
971+ * webbrowser-app is free software; you can redistribute it and/or modify
972+ * it under the terms of the GNU General Public License as published by
973+ * the Free Software Foundation; version 3.
974+ *
975+ * webbrowser-app is distributed in the hope that it will be useful,
976+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
977+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
978+ * GNU General Public License for more details.
979+ *
980+ * You should have received a copy of the GNU General Public License
981+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
982+ */
983+
984+import Ubuntu.Components 1.3
985+
986+Action {
987+ text: i18n.tr("Open link in new background tab")
988+}
989
990=== modified file 'webapp-googleplus/lib/actions/OpenLinkInNewTab.qml'
991--- webapp-googleplus/actions/OpenLinkInNewTab.qml 2015-03-13 16:35:21 +0000
992+++ webapp-googleplus/lib/actions/OpenLinkInNewTab.qml 2016-12-02 07:06:20 +0000
993@@ -1,5 +1,5 @@
994 /*
995- * Copyright 2013-2014 Canonical Ltd.
996+ * Copyright 2013-2015 Canonical Ltd.
997 *
998 * This file is part of webbrowser-app.
999 *
1000@@ -16,7 +16,7 @@
1001 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1002 */
1003
1004-import Ubuntu.Components 1.1
1005+import Ubuntu.Components 1.3
1006
1007 Action {
1008 text: i18n.tr("Open link in new tab")
1009
1010=== added file 'webapp-googleplus/lib/actions/OpenLinkInNewWindow.qml'
1011--- webapp-googleplus/lib/actions/OpenLinkInNewWindow.qml 1970-01-01 00:00:00 +0000
1012+++ webapp-googleplus/lib/actions/OpenLinkInNewWindow.qml 2016-12-02 07:06:20 +0000
1013@@ -0,0 +1,23 @@
1014+/*
1015+ * Copyright 2016 Canonical Ltd.
1016+ *
1017+ * This file is part of webbrowser-app.
1018+ *
1019+ * webbrowser-app is free software; you can redistribute it and/or modify
1020+ * it under the terms of the GNU General Public License as published by
1021+ * the Free Software Foundation; version 3.
1022+ *
1023+ * webbrowser-app is distributed in the hope that it will be useful,
1024+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1025+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1026+ * GNU General Public License for more details.
1027+ *
1028+ * You should have received a copy of the GNU General Public License
1029+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1030+ */
1031+
1032+import Ubuntu.Components 1.3
1033+
1034+Action {
1035+ text: i18n.tr("Open link in new window")
1036+}
1037
1038=== added file 'webapp-googleplus/lib/actions/OpenLinkInPrivateWindow.qml'
1039--- webapp-googleplus/lib/actions/OpenLinkInPrivateWindow.qml 1970-01-01 00:00:00 +0000
1040+++ webapp-googleplus/lib/actions/OpenLinkInPrivateWindow.qml 2016-12-02 07:06:20 +0000
1041@@ -0,0 +1,23 @@
1042+/*
1043+ * Copyright 2016 Canonical Ltd.
1044+ *
1045+ * This file is part of webbrowser-app.
1046+ *
1047+ * webbrowser-app is free software; you can redistribute it and/or modify
1048+ * it under the terms of the GNU General Public License as published by
1049+ * the Free Software Foundation; version 3.
1050+ *
1051+ * webbrowser-app is distributed in the hope that it will be useful,
1052+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1053+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1054+ * GNU General Public License for more details.
1055+ *
1056+ * You should have received a copy of the GNU General Public License
1057+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1058+ */
1059+
1060+import Ubuntu.Components 1.3
1061+
1062+Action {
1063+ text: i18n.tr("Open link in private window")
1064+}
1065
1066=== added file 'webapp-googleplus/lib/actions/OpenVideoInNewTab.qml'
1067--- webapp-googleplus/lib/actions/OpenVideoInNewTab.qml 1970-01-01 00:00:00 +0000
1068+++ webapp-googleplus/lib/actions/OpenVideoInNewTab.qml 2016-12-02 07:06:20 +0000
1069@@ -0,0 +1,23 @@
1070+/*
1071+ * Copyright 2016 Canonical Ltd.
1072+ *
1073+ * This file is part of webbrowser-app.
1074+ *
1075+ * webbrowser-app is free software; you can redistribute it and/or modify
1076+ * it under the terms of the GNU General Public License as published by
1077+ * the Free Software Foundation; version 3.
1078+ *
1079+ * webbrowser-app is distributed in the hope that it will be useful,
1080+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1081+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1082+ * GNU General Public License for more details.
1083+ *
1084+ * You should have received a copy of the GNU General Public License
1085+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1086+ */
1087+
1088+import Ubuntu.Components 1.3
1089+
1090+Action {
1091+ text: i18n.tr("Open video in new tab")
1092+}
1093
1094=== added file 'webapp-googleplus/lib/actions/Paste.qml'
1095--- webapp-googleplus/lib/actions/Paste.qml 1970-01-01 00:00:00 +0000
1096+++ webapp-googleplus/lib/actions/Paste.qml 2016-12-02 07:06:20 +0000
1097@@ -0,0 +1,23 @@
1098+/*
1099+ * Copyright 2015 Canonical Ltd.
1100+ *
1101+ * This file is part of webbrowser-app.
1102+ *
1103+ * webbrowser-app is free software; you can redistribute it and/or modify
1104+ * it under the terms of the GNU General Public License as published by
1105+ * the Free Software Foundation; version 3.
1106+ *
1107+ * webbrowser-app is distributed in the hope that it will be useful,
1108+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1109+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1110+ * GNU General Public License for more details.
1111+ *
1112+ * You should have received a copy of the GNU General Public License
1113+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1114+ */
1115+
1116+import Ubuntu.Components 1.3
1117+
1118+Action {
1119+ text: i18n.tr("Paste")
1120+}
1121
1122=== added file 'webapp-googleplus/lib/actions/Redo.qml'
1123--- webapp-googleplus/lib/actions/Redo.qml 1970-01-01 00:00:00 +0000
1124+++ webapp-googleplus/lib/actions/Redo.qml 2016-12-02 07:06:20 +0000
1125@@ -0,0 +1,23 @@
1126+/*
1127+ * Copyright 2015 Canonical Ltd.
1128+ *
1129+ * This file is part of webbrowser-app.
1130+ *
1131+ * webbrowser-app is free software; you can redistribute it and/or modify
1132+ * it under the terms of the GNU General Public License as published by
1133+ * the Free Software Foundation; version 3.
1134+ *
1135+ * webbrowser-app is distributed in the hope that it will be useful,
1136+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1137+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1138+ * GNU General Public License for more details.
1139+ *
1140+ * You should have received a copy of the GNU General Public License
1141+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1142+ */
1143+
1144+import Ubuntu.Components 1.3
1145+
1146+Action {
1147+ text: i18n.tr("Redo")
1148+}
1149
1150=== modified file 'webapp-googleplus/lib/actions/Reload.qml'
1151--- webapp-googleplus/actions/Reload.qml 2015-03-13 16:35:21 +0000
1152+++ webapp-googleplus/lib/actions/Reload.qml 2016-12-02 07:06:20 +0000
1153@@ -1,5 +1,5 @@
1154 /*
1155- * Copyright 2013-2014 Canonical Ltd.
1156+ * Copyright 2013-2015 Canonical Ltd.
1157 *
1158 * This file is part of webbrowser-app.
1159 *
1160@@ -16,7 +16,7 @@
1161 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1162 */
1163
1164-import Ubuntu.Components 1.1
1165+import Ubuntu.Components 1.3
1166 import Ubuntu.Unity.Action 1.1 as UnityActions
1167
1168 UnityActions.Action {
1169
1170=== modified file 'webapp-googleplus/lib/actions/SaveImage.qml'
1171--- webapp-googleplus/actions/SaveImage.qml 2015-03-13 16:35:21 +0000
1172+++ webapp-googleplus/lib/actions/SaveImage.qml 2016-12-02 07:06:20 +0000
1173@@ -1,5 +1,5 @@
1174 /*
1175- * Copyright 2014 Canonical Ltd.
1176+ * Copyright 2014-2015 Canonical Ltd.
1177 *
1178 * This file is part of webbrowser-app.
1179 *
1180@@ -16,7 +16,7 @@
1181 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1182 */
1183
1184-import Ubuntu.Components 1.1
1185+import Ubuntu.Components 1.3
1186
1187 Action {
1188 text: i18n.tr("Save image")
1189
1190=== added file 'webapp-googleplus/lib/actions/SaveLink.qml'
1191--- webapp-googleplus/lib/actions/SaveLink.qml 1970-01-01 00:00:00 +0000
1192+++ webapp-googleplus/lib/actions/SaveLink.qml 2016-12-02 07:06:20 +0000
1193@@ -0,0 +1,23 @@
1194+/*
1195+ * Copyright 2015 Canonical Ltd.
1196+ *
1197+ * This file is part of webbrowser-app.
1198+ *
1199+ * webbrowser-app is free software; you can redistribute it and/or modify
1200+ * it under the terms of the GNU General Public License as published by
1201+ * the Free Software Foundation; version 3.
1202+ *
1203+ * webbrowser-app is distributed in the hope that it will be useful,
1204+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1205+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1206+ * GNU General Public License for more details.
1207+ *
1208+ * You should have received a copy of the GNU General Public License
1209+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1210+ */
1211+
1212+import Ubuntu.Components 1.3
1213+
1214+Action {
1215+ text: i18n.tr("Save link")
1216+}
1217
1218=== added file 'webapp-googleplus/lib/actions/SaveVideo.qml'
1219--- webapp-googleplus/lib/actions/SaveVideo.qml 1970-01-01 00:00:00 +0000
1220+++ webapp-googleplus/lib/actions/SaveVideo.qml 2016-12-02 07:06:20 +0000
1221@@ -0,0 +1,23 @@
1222+/*
1223+ * Copyright 2016 Canonical Ltd.
1224+ *
1225+ * This file is part of webbrowser-app.
1226+ *
1227+ * webbrowser-app is free software; you can redistribute it and/or modify
1228+ * it under the terms of the GNU General Public License as published by
1229+ * the Free Software Foundation; version 3.
1230+ *
1231+ * webbrowser-app is distributed in the hope that it will be useful,
1232+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1233+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1234+ * GNU General Public License for more details.
1235+ *
1236+ * You should have received a copy of the GNU General Public License
1237+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1238+ */
1239+
1240+import Ubuntu.Components 1.3
1241+
1242+Action {
1243+ text: i18n.tr("Save video")
1244+}
1245
1246=== added file 'webapp-googleplus/lib/actions/SelectAll.qml'
1247--- webapp-googleplus/lib/actions/SelectAll.qml 1970-01-01 00:00:00 +0000
1248+++ webapp-googleplus/lib/actions/SelectAll.qml 2016-12-02 07:06:20 +0000
1249@@ -0,0 +1,23 @@
1250+/*
1251+ * Copyright 2015 Canonical Ltd.
1252+ *
1253+ * This file is part of webbrowser-app.
1254+ *
1255+ * webbrowser-app is free software; you can redistribute it and/or modify
1256+ * it under the terms of the GNU General Public License as published by
1257+ * the Free Software Foundation; version 3.
1258+ *
1259+ * webbrowser-app is distributed in the hope that it will be useful,
1260+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1261+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1262+ * GNU General Public License for more details.
1263+ *
1264+ * You should have received a copy of the GNU General Public License
1265+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1266+ */
1267+
1268+import Ubuntu.Components 1.3
1269+
1270+Action {
1271+ text: i18n.tr("Select all")
1272+}
1273
1274=== added file 'webapp-googleplus/lib/actions/Share.qml'
1275--- webapp-googleplus/lib/actions/Share.qml 1970-01-01 00:00:00 +0000
1276+++ webapp-googleplus/lib/actions/Share.qml 2016-12-02 07:06:20 +0000
1277@@ -0,0 +1,24 @@
1278+/*
1279+ * Copyright 2014-2015 Canonical Ltd.
1280+ *
1281+ * This file is part of webbrowser-app.
1282+ *
1283+ * webbrowser-app is free software; you can redistribute it and/or modify
1284+ * it under the terms of the GNU General Public License as published by
1285+ * the Free Software Foundation; version 3.
1286+ *
1287+ * webbrowser-app is distributed in the hope that it will be useful,
1288+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1289+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1290+ * GNU General Public License for more details.
1291+ *
1292+ * You should have received a copy of the GNU General Public License
1293+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1294+ */
1295+
1296+import Ubuntu.Components 1.3
1297+
1298+Action {
1299+ text: i18n.tr("Share")
1300+ iconName: "share"
1301+}
1302
1303=== added file 'webapp-googleplus/lib/actions/Undo.qml'
1304--- webapp-googleplus/lib/actions/Undo.qml 1970-01-01 00:00:00 +0000
1305+++ webapp-googleplus/lib/actions/Undo.qml 2016-12-02 07:06:20 +0000
1306@@ -0,0 +1,23 @@
1307+/*
1308+ * Copyright 2015 Canonical Ltd.
1309+ *
1310+ * This file is part of webbrowser-app.
1311+ *
1312+ * webbrowser-app is free software; you can redistribute it and/or modify
1313+ * it under the terms of the GNU General Public License as published by
1314+ * the Free Software Foundation; version 3.
1315+ *
1316+ * webbrowser-app is distributed in the hope that it will be useful,
1317+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1318+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1319+ * GNU General Public License for more details.
1320+ *
1321+ * You should have received a copy of the GNU General Public License
1322+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1323+ */
1324+
1325+import Ubuntu.Components 1.3
1326+
1327+Action {
1328+ text: i18n.tr("Undo")
1329+}
1330
1331=== added directory 'webapp-googleplus/lib/webcontainer'
1332=== added file 'webapp-googleplus/lib/webcontainer/AccountChooserDialog.qml'
1333--- webapp-googleplus/lib/webcontainer/AccountChooserDialog.qml 1970-01-01 00:00:00 +0000
1334+++ webapp-googleplus/lib/webcontainer/AccountChooserDialog.qml 2016-12-02 07:06:20 +0000
1335@@ -0,0 +1,124 @@
1336+/*
1337+ * Copyright 2013-2015 Canonical Ltd.
1338+ *
1339+ * This file is part of webbrowser-app.
1340+ *
1341+ * webbrowser-app is free software; you can redistribute it and/or modify
1342+ * it under the terms of the GNU General Public License as published by
1343+ * the Free Software Foundation; version 3.
1344+ *
1345+ * webbrowser-app is distributed in the hope that it will be useful,
1346+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1347+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1348+ * GNU General Public License for more details.
1349+ *
1350+ * You should have received a copy of the GNU General Public License
1351+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1352+ */
1353+
1354+import QtQuick 2.4
1355+import Qt.labs.settings 1.0
1356+import Ubuntu.Components 1.3
1357+import Ubuntu.Components.ListItems 1.3 as ListItem
1358+import Ubuntu.OnlineAccounts 0.1
1359+import Ubuntu.OnlineAccounts.Client 0.1
1360+
1361+SplashScreen {
1362+ id: root
1363+
1364+ property string providerId: ""
1365+ property string applicationId: ""
1366+ property bool accountMandatory: true
1367+ property var accountsModel: null
1368+
1369+ signal accountSelected(int accountId)
1370+ signal cancel()
1371+
1372+ property var __selectedAccount: settings.selectedAccount
1373+
1374+ Settings {
1375+ id: settings
1376+ property int selectedAccount
1377+ }
1378+
1379+ Setup {
1380+ id: setup
1381+ applicationId: root.applicationId
1382+ providerId: root.providerId
1383+ onFinished: {
1384+ if ("accountId" in reply) {
1385+ root.chooseAccount(reply.accountId)
1386+ } else {
1387+ root.cancel()
1388+ }
1389+ }
1390+ }
1391+
1392+ Column {
1393+ anchors { left: parent.left; right: parent.right }
1394+ spacing: units.gu(1)
1395+
1396+ ListItem.Caption {
1397+ text: i18n.tr("No accounts have been linked to this webapp; press the item below to add an account.")
1398+ visible: accountsModel.count === 0
1399+ }
1400+
1401+ Repeater {
1402+ model: accountsModel
1403+ AccountItem {
1404+ providerName: model.providerName
1405+ accountName: model.displayName
1406+ selected: model.accountId === root.__selectedAccount
1407+ onClicked: root.onConfirmed(model.accountId)
1408+ }
1409+ }
1410+
1411+ ListItem.Standard {
1412+ id: addAccountButton
1413+ text: i18n.tr("Add account")
1414+ iconName: "add"
1415+ selected: root.__selectedAccount === -1
1416+ onClicked: root.onConfirmed(-1)
1417+ }
1418+
1419+ ListItem.Standard {
1420+ id: skipButton
1421+ visible: !root.accountMandatory
1422+ text: i18n.tr("Don't use an account")
1423+ selected: root.__selectedAccount === -2
1424+ onClicked: root.onConfirmed(-2)
1425+ }
1426+
1427+ Button {
1428+ anchors.left: parent.left
1429+ anchors.right: parent.right
1430+ anchors.margins: units.gu(1)
1431+ text: i18n.tr("Cancel")
1432+ onClicked: root.cancel()
1433+ }
1434+ }
1435+
1436+ function chooseAccount(accountId) {
1437+ for (var i = 0; i < accountsModel.count; i++) {
1438+ if (accountsModel.get(i, "accountId") === accountId) {
1439+ settings.selectedAccount = accountId
1440+ root.accountSelected(accountId)
1441+ return
1442+ }
1443+ }
1444+
1445+ // The selected account was not found
1446+ settings.selectedAccount = -1
1447+ root.cancel()
1448+ }
1449+
1450+ function onConfirmed(account) {
1451+ if (account === -2) {
1452+ root.selectedAccount(0)
1453+ } else if (account === -1) {
1454+ setup.exec()
1455+ } else {
1456+ chooseAccount(account)
1457+ }
1458+ }
1459+}
1460
1461=== added file 'webapp-googleplus/lib/webcontainer/AccountErrorScreen.qml'
1462--- webapp-googleplus/lib/webcontainer/AccountErrorScreen.qml 1970-01-01 00:00:00 +0000
1463+++ webapp-googleplus/lib/webcontainer/AccountErrorScreen.qml 2016-12-02 07:06:20 +0000
1464@@ -0,0 +1,54 @@
1465+/*
1466+ * Copyright 2015 Canonical Ltd.
1467+ *
1468+ * This file is part of webbrowser-app.
1469+ *
1470+ * webbrowser-app is free software; you can redistribute it and/or modify
1471+ * it under the terms of the GNU General Public License as published by
1472+ * the Free Software Foundation; version 3.
1473+ *
1474+ * webbrowser-app is distributed in the hope that it will be useful,
1475+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1476+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1477+ * GNU General Public License for more details.
1478+ *
1479+ * You should have received a copy of the GNU General Public License
1480+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1481+ */
1482+
1483+import QtQuick 2.4
1484+import Ubuntu.Components 1.3
1485+
1486+Rectangle {
1487+ id: root
1488+
1489+ property alias message: messageLabel.text
1490+ signal closed()
1491+
1492+ anchors.fill: parent
1493+
1494+ Column {
1495+ anchors.fill: parent
1496+ anchors.margins: units.gu(4)
1497+
1498+ spacing: units.gu(3)
1499+
1500+ Label {
1501+ width: parent.width
1502+ fontSize: "x-large"
1503+ text: i18n.tr("Account error")
1504+ }
1505+
1506+ Label {
1507+ id: messageLabel
1508+ width: parent.width
1509+ wrapMode: Text.Wrap
1510+ }
1511+
1512+ Button {
1513+ anchors.horizontalCenter: parent.horizontalCenter
1514+ text: i18n.tr("Close")
1515+ onClicked: root.closed()
1516+ }
1517+ }
1518+}
1519
1520=== added file 'webapp-googleplus/lib/webcontainer/AccountItem.qml'
1521--- webapp-googleplus/lib/webcontainer/AccountItem.qml 1970-01-01 00:00:00 +0000
1522+++ webapp-googleplus/lib/webcontainer/AccountItem.qml 2016-12-02 07:06:20 +0000
1523@@ -0,0 +1,31 @@
1524+/*
1525+ * Copyright 2013-2015 Canonical Ltd.
1526+ *
1527+ * This file is part of webbrowser-app.
1528+ *
1529+ * webbrowser-app is free software; you can redistribute it and/or modify
1530+ * it under the terms of the GNU General Public License as published by
1531+ * the Free Software Foundation; version 3.
1532+ *
1533+ * webbrowser-app is distributed in the hope that it will be useful,
1534+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1535+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1536+ * GNU General Public License for more details.
1537+ *
1538+ * You should have received a copy of the GNU General Public License
1539+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1540+ */
1541+
1542+import QtQuick 2.4
1543+import Ubuntu.Components 1.3
1544+import Ubuntu.Components.ListItems 1.3 as ListItem
1545+
1546+ListItem.Subtitled {
1547+ id: root
1548+
1549+ property string providerName
1550+ property string accountName
1551+
1552+ text: providerName
1553+ subText: accountName
1554+}
1555
1556=== added file 'webapp-googleplus/lib/webcontainer/AccountsLogic.qml'
1557--- webapp-googleplus/lib/webcontainer/AccountsLogic.qml 1970-01-01 00:00:00 +0000
1558+++ webapp-googleplus/lib/webcontainer/AccountsLogic.qml 2016-12-02 07:06:20 +0000
1559@@ -0,0 +1,231 @@
1560+/*
1561+ * Copyright 2015 Canonical Ltd.
1562+ *
1563+ * This file is part of webbrowser-app.
1564+ *
1565+ * webbrowser-app is free software; you can redistribute it and/or modify
1566+ * it under the terms of the GNU General Public License as published by
1567+ * the Free Software Foundation; version 3.
1568+ *
1569+ * webbrowser-app is distributed in the hope that it will be useful,
1570+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1571+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1572+ * GNU General Public License for more details.
1573+ *
1574+ * You should have received a copy of the GNU General Public License
1575+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1576+ */
1577+
1578+import QtQuick 2.4
1579+import Qt.labs.settings 1.0
1580+import Ubuntu.OnlineAccounts 0.1
1581+import Ubuntu.OnlineAccounts.Client 0.1
1582+import webcontainer.private 0.1
1583+
1584+Item {
1585+ id: root
1586+
1587+ property alias providerId: accountsModelObject.provider
1588+ property alias applicationId: accountsModelObject.applicationId
1589+ property bool accountSwitcher: false
1590+ property var accountsModel: accountsModelObject
1591+
1592+ signal splashScreenRequested()
1593+ signal errorScreenRequested(string message)
1594+ signal accountSelected(int credentialsId, bool willMoveCookies)
1595+ signal contextReady()
1596+ signal quitRequested()
1597+
1598+ property var __account: null
1599+ property int __credentialsId: __account ? __account.authData.credentialsId : 0
1600+
1601+ Timer {
1602+ id: checkTimer
1603+ running: true
1604+ repeat: false
1605+ onTriggered: checkAccounts()
1606+ interval: 100
1607+ }
1608+
1609+ AccountServiceModel {
1610+ id: accountsModelObject
1611+ }
1612+
1613+ // This is only used if accountSwitcher is false
1614+ Setup {
1615+ id: setup
1616+ applicationId: root.applicationId
1617+ providerId: root.providerId
1618+ onFinished: {
1619+ if ("accountId" in reply) {
1620+ root.checkAccounts()
1621+ } else if ("errorName" in reply) {
1622+ root.errorScreenRequested(i18n.tr("Account window could not be opened. You can only create one account at a time; please try again after closing all other account windows."))
1623+ } else {
1624+ root.quitRequested()
1625+ }
1626+ }
1627+ }
1628+
1629+ Settings {
1630+ id: settings
1631+ property int selectedAccount: -1
1632+ property string initializedAccounts: "[]"
1633+ }
1634+
1635+ Component {
1636+ id: accountComponent
1637+ AccountService { }
1638+ }
1639+
1640+ Component {
1641+ id: onlineAccountStoreComponent
1642+ OnlineAccountsCookieStore { }
1643+ }
1644+
1645+ Component {
1646+ id: oxideCookieStoreComponent
1647+ ChromeCookieStore { }
1648+ }
1649+
1650+ function checkAccounts() {
1651+ checkTimer.stop()
1652+ console.log("Accounts: " + accountsModel.count)
1653+
1654+ /* If account switching is not supported, we just pick the first
1655+ * account here. */
1656+ if (!accountSwitcher) {
1657+ if (accountsModel.count === 0) {
1658+ setup.exec()
1659+ } else {
1660+ settings.selectedAccount = accountsModel.get(0, "accountId")
1661+ setupAccount(settings.selectedAccount)
1662+ }
1663+ return
1664+ }
1665+
1666+ if (accountsModel.count === 0) {
1667+ settings.selectedAccount = -1
1668+ } else if (settings.selectedAccount > 0) {
1669+ // check that the account exists
1670+ for (var i = 0; i < accountsModel.count; i++) {
1671+ if (accountsModel.get(i, "accountId") === settings.selectedAccount) {
1672+ break;
1673+ }
1674+ }
1675+ if (i >= accountsModel.count) {
1676+ // The selected account was not found
1677+ settings.selectedAccount = -1
1678+ }
1679+ }
1680+
1681+ if (settings.selectedAccount < 0) {
1682+ splashScreenRequested()
1683+ } else {
1684+ setupAccount(settings.selectedAccount)
1685+ }
1686+ }
1687+
1688+ function proceedWithNoAccount() {
1689+ __account = null
1690+ settings.selectedAccount = 0
1691+ accountSelected(__credentialsId, false)
1692+ }
1693+
1694+ function setupAccount(accountId) {
1695+ console.log("Setup account " + accountId)
1696+ if (__account && accountId === __account.accountId) {
1697+ console.log("Same as current account")
1698+ accountSelected(__credentialsId, false)
1699+ return
1700+ }
1701+ __account = null
1702+ for (var i = 0; i < accountsModel.count; i++) {
1703+ if (accountsModel.get(i, "accountId") === accountId) {
1704+ var accountHandle = accountsModel.get(i, "accountServiceHandle")
1705+ __account = accountComponent.createObject(root, {
1706+ objectHandle: accountHandle
1707+ })
1708+ break;
1709+ }
1710+ }
1711+ console.log("Credentials ID: " + __credentialsId)
1712+ settings.selectedAccount = accountId
1713+ accountSelected(__credentialsId, mustMoveCookies(accountId))
1714+ }
1715+
1716+ function login(account, callback) {
1717+ console.log("Preparing for login")
1718+
1719+ function authenticatedCallback() {
1720+ console.log("Authenticated!")
1721+ account.authenticated.disconnect(authenticatedCallback)
1722+ callback(true)
1723+ }
1724+ account.authenticated.connect(authenticatedCallback)
1725+
1726+ function errorCallback() {
1727+ console.log("Authentication error!")
1728+ account.authenticationError.disconnect(errorCallback)
1729+ callback(false)
1730+ }
1731+ account.authenticationError.connect(errorCallback)
1732+
1733+ account.authenticate(null)
1734+ }
1735+
1736+ function mustMoveCookies(accountId) {
1737+ var initializedAccounts
1738+ try {
1739+ initializedAccounts = JSON.parse(settings.initializedAccounts)
1740+ } catch(e) {
1741+ initializedAccounts = []
1742+ }
1743+ return initializedAccounts.indexOf(accountId) < 0
1744+ }
1745+
1746+ function rememberCookiesMoved(accountId) {
1747+ var initializedAccounts = JSON.parse(settings.initializedAccounts)
1748+ if (initializedAccounts.indexOf(accountId) < 0) {
1749+ initializedAccounts.push(accountId)
1750+ settings.initializedAccounts = JSON.stringify(initializedAccounts)
1751+ }
1752+ }
1753+
1754+ function onCookiesMoved(result) {
1755+ if (!result) {
1756+ console.log("Cookies were not moved")
1757+ } else {
1758+ console.log("cookies moved")
1759+ }
1760+ // Even if the cookies were not moved, we don't want to retry
1761+ rememberCookiesMoved(__account.accountId)
1762+ contextReady()
1763+ }
1764+
1765+ function setupWebcontextForAccount(webcontext) {
1766+ if (!__account || !mustMoveCookies(__account.accountId)) {
1767+ contextReady()
1768+ return
1769+ }
1770+
1771+ login(__account, function(authenticated) {
1772+ if (!authenticated) {
1773+ errorScreenRequested(i18n.tr("Authentication failed"))
1774+ } else {
1775+ console.log("Authentication succeeded, moving cookies")
1776+ var accountsCookieStore = onlineAccountStoreComponent.createObject(root, {
1777+ "accountId": __credentialsId
1778+ })
1779+
1780+ var webappCookieStore = oxideCookieStoreComponent.createObject(root, {
1781+ "oxideStoreBackend": webcontext.cookieManager,
1782+ "dbPath": webcontext.dataPath + "/cookies.sqlite"
1783+ })
1784+
1785+ webappCookieStore.moved.connect(onCookiesMoved)
1786+ webappCookieStore.moveFrom(accountsCookieStore)
1787+ }
1788+ })
1789+ }
1790+}
1791
1792=== added file 'webapp-googleplus/lib/webcontainer/AccountsPage.qml'
1793--- webapp-googleplus/lib/webcontainer/AccountsPage.qml 1970-01-01 00:00:00 +0000
1794+++ webapp-googleplus/lib/webcontainer/AccountsPage.qml 2016-12-02 07:06:20 +0000
1795@@ -0,0 +1,137 @@
1796+/*
1797+ * Copyright 2013-2015 Canonical Ltd.
1798+ *
1799+ * This file is part of webbrowser-app.
1800+ *
1801+ * webbrowser-app is free software; you can redistribute it and/or modify
1802+ * it under the terms of the GNU General Public License as published by
1803+ * the Free Software Foundation; version 3.
1804+ *
1805+ * webbrowser-app is distributed in the hope that it will be useful,
1806+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1807+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1808+ * GNU General Public License for more details.
1809+ *
1810+ * You should have received a copy of the GNU General Public License
1811+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1812+ */
1813+
1814+import QtQuick 2.4
1815+import Ubuntu.Components 1.3
1816+import Ubuntu.OnlineAccounts 0.1
1817+import webcontainer.private 0.1
1818+
1819+Item {
1820+ id: root
1821+
1822+ property alias providerId: accountsLogic.providerId
1823+ property alias applicationId: accountsLogic.applicationId
1824+ property alias accountSwitcher: accountsLogic.accountSwitcher
1825+ property string webappName: ""
1826+ property url webappIcon
1827+
1828+ signal accountSelected(string accountDataLocation, bool willMoveCookies)
1829+ signal contextReady()
1830+ signal quitRequested()
1831+
1832+ property string __providerName: providerId
1833+ property string __lastAccountDataLocation: ""
1834+
1835+ anchors.fill: parent
1836+
1837+ AccountsLogic {
1838+ id: accountsLogic
1839+
1840+ onSplashScreenRequested: showSplashScreen()
1841+ onAccountSelected: root.__emitAccountSelected(credentialsId, willMoveCookies)
1842+ onContextReady: root.contextReady()
1843+ onQuitRequested: root.quitRequested()
1844+ onErrorScreenRequested: showErrorScreen(message)
1845+ }
1846+
1847+ AccountsSplashScreen {
1848+ id: splashScreen
1849+
1850+ visible: false
1851+ providerName: root.__providerName
1852+ applicationName: root.webappName
1853+ iconSource: root.webappIcon
1854+
1855+ onChooseAccount: root.showAccountSwitcher()
1856+ onQuitRequested: root.quitRequested()
1857+ onSkip: accountsLogic.proceedWithNoAccount()
1858+ }
1859+
1860+ // Only temporarily used for bug https://bugs.launchpad.net/bugs/1441873
1861+ AccountErrorScreen {
1862+ id: errorScreen
1863+
1864+ visible: false
1865+ onClosed: root.quitRequested()
1866+ }
1867+
1868+ Loader {
1869+ id: accountChooserLoader
1870+ anchors.fill: parent
1871+ }
1872+
1873+ Component {
1874+ id: accountChooserComponent
1875+ AccountChooserDialog {
1876+ id: accountChooser
1877+ applicationName: root.webappName
1878+ iconSource: root.webappIcon
1879+ providerId: root.providerId
1880+ applicationId: root.applicationId
1881+ accountsModel: accountsLogic.accountsModel
1882+ onCancel: {
1883+ accountChooserLoader.sourceComponent = null
1884+ root.accountSelected(root.__lastAccountDataLocation, false)
1885+ }
1886+ onAccountSelected: {
1887+ accountChooserLoader.sourceComponent = null
1888+ accountsLogic.setupAccount(accountId)
1889+ }
1890+ }
1891+ }
1892+
1893+ ProviderModel {
1894+ id: providerModel
1895+ applicationId: root.applicationId
1896+ }
1897+
1898+ function __setupProviderData() {
1899+ for (var i = 0; i < providerModel.count; i++) {
1900+ if (providerModel.get(i, "providerId") === root.providerId) {
1901+ root.__providerName = providerModel.get(i, "displayName")
1902+ break
1903+ }
1904+ }
1905+ }
1906+
1907+ Component.onCompleted: {
1908+ __setupProviderData()
1909+ }
1910+
1911+ function showErrorScreen(message) {
1912+ errorScreen.message = message
1913+ errorScreen.visible = true
1914+ }
1915+
1916+ function showSplashScreen() {
1917+ splashScreen.visible = true
1918+ }
1919+
1920+ function showAccountSwitcher() {
1921+ accountChooserLoader.sourceComponent = accountChooserComponent
1922+ }
1923+
1924+ function __emitAccountSelected(credentialsId, willMoveCookies) {
1925+ __lastAccountDataLocation = credentialsId > 0 ? ("/id-" + credentialsId) : ""
1926+ accountSelected(__lastAccountDataLocation, willMoveCookies)
1927+ }
1928+
1929+ function setupWebcontextForAccount(webcontext) {
1930+ accountsLogic.setupWebcontextForAccount(webcontext)
1931+ }
1932+}
1933
1934=== added file 'webapp-googleplus/lib/webcontainer/AccountsSplashScreen.qml'
1935--- webapp-googleplus/lib/webcontainer/AccountsSplashScreen.qml 1970-01-01 00:00:00 +0000
1936+++ webapp-googleplus/lib/webcontainer/AccountsSplashScreen.qml 2016-12-02 07:06:20 +0000
1937@@ -0,0 +1,89 @@
1938+/*
1939+ * Copyright 2015 Canonical Ltd.
1940+ *
1941+ * This file is part of webbrowser-app.
1942+ *
1943+ * webbrowser-app is free software; you can redistribute it and/or modify
1944+ * it under the terms of the GNU General Public License as published by
1945+ * the Free Software Foundation; version 3.
1946+ *
1947+ * webbrowser-app is distributed in the hope that it will be useful,
1948+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1949+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1950+ * GNU General Public License for more details.
1951+ *
1952+ * You should have received a copy of the GNU General Public License
1953+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1954+ */
1955+
1956+import QtQuick 2.4
1957+import Ubuntu.Components 1.3
1958+
1959+SplashScreen {
1960+ id: root
1961+
1962+ property string providerName
1963+ property bool accountMandatory: true
1964+
1965+ signal chooseAccount()
1966+ signal skip()
1967+ signal quitRequested()
1968+
1969+ Column {
1970+ anchors {
1971+ left: parent.left
1972+ right: parent.right
1973+ }
1974+ spacing: units.gu(2)
1975+
1976+ Label {
1977+ anchors.left: parent.left
1978+ anchors.right: parent.right
1979+ horizontalAlignment: Text.AlignHCenter
1980+ wrapMode: Text.WordWrap
1981+ // TRANSLATORS: %1 refers to the application name, %2 refers to the account provider
1982+ text: i18n.tr("<b>%1</b> needs to access your %2 online account.").arg(root.applicationName).arg(root.providerName)
1983+ visible: root.accountMandatory
1984+ }
1985+
1986+ Label {
1987+ anchors.left: parent.left
1988+ anchors.right: parent.right
1989+ horizontalAlignment: Text.AlignHCenter
1990+ wrapMode: Text.WordWrap
1991+ // TRANSLATORS: %1 refers to the application name, %2 refers to the account provider
1992+ text: i18n.tr("<b>%1</b> would like to access your %2 online account.").arg(root.applicationName).arg(root.providerName)
1993+ visible: !root.accountMandatory
1994+ }
1995+
1996+ Label {
1997+ anchors.left: parent.left
1998+ anchors.right: parent.right
1999+ horizontalAlignment: Text.AlignHCenter
2000+ wrapMode: Text.WordWrap
2001+ text: i18n.tr("Choose an account now, or skip this step and choose an online account later.")
2002+ visible: !root.accountMandatory
2003+ }
2004+
2005+ Item {
2006+ anchors.left: parent.left
2007+ anchors.right: parent.right
2008+ anchors.margins: units.gu(1)
2009+ height: units.gu(6)
2010+
2011+ Button {
2012+ anchors.left: parent.left
2013+ width: parent.width / 2 - units.gu(1)
2014+ text: root.accountMandatory ? i18n.tr("Close the app") : i18n.tr("Skip")
2015+ onClicked: root.accountMandatory ? root.quitRequested() : root.skip()
2016+ }
2017+
2018+ Button {
2019+ anchors.right: parent.right
2020+ width: parent.width / 2 - units.gu(1)
2021+ text: i18n.tr("Choose account")
2022+ onClicked: root.chooseAccount()
2023+ }
2024+ }
2025+ }
2026+}
2027
2028=== renamed file 'webapp-googleplus/lib/AuthenticationDialog.qml' => 'webapp-googleplus/lib/webcontainer/AuthenticationDialog.qml'
2029=== renamed file 'webapp-googleplus/lib/BrowserView.qml' => 'webapp-googleplus/lib/webcontainer/BrowserView.qml'
2030=== renamed file 'webapp-googleplus/lib/CertificateVerificationDialog.qml' => 'webapp-googleplus/lib/webcontainer/CertificateVerificationDialog.qml'
2031=== added file 'webapp-googleplus/lib/webcontainer/Chrome.qml'
2032--- webapp-googleplus/lib/webcontainer/Chrome.qml 1970-01-01 00:00:00 +0000
2033+++ webapp-googleplus/lib/webcontainer/Chrome.qml 2016-12-02 07:06:20 +0000
2034@@ -0,0 +1,160 @@
2035+/*
2036+ * Copyright 2013-2015 Canonical Ltd.
2037+ *
2038+ * This file is part of webbrowser-app.
2039+ *
2040+ * webbrowser-app is free software; you can redistribute it and/or modify
2041+ * it under the terms of the GNU General Public License as published by
2042+ * the Free Software Foundation; version 3.
2043+ *
2044+ * webbrowser-app is distributed in the hope that it will be useful,
2045+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2046+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2047+ * GNU General Public License for more details.
2048+ *
2049+ * You should have received a copy of the GNU General Public License
2050+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2051+ */
2052+
2053+import QtQuick 2.4
2054+import Ubuntu.Components 1.3
2055+import ".."
2056+
2057+ChromeBase {
2058+ id: chrome
2059+
2060+ property var webview: null
2061+ property bool navigationButtonsVisible: false
2062+ property bool accountSwitcher: false
2063+
2064+ loading: webview && webview.loading
2065+ loadProgress: loading ? webview.loadProgress : 0
2066+
2067+ function updateChromeElementsColor(color) {
2068+ chromeTextLabel.color = color
2069+
2070+ backButton.iconColor = color
2071+ forwardButton.iconColor = color
2072+
2073+ reloadButton.iconColor = color
2074+ accountsButton.iconColor = color
2075+ }
2076+
2077+ signal chooseAccount()
2078+
2079+ FocusScope {
2080+ anchors {
2081+ fill: parent
2082+ margins: units.gu(1)
2083+ }
2084+
2085+ focus: true
2086+
2087+ ChromeButton {
2088+ id: backButton
2089+ objectName: "backButton"
2090+
2091+ iconName: "previous"
2092+ iconSize: 0.6 * height
2093+
2094+ height: parent.height
2095+ visible: chrome.navigationButtonsVisible
2096+ width: visible ? height : 0
2097+
2098+ anchors {
2099+ left: parent.left
2100+ verticalCenter: parent.verticalCenter
2101+ }
2102+
2103+ enabled: chrome.webview ? chrome.webview.canGoBack : false
2104+ onTriggered: chrome.webview.goBack()
2105+ }
2106+
2107+ ChromeButton {
2108+ id: forwardButton
2109+ objectName: "forwardButton"
2110+
2111+ iconName: "next"
2112+ iconSize: 0.6 * height
2113+
2114+ height: parent.height
2115+ visible: chrome.navigationButtonsVisible && enabled
2116+ width: visible ? height : 0
2117+
2118+ anchors {
2119+ left: backButton.right
2120+ verticalCenter: parent.verticalCenter
2121+ }
2122+
2123+ enabled: chrome.webview ? chrome.webview.canGoForward : false
2124+ onTriggered: chrome.webview.goForward()
2125+ }
2126+
2127+ Item {
2128+ id: faviconContainer
2129+
2130+ height: parent.height
2131+ width: height
2132+ anchors.left: forwardButton.right
2133+
2134+ Favicon {
2135+ anchors.centerIn: parent
2136+ source: chrome.webview ? chrome.webview.icon : null
2137+ }
2138+ }
2139+
2140+ Label {
2141+ id: chromeTextLabel
2142+ objectName: "chromeTextLabel"
2143+
2144+ anchors {
2145+ left: faviconContainer.right
2146+ right: reloadButton.left
2147+ rightMargin: units.gu(1)
2148+ verticalCenter: parent.verticalCenter
2149+ }
2150+
2151+ text: chrome.webview.title ? chrome.webview.title : chrome.webview.url
2152+ elide: Text.ElideRight
2153+ }
2154+
2155+ ChromeButton {
2156+ id: reloadButton
2157+ objectName: "reloadButton"
2158+
2159+ iconName: "reload"
2160+ iconSize: 0.6 * height
2161+
2162+ height: parent.height
2163+ visible: chrome.navigationButtonsVisible
2164+ width: visible ? height : 0
2165+
2166+ anchors {
2167+ right: accountsButton.left
2168+ verticalCenter: parent.verticalCenter
2169+ }
2170+
2171+ enabled: chrome.webview.url && chrome.webview.url !== ""
2172+ onTriggered: chrome.webview.reload()
2173+ }
2174+
2175+ ChromeButton {
2176+ id: accountsButton
2177+ objectName: "accountsButton"
2178+
2179+ iconName: "contact"
2180+ iconSize: 0.6 * height
2181+
2182+ height: parent.height
2183+ width: visible ? height : 0
2184+
2185+ anchors {
2186+ right: parent.right
2187+ verticalCenter: parent.verticalCenter
2188+ }
2189+
2190+ visible: accountSwitcher
2191+ onTriggered: chrome.chooseAccount()
2192+ }
2193+ }
2194+}
2195
2196=== renamed file 'webapp-googleplus/lib/ChromeBase.qml' => 'webapp-googleplus/lib/webcontainer/ChromeBase.qml'
2197=== renamed file 'webapp-googleplus/lib/ChromeButton.qml' => 'webapp-googleplus/lib/webcontainer/ChromeButton.qml'
2198=== renamed file 'webapp-googleplus/lib/ChromeStateTracker.qml' => 'webapp-googleplus/lib/webcontainer/ChromeStateTracker.qml'
2199=== renamed file 'webapp-googleplus/lib/ContentDownloadDialog.qml' => 'webapp-googleplus/lib/webcontainer/ContentDownloadDialog.qml'
2200--- webapp-googleplus/lib/ContentDownloadDialog.qml 2015-03-13 16:35:21 +0000
2201+++ webapp-googleplus/lib/webcontainer/ContentDownloadDialog.qml 2016-12-02 07:06:20 +0000
2202@@ -1,5 +1,5 @@
2203 /*
2204- * Copyright 2014 Canonical Ltd.
2205+ * Copyright 2014-2015 Canonical Ltd.
2206 *
2207 * This file is part of webbrowser-app.
2208 *
2209@@ -16,34 +16,52 @@
2210 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2211 */
2212
2213-import QtQuick 2.0
2214-import Ubuntu.Components 1.1
2215-import Ubuntu.Components.Popups 1.0
2216-import Ubuntu.Content 0.1
2217-
2218-PopupBase {
2219- id: downloadDialog
2220- anchors.fill: parent
2221- property var activeTransfer
2222- property var downloadId
2223- property alias contentType: peerPicker.contentType
2224-
2225- Rectangle {
2226+import QtQuick 2.4
2227+import Ubuntu.Components 1.3
2228+import Ubuntu.Components.Popups 1.3
2229+import Ubuntu.Content 1.3
2230+import webbrowsercommon.private 0.1
2231+import ".."
2232+
2233+Component {
2234+ PopupBase {
2235+ id: downloadDialog
2236+ objectName: "downloadDialog"
2237 anchors.fill: parent
2238- ContentPeerPicker {
2239- id: peerPicker
2240+ property var activeTransfer
2241+ property var downloadId
2242+ property var singleDownload
2243+ property var mimeType
2244+ property var filename
2245+ property var icon: MimeDatabase.iconForMimetype(mimeType)
2246+ property alias contentType: peerPicker.contentType
2247+
2248+ ContentPeerModel {
2249+ id: peerModel
2250 handler: ContentHandler.Destination
2251- visible: parent.visible
2252-
2253- onPeerSelected: {
2254- activeTransfer = peer.request()
2255- activeTransfer.downloadId = downloadDialog.downloadId
2256- activeTransfer.state = ContentTransfer.Downloading
2257- PopupUtils.close(downloadDialog)
2258- }
2259-
2260- onCancelPressed: {
2261- PopupUtils.close(downloadDialog)
2262+ contentType: downloadDialog.contentType
2263+ }
2264+
2265+ Rectangle {
2266+ id: pickerRect
2267+ anchors.fill: parent
2268+ visible: true
2269+ ContentPeerPicker {
2270+ id: peerPicker
2271+ handler: ContentHandler.Destination
2272+ objectName: "contentPeerPicker"
2273+ visible: parent.visible
2274+
2275+ onPeerSelected: {
2276+ activeTransfer = peer.request()
2277+ activeTransfer.downloadId = downloadDialog.downloadId
2278+ activeTransfer.state = ContentTransfer.Downloading
2279+ PopupUtils.close(downloadDialog)
2280+ }
2281+
2282+ onCancelPressed: {
2283+ PopupUtils.close(downloadDialog)
2284+ }
2285 }
2286 }
2287 }
2288
2289=== renamed file 'webapp-googleplus/lib/ContentPickerDialog.qml' => 'webapp-googleplus/lib/webcontainer/ContentPickerDialog.qml'
2290--- webapp-googleplus/lib/ContentPickerDialog.qml 2015-03-13 16:35:21 +0000
2291+++ webapp-googleplus/lib/webcontainer/ContentPickerDialog.qml 2016-12-02 07:06:20 +0000
2292@@ -1,5 +1,5 @@
2293 /*
2294- * Copyright 2014 Canonical Ltd.
2295+ * Copyright 2014-2015 Canonical Ltd.
2296 *
2297 * This file is part of webbrowser-app.
2298 *
2299@@ -16,11 +16,12 @@
2300 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2301 */
2302
2303-import QtQuick 2.0
2304-import Ubuntu.Components 1.1
2305-import Ubuntu.Components.Popups 1.0 as Popups
2306-import Ubuntu.Content 0.1
2307-import "MimeTypeMapper.js" as MimeTypeMapper
2308+import QtQuick 2.4
2309+import Ubuntu.Components 1.3
2310+import Ubuntu.Components.Popups 1.3 as Popups
2311+import Ubuntu.Content 1.3
2312+import "../MimeTypeMapper.js" as MimeTypeMapper
2313+import ".."
2314
2315 Component {
2316 Popups.PopupBase {
2317@@ -33,7 +34,6 @@
2318 parent: QuickUtils.rootItem(this)
2319
2320 property var activeTransfer
2321- property var selectedItems
2322
2323 Rectangle {
2324 anchors.fill: parent
2325@@ -61,7 +61,6 @@
2326 }
2327
2328 onCancelPressed: {
2329- webview.focus = true
2330 model.reject()
2331 }
2332 }
2333@@ -69,30 +68,13 @@
2334
2335 Connections {
2336 id: stateChangeConnection
2337+ target: null
2338 onStateChanged: {
2339 if (picker.activeTransfer.state === ContentTransfer.Charged) {
2340- selectedItems = []
2341+ var selectedItems = []
2342 for(var i in picker.activeTransfer.items) {
2343 selectedItems.push(String(picker.activeTransfer.items[i].url).replace("file://", ""))
2344 }
2345- acceptTimer.running = true
2346- }
2347- }
2348- }
2349-
2350- // FIXME: Work around for browser becoming insensitive to touch events
2351- // if the dialog is dismissed while the application is inactive.
2352- // Just listening for changes to Qt.application.active doesn't appear
2353- // to be enough to resolve this, so it seems that something else needs
2354- // to be happening first. As such there's a potential for a race
2355- // condition here, although as yet no problem has been encountered.
2356- Timer {
2357- id: acceptTimer
2358- interval: 100
2359- repeat: true
2360- onTriggered: {
2361- if(Qt.application.active) {
2362- webview.focus = true
2363 model.accept(selectedItems)
2364 }
2365 }
2366
2367=== renamed file 'webapp-googleplus/lib/ContentShareDialog.qml' => 'webapp-googleplus/lib/webcontainer/ContentShareDialog.qml'
2368=== added file 'webapp-googleplus/lib/webcontainer/ContextMenuMobile.qml'
2369--- webapp-googleplus/lib/webcontainer/ContextMenuMobile.qml 1970-01-01 00:00:00 +0000
2370+++ webapp-googleplus/lib/webcontainer/ContextMenuMobile.qml 2016-12-02 07:06:20 +0000
2371@@ -0,0 +1,162 @@
2372+/*
2373+ * Copyright 2015-2016 Canonical Ltd.
2374+ *
2375+ * This file is part of webbrowser-app.
2376+ *
2377+ * webbrowser-app is free software; you can redistribute it and/or modify
2378+ * it under the terms of the GNU General Public License as published by
2379+ * the Free Software Foundation; version 3.
2380+ *
2381+ * webbrowser-app is distributed in the hope that it will be useful,
2382+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2383+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2384+ * GNU General Public License for more details.
2385+ *
2386+ * You should have received a copy of the GNU General Public License
2387+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2388+ */
2389+
2390+import QtQuick 2.4
2391+import Ubuntu.Components 1.3
2392+import Ubuntu.Components.ListItems 1.3 as ListItems
2393+import Ubuntu.Components.Popups 1.3 as Popups
2394+import com.canonical.Oxide 1.8 as Oxide
2395+
2396+Popups.Dialog {
2397+ property QtObject contextModel: model
2398+ property ActionList actions: null
2399+
2400+ objectName: "contextMenuMobile"
2401+
2402+ QtObject {
2403+ id: internal
2404+ readonly property bool isImage: (contextModel.mediaType === Oxide.WebView.MediaTypeImage) ||
2405+ (contextModel.mediaType === Oxide.WebView.MediaTypeCanvas)
2406+ }
2407+
2408+ Row {
2409+ id: header
2410+ spacing: units.gu(2)
2411+ anchors {
2412+ left: parent.left
2413+ leftMargin: units.gu(2)
2414+ right: parent.right
2415+ rightMargin: units.gu(2)
2416+ }
2417+ height: units.gu(2 * title.lineCount + 3)
2418+ visible: title.text
2419+
2420+ Icon {
2421+ width: units.gu(2)
2422+ height: units.gu(2)
2423+ anchors {
2424+ top: parent.top
2425+ topMargin: units.gu(2)
2426+ }
2427+ name: internal.isImage ? "stock_image" : ""
2428+ // work around the lack of a standard stock_link symbolic icon in the theme
2429+ Component.onCompleted: {
2430+ if (!name) {
2431+ source = "assets/stock_link.svg"
2432+ }
2433+ }
2434+ }
2435+
2436+ Label {
2437+ id: title
2438+ objectName: "titleLabel"
2439+ text: contextModel.srcUrl.toString() ? contextModel.srcUrl : contextModel.linkUrl
2440+ width: parent.width - units.gu(4)
2441+ anchors {
2442+ top: parent.top
2443+ topMargin: units.gu(2)
2444+ bottom: parent.bottom
2445+ }
2446+ fontSize: "x-small"
2447+ maximumLineCount: 2
2448+ wrapMode: Text.Wrap
2449+ height: contentHeight
2450+ }
2451+ }
2452+
2453+ ListItems.ThinDivider {
2454+ anchors {
2455+ left: parent.left
2456+ leftMargin: units.gu(2)
2457+ right: parent.right
2458+ rightMargin: units.gu(2)
2459+ }
2460+ visible: header.visible
2461+ }
2462+
2463+ Repeater {
2464+ model: actions.children
2465+ delegate: ListItems.Empty {
2466+ action: modelData
2467+ objectName: action.objectName + "_item"
2468+ visible: action.enabled
2469+ showDivider: false
2470+
2471+ height: units.gu(5)
2472+
2473+ Label {
2474+ anchors {
2475+ left: parent.left
2476+ leftMargin: units.gu(2)
2477+ right: parent.right
2478+ rightMargin: units.gu(2)
2479+ verticalCenter: parent.verticalCenter
2480+ }
2481+ fontSize: "x-small"
2482+ text: action.text
2483+ }
2484+
2485+ ListItems.ThinDivider {
2486+ anchors {
2487+ left: parent.left
2488+ leftMargin: units.gu(2)
2489+ right: parent.right
2490+ rightMargin: units.gu(2)
2491+ bottom: parent.bottom
2492+ }
2493+ }
2494+
2495+ onTriggered: contextModel.close()
2496+ }
2497+ }
2498+
2499+ ListItems.Empty {
2500+ objectName: "cancelAction"
2501+ height: units.gu(5)
2502+ showDivider: false
2503+ Label {
2504+ anchors {
2505+ left: parent.left
2506+ leftMargin: units.gu(2)
2507+ right: parent.right
2508+ rightMargin: units.gu(2)
2509+ verticalCenter: parent.verticalCenter
2510+ }
2511+ fontSize: "x-small"
2512+ text: i18n.tr("Cancel")
2513+ }
2514+ onTriggered: contextModel.close()
2515+ }
2516+
2517+ // adjust default dialog visuals to custom requirements for the context menu
2518+ Binding {
2519+ target: __foreground
2520+ property: "margins"
2521+ value: 0
2522+ }
2523+ Binding {
2524+ target: __foreground
2525+ property: "itemSpacing"
2526+ value: 0
2527+ }
2528+
2529+ // We can’t prevent the dialog from stealing the focus from
2530+ // the webview, but we can at least restore it when the
2531+ // dialog is closed (https://launchpad.net/bugs/1526884).
2532+ Component.onDestruction: Oxide.WebView.view.forceActiveFocus()
2533+}
2534
2535=== added file 'webapp-googleplus/lib/webcontainer/ContextMenuWide.qml'
2536--- webapp-googleplus/lib/webcontainer/ContextMenuWide.qml 1970-01-01 00:00:00 +0000
2537+++ webapp-googleplus/lib/webcontainer/ContextMenuWide.qml 2016-12-02 07:06:20 +0000
2538@@ -0,0 +1,158 @@
2539+/*
2540+ * Copyright 2015-2016 Canonical Ltd.
2541+ *
2542+ * This file is part of webbrowser-app.
2543+ *
2544+ * webbrowser-app is free software; you can redistribute it and/or modify
2545+ * it under the terms of the GNU General Public License as published by
2546+ * the Free Software Foundation; version 3.
2547+ *
2548+ * webbrowser-app is distributed in the hope that it will be useful,
2549+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2550+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2551+ * GNU General Public License for more details.
2552+ *
2553+ * You should have received a copy of the GNU General Public License
2554+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2555+ */
2556+
2557+import QtQuick 2.4
2558+import Ubuntu.Components 1.3
2559+import Ubuntu.Components.ListItems 1.3 as ListItems
2560+import Ubuntu.Components.Popups 1.3 as Popups
2561+import com.canonical.Oxide 1.8 as Oxide
2562+
2563+Popups.Popover {
2564+ id: contextMenu
2565+
2566+ objectName: "contextMenuWide"
2567+
2568+ property QtObject contextModel: model
2569+ property ActionList actions: null
2570+ property var associatedWebview: null
2571+
2572+ QtObject {
2573+ id: internal
2574+
2575+ readonly property int lastEnabledActionIndex: {
2576+ var last = -1
2577+ for (var i in actions.children) {
2578+ if (actions.children[i].enabled) {
2579+ last = i
2580+ }
2581+ }
2582+ return last
2583+ }
2584+
2585+ readonly property real locationBarOffset: contextMenu.associatedWebview.locationBarController.height
2586+ + contextMenu.associatedWebview.locationBarController.offset
2587+ }
2588+
2589+ Rectangle {
2590+ anchors.fill: parent
2591+ color: "#ececec"
2592+ }
2593+
2594+ Column {
2595+ anchors {
2596+ left: parent.left
2597+ right: parent.right
2598+ }
2599+
2600+ Label {
2601+ id: titleLabel
2602+ objectName: "titleLabel"
2603+ text: contextModel.srcUrl.toString() ? contextModel.srcUrl : contextModel.linkUrl
2604+ anchors {
2605+ left: parent.left
2606+ leftMargin: units.gu(2)
2607+ right: parent.right
2608+ rightMargin: units.gu(2)
2609+ }
2610+ height: units.gu(5)
2611+ visible: text
2612+ fontSize: "x-small"
2613+ color: "#888888"
2614+ elide: Text.ElideRight
2615+ verticalAlignment: Text.AlignVCenter
2616+ }
2617+
2618+ ListItems.ThinDivider {
2619+ anchors {
2620+ left: parent.left
2621+ leftMargin: units.gu(2)
2622+ right: parent.right
2623+ rightMargin: units.gu(2)
2624+ }
2625+ visible: titleLabel.visible
2626+ }
2627+
2628+ Repeater {
2629+ model: actions.children
2630+ delegate: ListItems.Empty {
2631+ action: modelData
2632+ objectName: action.objectName + "_item"
2633+ visible: action.enabled
2634+ showDivider: false
2635+
2636+ height: units.gu(5)
2637+
2638+ Label {
2639+ anchors {
2640+ left: parent.left
2641+ leftMargin: units.gu(2)
2642+ right: parent.right
2643+ rightMargin: units.gu(2)
2644+ verticalCenter: parent.verticalCenter
2645+ }
2646+ fontSize: "small"
2647+ text: action.text
2648+ }
2649+
2650+ ListItems.ThinDivider {
2651+ visible: index < internal.lastEnabledActionIndex
2652+ anchors {
2653+ left: parent.left
2654+ leftMargin: units.gu(2)
2655+ right: parent.right
2656+ rightMargin: units.gu(2)
2657+ bottom: parent.bottom
2658+ }
2659+ }
2660+
2661+ onTriggered: contextMenu.hide()
2662+ }
2663+ }
2664+ }
2665+
2666+ Item {
2667+ id: positioner
2668+ visible: false
2669+ parent: contextMenu.associatedWebview
2670+ x: contextModel.position.x
2671+ y: contextModel.position.y + internal.locationBarOffset
2672+ }
2673+ caller: positioner
2674+
2675+ onVisibleChanged: {
2676+ if (!visible) {
2677+ contextModel.close()
2678+ }
2679+ }
2680+
2681+ // Override default implementation to prevent context menu from stealing
2682+ // active focus when shown (https://launchpad.net/bugs/1526884).
2683+ function show() {
2684+ visible = true
2685+ __foreground.show()
2686+ }
2687+
2688+ Binding {
2689+ // Ensure the context menu doesn’t steal focus from
2690+ // the webview when one of its actions is activated
2691+ // (https://launchpad.net/bugs/1526884).
2692+ target: __foreground
2693+ property: "activeFocusOnPress"
2694+ value: false
2695+ }
2696+}
2697
2698=== renamed file 'webapp-googleplus/lib/ErrorSheet.qml' => 'webapp-googleplus/lib/webcontainer/ErrorSheet.qml'
2699=== renamed file 'webapp-googleplus/lib/Favicon.qml' => 'webapp-googleplus/lib/webcontainer/Favicon.qml'
2700=== renamed file 'webapp-googleplus/lib/FilePickerDialog.qml' => 'webapp-googleplus/lib/webcontainer/FilePickerDialog.qml'
2701=== renamed file 'webapp-googleplus/lib/GeolocationPermissionRequest.qml' => 'webapp-googleplus/lib/webcontainer/GeolocationPermissionRequest.qml'
2702=== renamed file 'webapp-googleplus/lib/InvalidCertificateErrorSheet.qml' => 'webapp-googleplus/lib/webcontainer/InvalidCertificateErrorSheet.qml'
2703=== renamed file 'webapp-googleplus/lib/KeyboardRectangle.qml' => 'webapp-googleplus/lib/webcontainer/KeyboardRectangle.qml'
2704=== added file 'webapp-googleplus/lib/webcontainer/OnlineAccountsController.qml'
2705--- webapp-googleplus/lib/webcontainer/OnlineAccountsController.qml 1970-01-01 00:00:00 +0000
2706+++ webapp-googleplus/lib/webcontainer/OnlineAccountsController.qml 2016-12-02 07:06:20 +0000
2707@@ -0,0 +1,66 @@
2708+/*
2709+ * Copyright 2015 Canonical Ltd.
2710+ *
2711+ * This file is part of webbrowser-app.
2712+ *
2713+ * webbrowser-app is free software; you can redistribute it and/or modify
2714+ * it under the terms of the GNU General Public License as published by
2715+ * the Free Software Foundation; version 3.
2716+ *
2717+ * webbrowser-app is distributed in the hope that it will be useful,
2718+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2719+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2720+ * GNU General Public License for more details.
2721+ *
2722+ * You should have received a copy of the GNU General Public License
2723+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2724+ */
2725+
2726+import QtQuick 2.4
2727+
2728+Loader {
2729+ id: root
2730+
2731+ property string providerId: ""
2732+ property string applicationId: ""
2733+ property bool accountSwitcher: false
2734+ property string webappName: ""
2735+ property url webappIcon
2736+
2737+ signal accountSelected(string accountDataLocation, bool willMoveCookies)
2738+ signal contextReady()
2739+ signal quitRequested()
2740+
2741+ function setupWebcontextForAccount(webcontext) {
2742+ if (item) {
2743+ item.setupWebcontextForAccount(webcontext)
2744+ } else {
2745+ root.contextReady()
2746+ }
2747+ }
2748+
2749+ function showAccountSwitcher() {
2750+ if (item) item.showAccountSwitcher()
2751+ }
2752+
2753+ Component.onCompleted: {
2754+ if (providerId.length === 0) {
2755+ accountSelected("", false)
2756+ } else {
2757+ setSource("AccountsPage.qml", {
2758+ "providerId": providerId,
2759+ "applicationId": applicationId,
2760+ "accountSwitcher": accountSwitcher,
2761+ "webappName": webappName,
2762+ "webappIcon": webappIcon,
2763+ })
2764+ }
2765+ }
2766+
2767+ Connections {
2768+ target: item
2769+ onAccountSelected: root.accountSelected(accountDataLocation, willMoveCookies)
2770+ onContextReady: root.contextReady()
2771+ onQuitRequested: root.quitRequested()
2772+ }
2773+}
2774
2775=== renamed file 'webapp-googleplus/lib/PermissionRequest.qml' => 'webapp-googleplus/lib/webcontainer/PermissionRequest.qml'
2776=== added file 'webapp-googleplus/lib/webcontainer/PopupWindowController.qml'
2777--- webapp-googleplus/lib/webcontainer/PopupWindowController.qml 1970-01-01 00:00:00 +0000
2778+++ webapp-googleplus/lib/webcontainer/PopupWindowController.qml 2016-12-02 07:06:20 +0000
2779@@ -0,0 +1,266 @@
2780+/*
2781+ * Copyright 2014-2016 Canonical Ltd.
2782+ *
2783+ * This file is part of webbrowser-app.
2784+ *
2785+ * webbrowser-app is free software; you can redistribute it and/or modify
2786+ * it under the terms of the GNU General Public License as published by
2787+ * the Free Software Foundation; version 3.
2788+ *
2789+ * webbrowser-app is distributed in the hope that it will be useful,
2790+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2791+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2792+ * GNU General Public License for more details.
2793+ *
2794+ * You should have received a copy of the GNU General Public License
2795+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2796+ */
2797+
2798+import QtQuick 2.4
2799+import com.canonical.Oxide 1.0 as Oxide
2800+import Ubuntu.Components 1.3
2801+import Ubuntu.Components.Popups 1.3
2802+import Qt.labs.settings 1.0
2803+
2804+Item {
2805+ id: controller
2806+
2807+ property var webappUrlPatterns
2808+ property var mainWebappView
2809+ property var views: []
2810+ property bool blockOpenExternalUrls: false
2811+ property var mediaAccessDialogComponent
2812+ property bool wide: false
2813+
2814+ // Used to access runtime behavior during tests
2815+ signal openExternalUrlTriggered(string url)
2816+ signal newViewCreated(string url)
2817+ signal windowOverlayOpenAnimationDone()
2818+
2819+ signal initializeOverlayViewsWithUrls(var urls)
2820+
2821+ readonly property int maxSimultaneousViews: 3
2822+
2823+ Settings {
2824+ id: webviewOverlayUrlsSettings
2825+ property string overlayUrls
2826+ }
2827+
2828+ QtObject {
2829+ id: internal
2830+ property var urlPerOverlayView
2831+ }
2832+
2833+ function updateOverlayUrlsSettings() {
2834+ var urls = []
2835+ webviewOverlayUrlsSettings.overlayUrls = "[]"
2836+ for (var i in internal.urlPerOverlayView) {
2837+ urls.push(internal.urlPerOverlayView[i].toString())
2838+ }
2839+ webviewOverlayUrlsSettings.overlayUrls = JSON.stringify(urls)
2840+ }
2841+ function onUrlUpdatedForOverlay(overlayView, url) {
2842+ if (!internal.urlPerOverlayView) {
2843+ internal.urlPerOverlayView = {}
2844+ }
2845+
2846+ internal.urlPerOverlayView[overlayView] = url
2847+
2848+ updateOverlayUrlsSettings()
2849+ }
2850+
2851+ Connections {
2852+ target: Qt.application
2853+ onAboutToQuit: {
2854+ webviewOverlayUrlsSettings.overlayUrls = "[]"
2855+ }
2856+ }
2857+
2858+ Component.onCompleted: {
2859+ if (webviewOverlayUrlsSettings.overlayUrls
2860+ && webviewOverlayUrlsSettings.overlayUrls.length > 0) {
2861+ try {
2862+ var urls = JSON.parse(webviewOverlayUrlsSettings.overlayUrls)
2863+ if (typeof(urls) === 'object'
2864+ && urls.length != undefined
2865+ && urls.length > 0) {
2866+ initializeOverlayViewsWithUrls(urls)
2867+ }
2868+ } catch (e) {}
2869+ }
2870+ }
2871+
2872+ function openUrlExternally(url) {
2873+ if (!blockOpenExternalUrls) {
2874+ Qt.openUrlExternally(url)
2875+ }
2876+ openExternalUrlTriggered(url)
2877+ }
2878+
2879+ function onOverlayMoved(popup, diffY) {
2880+ if ((popup.y + diffY) > 0) {
2881+ popup.y += diffY
2882+ }
2883+ }
2884+ function handleNewViewAdded(view) {
2885+ if (views.length !== 0) {
2886+ var topView = views[views.length-1]
2887+ }
2888+ views.push(view)
2889+
2890+ view.webviewUrlChanged.connect(function(webviewUrl) {
2891+ onUrlUpdatedForOverlay(view, webviewUrl)
2892+ })
2893+ }
2894+ function handleOpenInUrlBrowserForView(url, view) {
2895+ handleViewRemoved(view)
2896+ openExternalUrlTriggered(url)
2897+ openUrlExternally(url)
2898+ }
2899+ function createViewSlidingHandlerFor(newView, viewBelow) {
2900+ var parentHeight = viewBelow.parent.height
2901+ return function() {
2902+ if (viewBelow && newView) {
2903+ viewBelow.opacity =
2904+ newView.y / parentHeight
2905+ }
2906+ }
2907+ }
2908+ function topViewOnStack() {
2909+ if (views.length !== 0) {
2910+ return views[views.length-1]
2911+ }
2912+ return mainWebappView
2913+ }
2914+ function handleViewRemoved(view) {
2915+ if (views.length === 0) {
2916+ return
2917+ }
2918+
2919+ var topMostView = views[views.length-1]
2920+ if (topMostView !== view) {
2921+ return
2922+ }
2923+ views.pop()
2924+ if (internal.urlPerOverlayView) {
2925+ delete internal.urlPerOverlayView[topMostView]
2926+ updateOverlayUrlsSettings()
2927+ }
2928+
2929+ var parentHeight = topMostView.parent.height
2930+ var nextView = topViewOnStack()
2931+ nextView.visible = true
2932+
2933+ function onViewSlidingOut() {
2934+ if (topMostView.y >= (topMostView.parent.height - 10)) {
2935+ topMostView.yChanged.disconnect(onViewSlidingOut)
2936+ topMostView.destroy()
2937+
2938+ updateViewVisibility(nextView, true)
2939+ }
2940+ }
2941+ topMostView.yChanged.connect(onViewSlidingOut)
2942+ topMostView.y = topMostView.parent.height
2943+ }
2944+ function updateViewVisibility(view, visible) {
2945+ if (view) {
2946+ view.opacity = visible ? 1.0 : 0.0
2947+ }
2948+ }
2949+ function createPopupView(parentView, params, isRequestFromMainWebappWebview, context) {
2950+ var view = popupWebOverlayFactory.createObject(
2951+ parentView,
2952+ params);
2953+
2954+ var topMostView = topViewOnStack()
2955+
2956+ // handle opacity updates of the view below this one
2957+ // when the view is sliding
2958+ view.yChanged.connect(
2959+ createViewSlidingHandlerFor(view, topMostView))
2960+
2961+ function onViewSlidingIn() {
2962+ var parentHeight = view.parent.height
2963+
2964+ if (view.y <= 10) {
2965+ view.yChanged.disconnect(onViewSlidingIn)
2966+
2967+ updateViewVisibility(topMostView, false)
2968+ }
2969+ }
2970+ view.yChanged.connect(onViewSlidingIn)
2971+
2972+ view.y = 0
2973+ handleNewViewAdded(view)
2974+ newViewCreated(view.url)
2975+ }
2976+ function createPopupViewForRequest(parentView, request, isRequestFromMainWebappWebview, context) {
2977+ createPopupView(parentView,
2978+ { request: request,
2979+ webContext: context,
2980+ popupWindowController: controller,
2981+ mediaAccessDialogComponent: mediaAccessDialogComponent
2982+ },
2983+ isRequestFromMainWebappWebview,
2984+ context)
2985+ }
2986+ function createPopupViewForUrl(parentView,
2987+ overlayUrl,
2988+ isRequestFromMainWebappWebview,
2989+ context) {
2990+ createPopupView(parentView,
2991+ { url: overlayUrl,
2992+ webContext: context,
2993+ popupWindowController: controller,
2994+ mediaAccessDialogComponent: mediaAccessDialogComponent
2995+ },
2996+ isRequestFromMainWebappWebview,
2997+ context)
2998+ }
2999+
3000+ Component {
3001+ id: popupWebOverlayFactory
3002+ PopupWindowOverlay {
3003+ id: overlay
3004+
3005+ height: parent.height
3006+ width: parent.width
3007+
3008+ wide: controller.wide
3009+
3010+ y: overlay.parent.height
3011+
3012+ // Poor mans heuristic to know when an overlay has been
3013+ // loaded and is in full view. We cannot rely on the
3014+ // NumberAnimation running/started since they dont
3015+ // work properly when inside a Behavior
3016+ onYChanged: {
3017+ if (y === 0) {
3018+ windowOverlayOpenAnimationDone()
3019+ }
3020+ }
3021+
3022+ Behavior on y {
3023+ NumberAnimation {
3024+ duration: 500
3025+ easing.type: Easing.InOutQuad
3026+ }
3027+ }
3028+ }
3029+ }
3030+
3031+ function handleNewForegroundNavigationRequest(
3032+ url, request, isRequestFromMainWebappWebview) {
3033+
3034+ if (views.length >= maxSimultaneousViews) {
3035+ request.action = Oxide.NavigationRequest.ActionReject
3036+ // Default to open externally, maybe should present a dialog
3037+ openUrlExternally(url.toString())
3038+ console.log("Maximum number of popup overlay opened, opening: "
3039+ + url
3040+ + " in the browser")
3041+ return false
3042+ }
3043+ return true
3044+ }
3045+}
3046
3047=== added file 'webapp-googleplus/lib/webcontainer/PopupWindowOverlay.qml'
3048--- webapp-googleplus/lib/webcontainer/PopupWindowOverlay.qml 1970-01-01 00:00:00 +0000
3049+++ webapp-googleplus/lib/webcontainer/PopupWindowOverlay.qml 2016-12-02 07:06:20 +0000
3050@@ -0,0 +1,248 @@
3051+/*
3052+ * Copyright 2014-2016 Canonical Ltd.
3053+ *
3054+ * This file is part of webbrowser-app.
3055+ *
3056+ * webbrowser-app is free software; you can redistribute it and/or modify
3057+ * it under the terms of the GNU General Public License as published by
3058+ * the Free Software Foundation; version 3.
3059+ *
3060+ * webbrowser-app is distributed in the hope that it will be useful,
3061+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3062+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3063+ * GNU General Public License for more details.
3064+ *
3065+ * You should have received a copy of the GNU General Public License
3066+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3067+ */
3068+
3069+import QtQuick 2.4
3070+import QtQuick.Window 2.2
3071+import com.canonical.Oxide 1.4 as Oxide
3072+import Ubuntu.Components 1.3
3073+import Ubuntu.Components.Popups 1.3
3074+import ".."
3075+
3076+FocusScope {
3077+ id: popup
3078+
3079+ property var popupWindowController
3080+ property var webContext
3081+ property alias currentWebview: popupWebview
3082+ property alias request: popupWebview.request
3083+ property alias url: popupWebview.url
3084+ property var mediaAccessDialogComponent
3085+ property alias wide: popupWebview.wide
3086+
3087+ signal webviewUrlChanged(url webviewUrl)
3088+
3089+ focus: true
3090+
3091+ Rectangle {
3092+ color: "#F2F1F0"
3093+ anchors.fill: parent
3094+ }
3095+
3096+ Item {
3097+ id: menubar
3098+
3099+ height: units.gu(6)
3100+ width: parent.width
3101+
3102+ anchors {
3103+ top: parent.top
3104+ horizontalCenter: parent.horizontalCenter
3105+ }
3106+
3107+ ChromeButton {
3108+ id: closeButton
3109+ objectName: "overlayCloseButton"
3110+ anchors {
3111+ left: parent.left
3112+ verticalCenter: parent.verticalCenter
3113+ }
3114+
3115+ height: parent.height
3116+ width: height
3117+
3118+ iconName: "dropdown-menu"
3119+ iconSize: 0.6 * height
3120+
3121+ enabled: true
3122+ visible: true
3123+
3124+ MouseArea {
3125+ anchors.fill: parent
3126+ onClicked: {
3127+ if (popupWindowController) {
3128+ popupWindowController.handleViewRemoved(popup)
3129+ }
3130+ }
3131+ }
3132+ }
3133+
3134+ Item {
3135+ anchors {
3136+ top: parent.top
3137+ bottom: parent.bottom
3138+ left: closeButton.right
3139+ right: buttonOpenInBrowser.left
3140+ }
3141+
3142+ Label {
3143+ anchors {
3144+ rightMargin: units.gu(2)
3145+ verticalCenter: parent.verticalCenter
3146+ left: parent.left
3147+ right: parent.right
3148+ }
3149+
3150+ text: popupWebview.title ? popupWebview.title : popupWebview.url
3151+ elide: Text.ElideRight
3152+ }
3153+
3154+ MouseArea {
3155+ anchors.fill: parent
3156+
3157+ property int initMouseY: 0
3158+ property int prevMouseY: 0
3159+
3160+ onPressed: {
3161+ initMouseY = mouse.y
3162+ prevMouseY = initMouseY
3163+ }
3164+ onReleased: {
3165+ if ((prevMouseY - initMouseY) > (popup.height / 8) ||
3166+ popup.y > popup.height/2) {
3167+ if (popupWindowController) {
3168+ popupWindowController.handleViewRemoved(popup)
3169+ return
3170+ }
3171+ }
3172+ popup.y = 0
3173+ }
3174+ onMouseYChanged: {
3175+ if (popupWindowController) {
3176+ var diff = mouseY - initMouseY
3177+ prevMouseY = mouseY
3178+ popupWindowController.onOverlayMoved(popup, diff)
3179+ }
3180+ }
3181+ }
3182+ }
3183+
3184+ ChromeButton {
3185+ id: buttonOpenInBrowser
3186+ objectName: "overlayButtonOpenInBrowser"
3187+ anchors {
3188+ right: parent.right
3189+ verticalCenter: parent.verticalCenter
3190+ rightMargin: units.gu(1)
3191+ }
3192+
3193+ height: parent.height
3194+ width: height
3195+
3196+ iconName: "external-link"
3197+ iconSize: 0.6 * height
3198+
3199+ enabled: true
3200+ visible: true
3201+
3202+ MouseArea {
3203+ anchors.fill: parent
3204+ onClicked: {
3205+ if (popupWindowController) {
3206+ popupWindowController.handleOpenInUrlBrowserForView(
3207+ popupWebview.url, popup)
3208+ }
3209+ }
3210+ }
3211+ }
3212+ }
3213+
3214+ WebappWebview {
3215+ id: popupWebview
3216+
3217+ objectName: "overlayWebview"
3218+
3219+ context: webContext
3220+
3221+ onUrlChanged: webviewUrlChanged(popupWebview.url)
3222+
3223+ focus: true
3224+
3225+ Connections {
3226+ target: popupWebview.visible ? popupWebview : null
3227+
3228+ /**
3229+ * We are only connecting to the mediaAccessPermission signal if we are the currently
3230+ * visible overlay. If other overlays slide over this one, oxide will deny (by default)
3231+ * all media access requests for this overlay.
3232+ *
3233+ * See the browser's webbrowser/Browser.qml source for additional comments.
3234+ */
3235+ onMediaAccessPermissionRequested: PopupUtils.open(mediaAccessDialogComponent, null, { request: request })
3236+ }
3237+
3238+ onOpenUrlExternallyRequested: {
3239+ if (popupWindowController) {
3240+ popupWindowController.openUrlExternally(url)
3241+ }
3242+ }
3243+
3244+ anchors {
3245+ bottom: parent.bottom
3246+ left: parent.left
3247+ right: parent.right
3248+ top: menubar.bottom
3249+ }
3250+
3251+ onNewViewRequested: {
3252+ if (popupWindowController) {
3253+ popupWindowController.createPopupViewForRequest(
3254+ popup.parent, request, false, context)
3255+ }
3256+ }
3257+
3258+ function isNewForegroundWebViewDisposition(disposition) {
3259+ return disposition === Oxide.NavigationRequest.DispositionNewPopup ||
3260+ disposition === Oxide.NavigationRequest.DispositionNewForegroundTab;
3261+ }
3262+
3263+ onNavigationRequested: {
3264+ var url = request.url.toString()
3265+ request.action = Oxide.NavigationRequest.ActionAccept
3266+ if (isNewForegroundWebViewDisposition(request.disposition)) {
3267+ var shouldAcceptRequest =
3268+ popupWindowController.handleNewForegroundNavigationRequest(
3269+ url, request, false);
3270+ if (!shouldAcceptRequest) {
3271+ request.action = Oxide.NavigationRequest.ActionReject
3272+ }
3273+ }
3274+ }
3275+
3276+ onCloseRequested: {
3277+ if (popupWindowController) {
3278+ popupWindowController.handleViewRemoved(popup)
3279+ }
3280+ }
3281+
3282+ Loader {
3283+ anchors {
3284+ fill: popupWebview
3285+ }
3286+ active: webProcessMonitor.crashed || (webProcessMonitor.killed && !popupWebview.currentWebview.loading)
3287+ sourceComponent: SadPage {
3288+ webview: popupWebview
3289+ objectName: "overlaySadPage"
3290+ }
3291+ WebProcessMonitor {
3292+ id: webProcessMonitor
3293+ webview: popupWebview
3294+ }
3295+ asynchronous: true
3296+ }
3297+ }
3298+}
3299
3300=== renamed file 'webapp-googleplus/lib/ProxyAuthenticationDialog.qml' => 'webapp-googleplus/lib/webcontainer/ProxyAuthenticationDialog.qml'
3301=== added file 'webapp-googleplus/lib/webcontainer/SadPage.qml'
3302--- webapp-googleplus/lib/webcontainer/SadPage.qml 1970-01-01 00:00:00 +0000
3303+++ webapp-googleplus/lib/webcontainer/SadPage.qml 2016-12-02 07:06:20 +0000
3304@@ -0,0 +1,56 @@
3305+/*
3306+ * Copyright 2015-2016 Canonical Ltd.
3307+ *
3308+ * This file is part of webbrowser-app.
3309+ *
3310+ * webbrowser-app is free software; you can redistribute it and/or modify
3311+ * it under the terms of the GNU General Public License as published by
3312+ * the Free Software Foundation; version 3.
3313+ *
3314+ * webbrowser-app is distributed in the hope that it will be useful,
3315+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3316+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3317+ * GNU General Public License for more details.
3318+ *
3319+ * You should have received a copy of the GNU General Public License
3320+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3321+ */
3322+
3323+import QtQuick 2.4
3324+import Ubuntu.Components 1.3
3325+
3326+Rectangle {
3327+ property var webview
3328+
3329+ Column {
3330+ anchors {
3331+ fill: parent
3332+ margins: units.gu(4)
3333+ }
3334+ spacing: units.gu(4)
3335+
3336+ Image {
3337+ anchors.horizontalCenter: parent.horizontalCenter
3338+ source: "assets/tab-error.png"
3339+ }
3340+
3341+ Label {
3342+ anchors {
3343+ left: parent.left
3344+ right: parent.right
3345+ }
3346+
3347+ wrapMode: Text.Wrap
3348+ horizontalAlignment: Text.AlignHCenter
3349+ text: webview ? i18n.tr("Oops, something went wrong.") : ""
3350+ }
3351+
3352+ Button {
3353+ anchors.horizontalCenter: parent.horizontalCenter
3354+ objectName: "reloadButton"
3355+ text: i18n.tr("Reload")
3356+ color: theme.palette.normal.positive
3357+ onClicked: webview.reload()
3358+ }
3359+ }
3360+}
3361
3362=== renamed file 'webapp-googleplus/lib/ScrollTracker.qml' => 'webapp-googleplus/lib/webcontainer/ScrollTracker.qml'
3363=== renamed file 'webapp-googleplus/lib/Share.qml' => 'webapp-googleplus/lib/webcontainer/Share.qml'
3364=== added file 'webapp-googleplus/lib/webcontainer/SplashScreen.qml'
3365--- webapp-googleplus/lib/webcontainer/SplashScreen.qml 1970-01-01 00:00:00 +0000
3366+++ webapp-googleplus/lib/webcontainer/SplashScreen.qml 2016-12-02 07:06:20 +0000
3367@@ -0,0 +1,65 @@
3368+/*
3369+ * Copyright 2015 Canonical Ltd.
3370+ *
3371+ * This file is part of webbrowser-app.
3372+ *
3373+ * webbrowser-app is free software; you can redistribute it and/or modify
3374+ * it under the terms of the GNU General Public License as published by
3375+ * the Free Software Foundation; version 3.
3376+ *
3377+ * webbrowser-app is distributed in the hope that it will be useful,
3378+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3379+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3380+ * GNU General Public License for more details.
3381+ *
3382+ * You should have received a copy of the GNU General Public License
3383+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3384+ */
3385+
3386+import QtQuick 2.4
3387+import Ubuntu.Components 1.3
3388+import Ubuntu.OnlineAccounts 0.1
3389+
3390+Rectangle {
3391+ id: root
3392+
3393+ property string applicationName
3394+ property alias iconSource: icon.source
3395+ default property alias contents: contentsHolder.data
3396+
3397+ anchors.fill: parent
3398+
3399+ Flickable {
3400+ anchors.fill: parent
3401+ contentHeight: Math.max(contentItem.childrenRect.height, height)
3402+
3403+ Column {
3404+ anchors {
3405+ left: parent.left
3406+ right: parent.right
3407+ verticalCenter: parent.verticalCenter
3408+ }
3409+ spacing: units.gu(2)
3410+
3411+ Icon {
3412+ id: icon
3413+ anchors.horizontalCenter: parent.horizontalCenter
3414+ width: units.gu(10)
3415+ height: width
3416+ }
3417+
3418+ Label {
3419+ anchors.horizontalCenter: parent.horizontalCenter
3420+ fontSize: "x-large"
3421+ text: root.applicationName
3422+ }
3423+
3424+ Item {
3425+ id: contentsHolder
3426+ anchors.left: parent.left
3427+ anchors.right: parent.right
3428+ height: childrenRect.height
3429+ }
3430+ }
3431+ }
3432+}
3433
3434=== renamed file 'webapp-googleplus/lib/ThinProgressBar.qml' => 'webapp-googleplus/lib/webcontainer/ThinProgressBar.qml'
3435=== added file 'webapp-googleplus/lib/webcontainer/WebApp.qml'
3436--- webapp-googleplus/lib/webcontainer/WebApp.qml 1970-01-01 00:00:00 +0000
3437+++ webapp-googleplus/lib/webcontainer/WebApp.qml 2016-12-02 07:06:20 +0000
3438@@ -0,0 +1,323 @@
3439+/*
3440+ * Copyright 2013-2016 Canonical Ltd.
3441+ *
3442+ * This file is part of webbrowser-app.
3443+ *
3444+ * webbrowser-app is free software; you can redistribute it and/or modify
3445+ * it under the terms of the GNU General Public License as published by
3446+ * the Free Software Foundation; version 3.
3447+ *
3448+ * webbrowser-app is distributed in the hope that it will be useful,
3449+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3450+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3451+ * GNU General Public License for more details.
3452+ *
3453+ * You should have received a copy of the GNU General Public License
3454+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3455+ */
3456+
3457+import QtQuick 2.4
3458+import webbrowsercommon.private 0.1
3459+import com.canonical.Oxide 1.5 as Oxide
3460+import Ubuntu.Components 1.3
3461+import Ubuntu.Unity.Action 1.1 as UnityActions
3462+import Ubuntu.UnityWebApps 0.1 as UnityWebApps
3463+import Qt.labs.settings 1.0
3464+import "../actions" as Actions
3465+import ".."
3466+import "ColorUtils.js" as ColorUtils
3467+
3468+BrowserView {
3469+ id: webapp
3470+ objectName: "webappBrowserView"
3471+
3472+ currentWebview: containerWebView.currentWebview
3473+
3474+ property alias window: containerWebView.window
3475+
3476+ property alias url: containerWebView.url
3477+
3478+ property bool accountSwitcher
3479+
3480+ property string webappModelSearchPath: ""
3481+
3482+ property var webappUrlPatterns
3483+ property alias popupRedirectionUrlPrefixPattern: containerWebView.popupRedirectionUrlPrefixPattern
3484+ property alias webviewOverrideFile: containerWebView.webviewOverrideFile
3485+ property alias blockOpenExternalUrls: containerWebView.blockOpenExternalUrls
3486+ property alias localUserAgentOverride: containerWebView.localUserAgentOverride
3487+ property alias dataPath: containerWebView.dataPath
3488+ property alias runningLocalApplication: containerWebView.runningLocalApplication
3489+ property alias openExternalUrlInOverlay: containerWebView.openExternalUrlInOverlay
3490+ property alias popupBlockerEnabled: containerWebView.popupBlockerEnabled
3491+
3492+ property string webappName: ""
3493+
3494+ property bool backForwardButtonsVisible: false
3495+ property bool chromeVisible: false
3496+ readonly property bool chromeless: !chromeVisible && !backForwardButtonsVisible && !accountSwitcher
3497+ readonly property real themeColorTextContrastFactor: 3.0
3498+
3499+ signal chooseAccount()
3500+
3501+ // Used for testing. There is a bug that currently prevents non visual Qt objects
3502+ // to be introspectable from AP which makes directly accessing the settings object
3503+ // not possible https://bugs.launchpad.net/autopilot-qt/+bug/1273956
3504+ property alias generatedUrlPatterns: urlPatternSettings.generatedUrlPatterns
3505+
3506+ currentWebcontext: currentWebview ? currentWebview.context : null
3507+
3508+ actions: [
3509+ Actions.Back {
3510+ enabled: webapp.backForwardButtonsVisible && containerWebView.currentWebview && containerWebView.currentWebview.canGoBack
3511+ onTriggered: containerWebView.currentWebview.goBack()
3512+ },
3513+ Actions.Forward {
3514+ enabled: webapp.backForwardButtonsVisible && containerWebView.currentWebview && containerWebView.currentWebview.canGoForward
3515+ onTriggered: containerWebView.currentWebview.goForward()
3516+ },
3517+ Actions.Reload {
3518+ onTriggered: containerWebView.currentWebview.reload()
3519+ }
3520+ ]
3521+
3522+ focus: true
3523+
3524+ Settings {
3525+ id: urlPatternSettings
3526+ property string generatedUrlPatterns
3527+ }
3528+
3529+ function addGeneratedUrlPattern(urlPattern) {
3530+ if (urlPattern.trim().length === 0) {
3531+ return;
3532+ }
3533+
3534+ var patterns = []
3535+ if (urlPatternSettings.generatedUrlPatterns
3536+ && urlPatternSettings.generatedUrlPatterns.trim().length !== 0) {
3537+ try {
3538+ patterns = JSON.parse(urlPatternSettings.generatedUrlPatterns)
3539+ } catch(e) {
3540+ console.error("Invalid JSON content found in url patterns file")
3541+ }
3542+ if (! (patterns instanceof Array)) {
3543+ console.error("Invalid JSON content type found in url patterns file (not an array)")
3544+ patterns = []
3545+ }
3546+ }
3547+ if (patterns.indexOf(urlPattern) < 0) {
3548+ patterns.push(urlPattern)
3549+
3550+ urlPatternSettings.generatedUrlPatterns = JSON.stringify(patterns)
3551+ }
3552+ }
3553+
3554+ function mergeUrlPatternSets(p1, p2) {
3555+ if ( ! (p1 instanceof Array)) {
3556+ return (p2 instanceof Array) ? p2 : []
3557+ }
3558+ if ( ! (p2 instanceof Array)) {
3559+ return (p1 instanceof Array) ? p1 : []
3560+ }
3561+ var p1hash = {}
3562+ var result = []
3563+ for (var i1 in p1) {
3564+ p1hash[p1[i1]] = 1
3565+ result.push(p1[i1])
3566+ }
3567+ for (var i2 in p2) {
3568+ if (! (p2[i2] in p1hash)) {
3569+ result.push(p2[i2])
3570+ }
3571+ }
3572+ return result
3573+ }
3574+
3575+ Item {
3576+ id: webviewContainer
3577+ anchors.fill: parent
3578+
3579+ WebappContainerWebview {
3580+ id: containerWebView
3581+ objectName: "webview"
3582+
3583+ wide: webapp.wide
3584+ anchors {
3585+ left: parent.left
3586+ right: parent.right
3587+ top: parent.top
3588+ }
3589+ height: parent.height - osk.height
3590+ developerExtrasEnabled: webapp.developerExtrasEnabled
3591+
3592+ focus: true
3593+
3594+ onThemeColorMetaInformationDetected: {
3595+ var color = webappContainerHelper.rgbColorFromCSSColor(theme_color)
3596+ if (!webapp.chromeless && chromeLoader.item && color.length) {
3597+ chromeLoader.item.backgroundColor = theme_color
3598+ chromeLoader.item.updateChromeElementsColor(
3599+ ColorUtils.getMostConstrastedColor(
3600+ color,
3601+ Qt.darker(theme_color, themeColorTextContrastFactor),
3602+ Qt.lighter(theme_color, themeColorTextContrastFactor))
3603+ )
3604+ }
3605+ }
3606+ onSamlRequestUrlPatternReceived: {
3607+ addGeneratedUrlPattern(urlPattern)
3608+ }
3609+ webappUrlPatterns: mergeUrlPatternSets(urlPatternSettings.generatedUrlPatterns,
3610+ webapp.webappUrlPatterns)
3611+
3612+ /**
3613+ * Use the --webapp parameter value w/ precedence, but also take into account
3614+ * the fact that a webapp 'name' can come from a webapp-properties.json file w/o
3615+ * being explictly defined here.
3616+ */
3617+ webappName: webapp.webappName === "" ? unityWebapps.name : webapp.webappName
3618+
3619+ Loader {
3620+ anchors {
3621+ fill: containerWebView
3622+ topMargin: (!webapp.chromeless && chromeLoader.item.state == "shown")
3623+ ? chromeLoader.item.height
3624+ : 0
3625+ }
3626+ active: containerWebView.currentWebview &&
3627+ (webProcessMonitor.crashed || (webProcessMonitor.killed && !containerWebView.currentWebview.loading))
3628+ sourceComponent: SadPage {
3629+ webview: containerWebView.currentWebview
3630+ objectName: "mainWebviewSadPage"
3631+ }
3632+ WebProcessMonitor {
3633+ id: webProcessMonitor
3634+ webview: containerWebView.currentWebview
3635+ }
3636+ asynchronous: true
3637+ }
3638+ }
3639+
3640+ Loader {
3641+ anchors {
3642+ fill: containerWebView
3643+ topMargin: (!webapp.chromeless && chromeLoader.item.state == "shown") ? chromeLoader.item.height : 0
3644+ }
3645+ sourceComponent: ErrorSheet {
3646+ visible: containerWebView.currentWebview && containerWebView.currentWebview.lastLoadFailed
3647+ url: containerWebView.currentWebview ? containerWebView.currentWebview.url : ""
3648+ onRefreshClicked: {
3649+ if (containerWebView.currentWebview)
3650+ containerWebView.currentWebview.reload()
3651+ }
3652+ }
3653+ asynchronous: true
3654+ }
3655+
3656+ Loader {
3657+ id: chromeLoader
3658+
3659+ anchors {
3660+ top: parent.top
3661+ left: parent.left
3662+ right: parent.right
3663+ }
3664+
3665+ sourceComponent: webapp.chromeless ? progressbarComponent : chromeComponent
3666+
3667+ Component {
3668+ id: chromeComponent
3669+
3670+ Chrome {
3671+ webview: webapp.currentWebview
3672+ navigationButtonsVisible: webapp.backForwardButtonsVisible
3673+ accountSwitcher: webapp.accountSwitcher
3674+
3675+ anchors {
3676+ left: parent.left
3677+ right: parent.right
3678+ }
3679+ height: units.gu(6)
3680+ y: webapp.currentWebview ? containerWebView.currentWebview.locationBarController.offset : 0
3681+
3682+ onChooseAccount: webapp.chooseAccount()
3683+ }
3684+ }
3685+
3686+ Component {
3687+ id: progressbarComponent
3688+
3689+ ThinProgressBar {
3690+ visible: webapp.currentWebview && webapp.currentWebview.loading
3691+ value: visible ? webapp.currentWebview.loadProgress : 0
3692+
3693+ anchors {
3694+ left: parent.left
3695+ right: parent.right
3696+ top: parent.top
3697+ }
3698+ }
3699+ }
3700+ }
3701+
3702+ Binding {
3703+ when: webapp.currentWebview && !webapp.chromeless
3704+ target: webapp.currentWebview ? webapp.currentWebview.locationBarController : null
3705+ property: 'height'
3706+ value: webapp.currentWebview.visible ? chromeLoader.item.height : 0
3707+ }
3708+
3709+ ChromeController {
3710+ webview: webapp.currentWebview
3711+ forceHide: webapp.chromeless
3712+ defaultMode: webapp.hasTouchScreen
3713+ ? Oxide.LocationBarController.ModeAuto
3714+ : Oxide.LocationBarController.ModeShown
3715+ }
3716+ }
3717+
3718+ UnityWebApps.UnityWebApps {
3719+ id: unityWebapps
3720+ name: webappName
3721+ bindee: containerWebView.currentWebview
3722+ actionsContext: actionManager.globalContext
3723+ model: UnityWebApps.UnityWebappsAppModel { searchPath: webappModelSearchPath }
3724+ injectExtraUbuntuApis: runningLocalApplication
3725+ injectExtraContentShareCapabilities: !runningLocalApplication
3726+
3727+ Component.onCompleted: {
3728+ // Delay bind the property to add a bit of backward compatibility with
3729+ // other unity-webapps-qml modules
3730+ if (unityWebapps.embeddedUiComponentParent !== undefined) {
3731+ unityWebapps.embeddedUiComponentParent = webapp
3732+ }
3733+ }
3734+ }
3735+
3736+ // F5 or Ctrl+R: Reload current Tab
3737+ Shortcut {
3738+ sequence: "Ctrl+r"
3739+ enabled: currentWebview && currentWebview.visible
3740+ onActivated: currentWebview.reload()
3741+ }
3742+ Shortcut {
3743+ sequence: "F5"
3744+ enabled: currentWebview && currentWebview.visible
3745+ onActivated: currentWebview.reload()
3746+ }
3747+
3748+ // Alt+← or Backspace: Goes to the previous page
3749+ Shortcut {
3750+ sequence: StandardKey.Back
3751+ enabled: currentWebview && currentWebview.canGoBack
3752+ onActivated: currentWebview.goBack()
3753+ }
3754+
3755+ // Alt+→ or Shift+Backspace: Goes to the next page
3756+ Shortcut {
3757+ sequence: StandardKey.Forward
3758+ enabled: currentWebview && currentWebview.canGoForward
3759+ onActivated: currentWebview.goForward()
3760+ }
3761+}
3762
3763=== added file 'webapp-googleplus/lib/webcontainer/WebViewImplOxide.qml'
3764--- webapp-googleplus/lib/webcontainer/WebViewImplOxide.qml 1970-01-01 00:00:00 +0000
3765+++ webapp-googleplus/lib/webcontainer/WebViewImplOxide.qml 2016-12-02 07:06:20 +0000
3766@@ -0,0 +1,297 @@
3767+/*
3768+ * Copyright 2014-2016 Canonical Ltd.
3769+ *
3770+ * This file is part of webbrowser-app.
3771+ *
3772+ * webbrowser-app is free software; you can redistribute it and/or modify
3773+ * it under the terms of the GNU General Public License as published by
3774+ * the Free Software Foundation; version 3.
3775+ *
3776+ * webbrowser-app is distributed in the hope that it will be useful,
3777+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3778+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3779+ * GNU General Public License for more details.
3780+ *
3781+ * You should have received a copy of the GNU General Public License
3782+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3783+ */
3784+
3785+import QtQuick 2.4
3786+import QtQuick.Window 2.2
3787+import com.canonical.Oxide 1.8 as Oxide
3788+import Ubuntu.Components 1.3
3789+import Ubuntu.Components.Popups 1.3
3790+import Ubuntu.UnityWebApps 0.1 as UnityWebApps
3791+import Ubuntu.Web 0.2
3792+import ".."
3793+
3794+WebappWebview {
3795+ id: webview
3796+
3797+ // XXX: Ideally, we would use the Window.window
3798+ // attached property, but it is new in Qt 5.7.
3799+ property Window window
3800+
3801+ property bool developerExtrasEnabled: false
3802+ property string webappName: ""
3803+ property string localUserAgentOverride: ""
3804+ property var webappUrlPatterns: null
3805+ property string popupRedirectionUrlPrefixPattern: ""
3806+ property url dataPath
3807+ property var popupController
3808+ property var overlayViewsParent: webview.parent
3809+ property var mediaAccessDialogComponent
3810+ property bool openExternalUrlInOverlay: false
3811+ property bool popupBlockerEnabled: true
3812+
3813+ // Mostly used for testing & avoid external urls to
3814+ // "leak" in the default browser. External URLs corresponds
3815+ // to URLs that are not included in the set defined by the url patterns
3816+ // (if any) or navigations resulting in new windows being created.
3817+ property bool blockOpenExternalUrls: false
3818+
3819+ signal samlRequestUrlPatternReceived(string urlPattern)
3820+ signal themeColorMetaInformationDetected(string theme_color)
3821+
3822+ // Those signals are used for testing purposes to externally
3823+ // track down the various internal logic & steps of a popup lifecycle.
3824+ signal openExternalUrlTriggered(string url)
3825+ signal gotRedirectionUrl(string url)
3826+ property bool runningLocalApplication: false
3827+
3828+ onLoadEvent: {
3829+ var url = event.url.toString()
3830+ if (event.type === Oxide.LoadEvent.TypeRedirected
3831+ && url.indexOf("SAMLRequest") > 0) {
3832+ handleSamlRequestNavigation(url)
3833+ }
3834+ }
3835+
3836+ function openOverlayForUrl(overlayUrl) {
3837+ if (popupController) {
3838+ popupController.createPopupViewForUrl(
3839+ overlayViewsParent,
3840+ overlayUrl,
3841+ true,
3842+ context)
3843+ }
3844+ }
3845+
3846+ focus: true
3847+
3848+ currentWebview: webview
3849+
3850+ context: WebContext {
3851+ dataPath: webview.dataPath
3852+ userAgent: localUserAgentOverride ? localUserAgentOverride : defaultUserAgent
3853+
3854+ popupBlockerEnabled: webview.popupBlockerEnabled
3855+
3856+ userScripts: [
3857+ Oxide.UserScript {
3858+ context: "oxide://webapp-specific-page-metadata-collector/"
3859+ url: Qt.resolvedUrl("webapp-specific-page-metadata-collector.js")
3860+ incognitoEnabled: false
3861+ matchAllFrames: false
3862+ }
3863+ ]
3864+ }
3865+
3866+ Component.onCompleted: webappSpecificMessageHandler.createObject(
3867+ webview,
3868+ {
3869+ msgId: "webapp-specific-page-metadata-detected",
3870+ contexts: ["oxide://webapp-specific-page-metadata-collector/"],
3871+ callback: function(msg, frame) {
3872+ handlePageMetadata(msg.args)
3873+ }
3874+ });
3875+
3876+ Component {
3877+ id: webappSpecificMessageHandler
3878+ Oxide.ScriptMessageHandler { }
3879+ }
3880+
3881+ onOpenUrlExternallyRequested: openUrlExternally(url, false)
3882+
3883+ preferences.allowFileAccessFromFileUrls: runningLocalApplication
3884+ preferences.allowUniversalAccessFromFileUrls: runningLocalApplication
3885+ preferences.localStorageEnabled: true
3886+ preferences.appCacheEnabled: true
3887+
3888+ onNewViewRequested: popupController.createPopupViewForRequest(overlayViewsParent, request, true, context)
3889+
3890+ Connections {
3891+ target: webview.visible ? webview : null
3892+
3893+ /**
3894+ * We are only connecting to the mediaAccessPermission signal if we are
3895+ * the only webview currently visible (no overlay present). In the case of an overlay
3896+ * and the absence of a signal handler in this main view, oxide's default behavior
3897+ * is triggered and the request is denied.
3898+ *
3899+ * See the browser's webbrowser/Browser.qml source for additional comments.
3900+ */
3901+ onMediaAccessPermissionRequested: PopupUtils.open(mediaAccessDialogComponent, null, { request: request })
3902+ }
3903+
3904+ StateSaver.properties: "url"
3905+ StateSaver.enabled: !runningLocalApplication
3906+
3907+ function handleSAMLRequestPattern(urlPattern) {
3908+ webappUrlPatterns.push(urlPattern)
3909+
3910+ samlRequestUrlPatternReceived(urlPattern)
3911+ }
3912+
3913+ function isRunningAsANamedWebapp() {
3914+ return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0
3915+ }
3916+
3917+ function haveValidUrlPatterns() {
3918+ return webappUrlPatterns && webappUrlPatterns.length !== 0
3919+ }
3920+
3921+ function isNewForegroundWebViewDisposition(disposition) {
3922+ return disposition === Oxide.NavigationRequest.DispositionNewPopup ||
3923+ disposition === Oxide.NavigationRequest.DispositionNewForegroundTab;
3924+ }
3925+
3926+ function openUrlExternally(url, isTriggeredByUserNavigation) {
3927+ if (openExternalUrlInOverlay && isTriggeredByUserNavigation) {
3928+ popupController.createPopupViewForUrl(overlayViewsParent, url, true, context)
3929+ return
3930+ } else {
3931+ webview.openExternalUrlTriggered(url)
3932+ if (! webview.blockOpenExternalUrls) {
3933+ Qt.openUrlExternally(url)
3934+ }
3935+ }
3936+ }
3937+
3938+ function shouldAllowNavigationTo(url) {
3939+ // The list of url patterns defined by the webapp takes precedence over command line
3940+ if (isRunningAsANamedWebapp()) {
3941+ if (unityWebapps.model.exists(unityWebapps.name) &&
3942+ unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) {
3943+ return true;
3944+ }
3945+ }
3946+
3947+ // We still take the possible additional patterns specified in the command line
3948+ // (the in the case of finer grained ones specifically for the container and not
3949+ // as an 'install source' for the webapp).
3950+ if (haveValidUrlPatterns()) {
3951+ for (var i = 0; i < webappUrlPatterns.length; ++i) {
3952+ var pattern = webappUrlPatterns[i]
3953+ if (url.match(pattern)) {
3954+ return true;
3955+ }
3956+ }
3957+ }
3958+
3959+ return false;
3960+ }
3961+
3962+ function handleSamlRequestNavigation(url) {
3963+ var urlRegExp = new RegExp("https?://([^?/]+)")
3964+ var match = urlRegExp.exec(url)
3965+ var host = match[1]
3966+ var escapeDotsRegExp = new RegExp("\\.", "g")
3967+ var hostPattern = "https?://" + host.replace(escapeDotsRegExp, "\\.") + "/*"
3968+
3969+ console.log("SAML request detected. Adding host pattern: " + hostPattern)
3970+
3971+ handleSAMLRequestPattern(hostPattern)
3972+ }
3973+
3974+ function navigateToUrl(targetUrl) {
3975+ webview.forceActiveFocus()
3976+ webview.url = targetUrl
3977+ }
3978+
3979+ function navigationRequestedDelegate(request) {
3980+ var url = request.url.toString()
3981+ if (runningLocalApplication && url.indexOf("file://") !== 0) {
3982+ request.action = Oxide.NavigationRequest.ActionReject
3983+ openUrlExternally(url, true)
3984+ return
3985+ }
3986+
3987+ request.action = Oxide.NavigationRequest.ActionReject
3988+ if (isNewForegroundWebViewDisposition(request.disposition)) {
3989+ var shouldAcceptRequest =
3990+ popupController.handleNewForegroundNavigationRequest(
3991+ url, request, true);
3992+ if (shouldAcceptRequest) {
3993+ request.action = Oxide.NavigationRequest.ActionAccept
3994+ }
3995+ return
3996+ }
3997+
3998+ // Pass-through if we are not running as a named webapp (--webapp='Gmail')
3999+ // or if we dont have a list of url patterns specified to filter the
4000+ // browsing actions
4001+ if ( ! webview.haveValidUrlPatterns() && ! webview.isRunningAsANamedWebapp()) {
4002+ request.action = Oxide.NavigationRequest.ActionAccept
4003+ return
4004+ }
4005+
4006+ if (webview.shouldAllowNavigationTo(url))
4007+ request.action = Oxide.NavigationRequest.ActionAccept
4008+
4009+ // SAML requests are used for instance by Google Apps for your domain;
4010+ // they are implemented as a HTTP redirect to a URL containing the
4011+ // query parameter called "SAMLRequest".
4012+ // Besides letting the request through, we must also add the SAML
4013+ // domain to the list of the allowed hosts.
4014+ if (request.disposition === Oxide.NavigationRequest.DispositionCurrentTab
4015+ && url.indexOf("SAMLRequest") > 0) {
4016+ handleSamlRequestNavigation(url)
4017+ request.action = Oxide.NavigationRequest.ActionAccept
4018+ }
4019+
4020+ if (request.action === Oxide.NavigationRequest.ActionReject) {
4021+ console.debug('Opening: ' + url + ' in the browser window.')
4022+ openUrlExternally(url, true)
4023+ }
4024+ }
4025+
4026+ // Small shim needed when running as a webapp to wire-up connections
4027+ // with the webview (message received, etc…).
4028+ // This is being called (and expected) internally by the webapps
4029+ // component as a way to bind to a webview lookalike without
4030+ // reaching out directly to its internals (see it as an interface).
4031+ function getUnityWebappsProxies() {
4032+ var eventHandlers = {
4033+ onAppRaised: function () {
4034+ window.raise();
4035+ }
4036+ };
4037+ return UnityWebAppsUtils.makeProxiesForWebViewBindee(webview, eventHandlers)
4038+ }
4039+
4040+ function handlePageMetadata(metadata) {
4041+ if (metadata.type === 'manifest') {
4042+ var request = new XMLHttpRequest();
4043+ request.onreadystatechange = function() {
4044+ if (request.readyState === XMLHttpRequest.DONE) {
4045+ try {
4046+ var manifest = JSON.parse(request.responseText);
4047+ if (manifest['theme_color']
4048+ && manifest['theme_color'].length !== 0) {
4049+ themeColorMetaInformationDetected(manifest['theme_color'])
4050+ }
4051+ } catch(e) {}
4052+ }
4053+ }
4054+ request.open("GET", metadata.manifest);
4055+ request.send();
4056+ } else if (metadata.type === 'theme-color') {
4057+ if (metadata['theme_color']
4058+ && metadata['theme_color'].length !== 0) {
4059+ themeColorMetaInformationDetected(metadata['theme_color'])
4060+ }
4061+ }
4062+ }
4063+}
4064
4065=== added file 'webapp-googleplus/lib/webcontainer/WebappContainerWebview.qml'
4066--- webapp-googleplus/lib/webcontainer/WebappContainerWebview.qml 1970-01-01 00:00:00 +0000
4067+++ webapp-googleplus/lib/webcontainer/WebappContainerWebview.qml 2016-12-02 07:06:20 +0000
4068@@ -0,0 +1,139 @@
4069+/*
4070+ * Copyright 2014-2016 Canonical Ltd.
4071+ *
4072+ * This file is part of webbrowser-app.
4073+ *
4074+ * webbrowser-app is free software; you can redistribute it and/or modify
4075+ * it under the terms of the GNU General Public License as published by
4076+ * the Free Software Foundation; version 3.
4077+ *
4078+ * webbrowser-app is distributed in the hope that it will be useful,
4079+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4080+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4081+ * GNU General Public License for more details.
4082+ *
4083+ * You should have received a copy of the GNU General Public License
4084+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4085+ */
4086+
4087+import QtQuick 2.4
4088+import QtQuick.Window 2.2
4089+import Ubuntu.Components 1.3
4090+import Ubuntu.Unity.Action 1.1 as UnityActions
4091+import Ubuntu.UnityWebApps 0.1 as UnityWebApps
4092+import "../actions" as Actions
4093+import ".."
4094+
4095+FocusScope {
4096+ id: containerWebview
4097+
4098+ property Window window
4099+
4100+ property string url: ""
4101+ property bool developerExtrasEnabled: false
4102+ property string webappName: ""
4103+ property url dataPath
4104+ property var currentWebview: webappContainerWebViewLoader.item ?
4105+ webappContainerWebViewLoader.item.currentWebview
4106+ : null
4107+ property var webappUrlPatterns
4108+ property string localUserAgentOverride: ""
4109+ property string popupRedirectionUrlPrefixPattern: ""
4110+ property url webviewOverrideFile: ""
4111+ property bool blockOpenExternalUrls: false
4112+ property bool runningLocalApplication: false
4113+ property bool wide: false
4114+ property bool openExternalUrlInOverlay: false
4115+ property bool popupBlockerEnabled: true
4116+
4117+ signal samlRequestUrlPatternReceived(string urlPattern)
4118+ signal themeColorMetaInformationDetected(string theme_color)
4119+
4120+ onWideChanged: {
4121+ if (webappContainerWebViewLoader.item
4122+ && webappContainerWebViewLoader.item.wide !== undefined) {
4123+ webappContainerWebViewLoader.item.wide = wide
4124+ }
4125+ }
4126+
4127+ Component {
4128+ id: mediaAccessDialogComponent
4129+ MediaAccessDialog {
4130+ objectName: "mediaAccessDialog"
4131+ }
4132+ }
4133+
4134+ PopupWindowController {
4135+ id: popupController
4136+ objectName: "popupController"
4137+ webappUrlPatterns: containerWebview.webappUrlPatterns
4138+ mainWebappView: containerWebview.currentWebview
4139+ blockOpenExternalUrls: containerWebview.blockOpenExternalUrls
4140+ mediaAccessDialogComponent: mediaAccessDialogComponent
4141+ wide: containerWebview.wide
4142+ onInitializeOverlayViewsWithUrls: {
4143+ if (webappContainerWebViewLoader.item) {
4144+ for (var i in urls) {
4145+ webappContainerWebViewLoader
4146+ .item
4147+ .openOverlayForUrl(urls[i])
4148+ }
4149+ }
4150+ }
4151+
4152+ }
4153+
4154+ Connections {
4155+ target: webappContainerWebViewLoader.item
4156+ onSamlRequestUrlPatternReceived: {
4157+ samlRequestUrlPatternReceived(urlPattern)
4158+ }
4159+ }
4160+
4161+ Connections {
4162+ target: webappContainerWebViewLoader.item
4163+ onThemeColorMetaInformationDetected: {
4164+ themeColorMetaInformationDetected(theme_color)
4165+ }
4166+ }
4167+
4168+ Loader {
4169+ id: webappContainerWebViewLoader
4170+ objectName: "containerWebviewLoader"
4171+ anchors.fill: parent
4172+ focus: true
4173+ }
4174+
4175+ onUrlChanged: if (webappContainerWebViewLoader.item) webappContainerWebViewLoader.item.url = url
4176+
4177+ Component.onCompleted: {
4178+ var webappEngineSource = Qt.resolvedUrl("WebViewImplOxide.qml");
4179+
4180+ // This is an experimental, UNSUPPORTED, API
4181+ // It loads an alternative webview, adjusted for a specific webapp
4182+ if (webviewOverrideFile.toString()) {
4183+ console.log("Loading custom webview from " + webviewOverrideFile);
4184+ webappEngineSource = webviewOverrideFile;
4185+ }
4186+
4187+ webappContainerWebViewLoader.setSource(
4188+ webappEngineSource,
4189+ { window: containerWebView.window
4190+ , localUserAgentOverride: containerWebview.localUserAgentOverride
4191+ , url: containerWebview.url
4192+ , webappName: containerWebview.webappName
4193+ , dataPath: dataPath
4194+ , webappUrlPatterns: containerWebview.webappUrlPatterns
4195+ , developerExtrasEnabled: containerWebview.developerExtrasEnabled
4196+ , popupRedirectionUrlPrefixPattern: containerWebview.popupRedirectionUrlPrefixPattern
4197+ , blockOpenExternalUrls: containerWebview.blockOpenExternalUrls
4198+ , runningLocalApplication: containerWebview.runningLocalApplication
4199+ , popupController: popupController
4200+ , overlayViewsParent: containerWebview.parent
4201+ , wide: containerWebview.wide
4202+ , mediaAccessDialogComponent: mediaAccessDialogComponent
4203+ , openExternalUrlInOverlay: containerWebview.openExternalUrlInOverlay
4204+ , popupBlockerEnabled: containerWebview.popupBlockerEnabled})
4205+ }
4206+}
4207+
4208
4209=== added file 'webapp-googleplus/lib/webcontainer/WebappWebview.qml'
4210--- webapp-googleplus/lib/webcontainer/WebappWebview.qml 1970-01-01 00:00:00 +0000
4211+++ webapp-googleplus/lib/webcontainer/WebappWebview.qml 2016-12-02 07:06:20 +0000
4212@@ -0,0 +1,234 @@
4213+/*
4214+ * Copyright 2016 Canonical Ltd.
4215+ *
4216+ * This file is part of webbrowser-app.
4217+ *
4218+ * webbrowser-app is free software; you can redistribute it and/or modify
4219+ * it under the terms of the GNU General Public License as published by
4220+ * the Free Software Foundation; version 3.
4221+ *
4222+ * webbrowser-app is distributed in the hope that it will be useful,
4223+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4224+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4225+ * GNU General Public License for more details.
4226+ *
4227+ * You should have received a copy of the GNU General Public License
4228+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4229+ */
4230+
4231+import QtQuick 2.4
4232+import com.canonical.Oxide 1.8 as Oxide
4233+import Ubuntu.Components 1.3
4234+import Ubuntu.Components.Popups 1.3
4235+import Ubuntu.Web 0.2
4236+import "../actions" as Actions
4237+import ".."
4238+
4239+WebViewImpl {
4240+ id: webappWebview
4241+
4242+ property bool wide: false
4243+
4244+ signal openUrlExternallyRequested(string url)
4245+
4246+ filePicker: filePickerLoader.item
4247+
4248+ property QtObject contextModel: null
4249+ contextualActions: ActionList {
4250+ Actions.OpenLinkInBrowser {
4251+ objectName: "OpenLinkInBrowser"
4252+ enabled: contextModel && contextModel.linkUrl.toString()
4253+ onTriggered: openUrlExternallyRequested(contextModel.linkUrl)
4254+ }
4255+ Actions.CopyLink {
4256+ enabled: contextModel && contextModel.linkUrl.toString()
4257+ onTriggered: Clipboard.push(["text/plain", contextModel.linkUrl.toString()])
4258+ objectName: "CopyLinkContextualAction"
4259+ }
4260+ Actions.SaveLink {
4261+ enabled: contextModel && contextModel.linkUrl.toString()
4262+ onTriggered: contextModel.saveLink()
4263+ objectName: "SaveLinkContextualAction"
4264+ }
4265+ Actions.Share {
4266+ objectName: "ShareContextualAction"
4267+ enabled: (contentHandlerLoader.status == Loader.Ready) && contextModel &&
4268+ (contextModel.linkUrl.toString() || contextModel.selectionText)
4269+ onTriggered: {
4270+ if (contextModel.linkUrl.toString()) {
4271+ internal.shareLink(contextModel.linkUrl.toString(), contextModel.linkText)
4272+ } else if (contextModel.selectionText) {
4273+ internal.shareText(contextModel.selectionText)
4274+ }
4275+ }
4276+ }
4277+ Actions.CopyImage {
4278+ enabled: contextModel &&
4279+ (contextModel.mediaType === Oxide.WebView.MediaTypeImage) &&
4280+ contextModel.srcUrl.toString()
4281+ onTriggered: Clipboard.push(["text/plain", contextModel.srcUrl.toString()])
4282+ objectName: "CopyImageContextualAction"
4283+ }
4284+ Actions.SaveImage {
4285+ enabled: contextModel &&
4286+ ((contextModel.mediaType === Oxide.WebView.MediaTypeImage) ||
4287+ (contextModel.mediaType === Oxide.WebView.MediaTypeCanvas)) &&
4288+ contextModel.hasImageContents
4289+ onTriggered: contextModel.saveMedia()
4290+ objectName: "SaveImageContextualAction"
4291+ }
4292+ Actions.Undo {
4293+ enabled: contextModel &&
4294+ contextModel.isEditable &&
4295+ (contextModel.editFlags & Oxide.WebView.UndoCapability)
4296+ onTriggered: executeEditingCommand(Oxide.WebView.EditingCommandUndo)
4297+ objectName: "UndoContextualAction"
4298+ }
4299+ Actions.Redo {
4300+ enabled: contextModel &&
4301+ contextModel.isEditable &&
4302+ (contextModel.editFlags & Oxide.WebView.RedoCapability)
4303+ onTriggered: executeEditingCommand(Oxide.WebView.EditingCommandRedo)
4304+ objectName: "RedoContextualAction"
4305+ }
4306+ Actions.Cut {
4307+ enabled: contextModel &&
4308+ contextModel.isEditable &&
4309+ (contextModel.editFlags & Oxide.WebView.CutCapability)
4310+ onTriggered: executeEditingCommand(Oxide.WebView.EditingCommandCut)
4311+ objectName: "CutContextualAction"
4312+ }
4313+ Actions.Copy {
4314+ enabled: contextModel &&
4315+ contextModel.isEditable &&
4316+ (contextModel.editFlags & Oxide.WebView.CopyCapability)
4317+ onTriggered: executeEditingCommand(Oxide.WebView.EditingCommandCopy)
4318+ objectName: "CopyContextualAction"
4319+ }
4320+ Actions.Paste {
4321+ enabled: contextModel &&
4322+ contextModel.isEditable &&
4323+ (contextModel.editFlags & Oxide.WebView.PasteCapability)
4324+ onTriggered: executeEditingCommand(Oxide.WebView.EditingCommandPaste)
4325+ objectName: "PasteContextualAction"
4326+ }
4327+ Actions.Erase {
4328+ enabled: contextModel &&
4329+ contextModel.isEditable &&
4330+ (contextModel.editFlags & Oxide.WebView.EraseCapability)
4331+ onTriggered: executeEditingCommand(Oxide.WebView.EditingCommandErase)
4332+ objectName: "EraseContextualAction"
4333+ }
4334+ Actions.SelectAll {
4335+ enabled: contextModel &&
4336+ contextModel.isEditable &&
4337+ (contextModel.editFlags & Oxide.WebView.SelectAllCapability)
4338+ onTriggered: executeEditingCommand(Oxide.WebView.EditingCommandSelectAll)
4339+ objectName: "SelectAllContextualAction"
4340+ }
4341+ }
4342+ function contextMenuOnCompleted(menu) {
4343+ if (!menu || !menu.contextModel) {
4344+ return
4345+ }
4346+ contextModel = menu.contextModel
4347+
4348+ var isImageMediaType =
4349+ ((contextModel.mediaType === Oxide.WebView.MediaTypeImage) ||
4350+ (contextModel.mediaType === Oxide.WebView.MediaTypeCanvas))
4351+ && contextModel.hasImageContents;
4352+
4353+ if (contextModel.linkUrl.toString() ||
4354+ contextModel.srcUrl.toString() ||
4355+ contextModel.selectionText ||
4356+ (contextModel.isEditable && contextModel.editFlags) ||
4357+ isImageMediaType) {
4358+ menu.show()
4359+ } else {
4360+ contextModel.close()
4361+ }
4362+ }
4363+ Component {
4364+ id: contextMenuNarrowComponent
4365+ ContextMenuMobile {
4366+ actions: contextualActions
4367+ Component.onCompleted: webappWebview.contextMenuOnCompleted(this)
4368+ }
4369+ }
4370+ Component {
4371+ id: contextMenuWideComponent
4372+ ContextMenuWide {
4373+ associatedWebview: webappWebview
4374+ parent: webappWebview
4375+ actions: contextualActions
4376+ Component.onCompleted: webappWebview.contextMenuOnCompleted(this)
4377+ }
4378+ }
4379+ contextMenu: webappWebview.wide ? contextMenuWideComponent : contextMenuNarrowComponent
4380+
4381+ onGeolocationPermissionRequested: {
4382+ if (__runningConfined && (request.origin == request.embedder)) {
4383+ // When running confined, querying the location service will trigger
4384+ // a system prompt (trust store), so no need for a custom one.
4385+ request.allow()
4386+ } else {
4387+ requestGeolocationPermission(request)
4388+ }
4389+ }
4390+
4391+ Loader {
4392+ id: contentHandlerLoader
4393+ source: "../ContentHandler.qml"
4394+ asynchronous: true
4395+ }
4396+
4397+ QtObject {
4398+ id: internal
4399+
4400+ function instantiateShareComponent() {
4401+ var component = Qt.createComponent("../Share.qml")
4402+ if (component.status === Component.Ready) {
4403+ var share = component.createObject(webappWebview)
4404+ share.onDone.connect(share.destroy)
4405+ return share
4406+ }
4407+ return null
4408+ }
4409+
4410+ function shareLink(url, title) {
4411+ var share = instantiateShareComponent()
4412+ if (share) share.shareLink(url, title)
4413+ }
4414+
4415+ function shareText(text) {
4416+ var share = instantiateShareComponent()
4417+ if (share) share.shareText(text)
4418+ }
4419+ }
4420+
4421+ onShowDownloadDialog: {
4422+ if (downloadDialogLoader.status === Loader.Ready) {
4423+ var downloadDialog =
4424+ PopupUtils.open(downloadDialogLoader.item,
4425+ webappWebview,
4426+ {"contentType" : contentType,
4427+ "downloadId" : downloadId,
4428+ "singleDownload" : downloader,
4429+ "filename" : filename,
4430+ "mimeType" : mimeType})
4431+ downloadDialog.startDownload.connect(startDownload)
4432+ }
4433+ }
4434+
4435+ Loader {
4436+ id: downloadDialogLoader
4437+ source: "ContentDownloadDialog.qml"
4438+ asynchronous: true
4439+ }
4440+
4441+ Loader {
4442+ id: filePickerLoader
4443+ source: "ContentPickerDialog.qml"
4444+ asynchronous: true
4445+ }
4446+}
4447
4448=== added file 'webapp-googleplus/lib/webcontainer/webapp-container.qml'
4449--- webapp-googleplus/lib/webcontainer/webapp-container.qml 1970-01-01 00:00:00 +0000
4450+++ webapp-googleplus/lib/webcontainer/webapp-container.qml 2016-12-02 07:06:20 +0000
4451@@ -0,0 +1,336 @@
4452+/*
4453+ * Copyright 2013-2016 Canonical Ltd.
4454+ *
4455+ * This file is part of webbrowser-app.
4456+ *
4457+ * webbrowser-app is free software; you can redistribute it and/or modify
4458+ * it under the terms of the GNU General Public License as published by
4459+ * the Free Software Foundation; version 3.
4460+ *
4461+ * webbrowser-app is distributed in the hope that it will be useful,
4462+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4463+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4464+ * GNU General Public License for more details.
4465+ *
4466+ * You should have received a copy of the GNU General Public License
4467+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4468+ */
4469+
4470+import QtQuick 2.4
4471+import Ubuntu.Components 1.3
4472+import Ubuntu.UnityWebApps 0.1 as UnityWebApps
4473+import Ubuntu.Web 0.2
4474+import webcontainer.private 0.1
4475+import ".."
4476+
4477+BrowserWindow {
4478+ id: root
4479+ objectName: "webappContainer"
4480+
4481+ property bool backForwardButtonsVisible: true
4482+ property bool chromeVisible: true
4483+
4484+ property string localCookieStoreDbPath: ""
4485+
4486+ property string url: ""
4487+ property url webappIcon: ""
4488+ property string webappName: ""
4489+ property string webappModelSearchPath: ""
4490+ property var webappUrlPatterns
4491+ property string accountProvider: ""
4492+ property bool accountSwitcher: false
4493+ property string popupRedirectionUrlPrefixPattern: ""
4494+ property url webviewOverrideFile: ""
4495+ property var __webappCookieStore: null
4496+ property alias webContextSessionCookieMode: webappViewLoader.webContextSessionCookieMode
4497+ property string localUserAgentOverride: ""
4498+ property bool blockOpenExternalUrls: false
4499+ property bool openExternalUrlInOverlay: false
4500+ property string defaultVideoCaptureCameraPosition: ""
4501+ property bool popupBlockerEnabled: true
4502+
4503+ currentWebview: webappViewLoader.item ? webappViewLoader.item.currentWebview : null
4504+
4505+ property bool runningLocalApplication: false
4506+
4507+ property bool startMaximized: false
4508+
4509+ title: getWindowTitle()
4510+
4511+ // Used for testing
4512+ signal schemeUriHandleFilterResult(string uri)
4513+
4514+ function getWindowTitle() {
4515+ var webappViewTitle =
4516+ webappViewLoader.item
4517+ ? webappViewLoader.item.title : ""
4518+ var name = getWebappName()
4519+ if (typeof(name) === 'string' && name.length !== 0) {
4520+ return name
4521+ } else if (webappViewTitle) {
4522+ // TRANSLATORS: %1 refers to the current page’s title
4523+ return i18n.tr("%1 - Ubuntu Web Browser").arg(webappViewTitle)
4524+ } else {
4525+ return i18n.tr("Ubuntu Web Browser")
4526+ }
4527+ }
4528+
4529+ Component {
4530+ id: webappViewComponent
4531+
4532+ WebApp {
4533+ id: browser
4534+
4535+ window: root
4536+
4537+ url: accountProvider.length !== 0 ? "" : root.url
4538+
4539+ accountSwitcher: root.accountSwitcher
4540+
4541+ dataPath: webappDataLocation
4542+ chromeVisible: root.chromeVisible
4543+ backForwardButtonsVisible: root.backForwardButtonsVisible
4544+ developerExtrasEnabled: root.developerExtrasEnabled
4545+ webappModelSearchPath: root.webappModelSearchPath
4546+ webappUrlPatterns: root.webappUrlPatterns
4547+ blockOpenExternalUrls: root.blockOpenExternalUrls
4548+ openExternalUrlInOverlay: root.openExternalUrlInOverlay
4549+ defaultVideoCaptureDevicePosition: root.defaultVideoCaptureCameraPosition ?
4550+ root.defaultVideoCaptureCameraPosition
4551+ : browser.defaultVideoCaptureDevicePosition
4552+ popupBlockerEnabled: root.popupBlockerEnabled
4553+ hasTouchScreen: root.hasTouchScreen
4554+
4555+ focus: true
4556+
4557+ popupRedirectionUrlPrefixPattern: root.popupRedirectionUrlPrefixPattern
4558+
4559+ localUserAgentOverride: getLocalUserAgentOverrideIfAny()
4560+
4561+ runningLocalApplication: root.runningLocalApplication
4562+ webviewOverrideFile: root.webviewOverrideFile
4563+
4564+ anchors.fill: parent
4565+
4566+ onWebappNameChanged: {
4567+ if (root.webappName !== browser.webappName) {
4568+ root.webappName = browser.webappName;
4569+ root.title = getWindowTitle();
4570+ }
4571+ }
4572+
4573+ onChooseAccount: {
4574+ showAccountsPage()
4575+ onlineAccountsController.showAccountSwitcher()
4576+ }
4577+ }
4578+ }
4579+
4580+ function getWebappName() {
4581+ /**
4582+ Any webapp name coming from the command line takes over.
4583+ A webapp can also be defined by a specific drop-in webapp-properties.json
4584+ file that can bundle a few specific 'properties' (as the name implies)
4585+ instead of having them listed in the command line.
4586+ */
4587+ if (webappName)
4588+ return webappName
4589+ return webappModelSearchPath && webappModel.providesSingleInlineWebapp()
4590+ ? webappModel.getSingleInlineWebappName()
4591+ : ""
4592+ }
4593+
4594+ function getLocalUserAgentOverrideIfAny() {
4595+ if (localUserAgentOverride.length !== 0)
4596+ return localUserAgentOverride
4597+
4598+ var name = getWebappName()
4599+ if (name && webappModel.exists(name))
4600+ return webappModel.userAgentOverrideFor(name)
4601+
4602+ return ""
4603+ }
4604+
4605+ UnityWebApps.UnityWebappsAppModel {
4606+ id: webappModel
4607+ searchPath: root.webappModelSearchPath
4608+
4609+ onModelContentChanged: {
4610+ var name = getWebappName()
4611+ if (name && root.url.length === 0) {
4612+ var idx = webappModel.getWebappIndex(name)
4613+ root.url = webappModel.data(
4614+ idx, UnityWebApps.UnityWebappsAppModel.Homepage)
4615+ }
4616+ }
4617+ }
4618+
4619+ // Because of https://launchpad.net/bugs/1398046, it's important that this
4620+ // is the first child
4621+ Loader {
4622+ id: webappViewLoader
4623+ anchors.fill: parent
4624+
4625+ property var webContextSessionCookieMode: ""
4626+ property var webappDataLocation
4627+
4628+ focus: true
4629+
4630+ onLoaded: {
4631+ var context = item.currentWebview.context
4632+ onlineAccountsController.setupWebcontextForAccount(context)
4633+ }
4634+ }
4635+
4636+ OnlineAccountsController {
4637+ id: onlineAccountsController
4638+ anchors.fill: parent
4639+ z: -1 // This is needed to have the dialogs shown; see above comment about bug 1398046
4640+ providerId: accountProvider
4641+ applicationId: unversionedAppId
4642+ accountSwitcher: root.accountSwitcher
4643+ webappName: getWebappName()
4644+ webappIcon: root.webappIcon
4645+
4646+ onAccountSelected: {
4647+ var newWebappDataLocation = dataLocation + accountDataLocation
4648+ console.log("Loading webview on " + newWebappDataLocation)
4649+ if (newWebappDataLocation == webappViewLoader.webappDataLocation) {
4650+ showWebView()
4651+ return
4652+ }
4653+ webappViewLoader.sourceComponent = null
4654+ webappViewLoader.webappDataLocation = newWebappDataLocation
4655+ // If we need to preserve session cookies, make sure that the
4656+ // mode is "restored" and not "persistent", or the cookies
4657+ // transferred from OA would be lost.
4658+ // We check if the webContextSessionCookieMode is defined and, if so,
4659+ // we override it in the webapp loader.
4660+ if (willMoveCookies && typeof webContextSessionCookieMode === "string") {
4661+ webappViewLoader.webContextSessionCookieMode = "restored"
4662+ }
4663+ webappViewLoader.sourceComponent = webappViewComponent
4664+ }
4665+ onContextReady: startBrowsing()
4666+ onQuitRequested: Qt.quit()
4667+ }
4668+
4669+ Component.onCompleted: {
4670+ i18n.domain = "webbrowser-app"
4671+ if (forceFullscreen) {
4672+ showFullScreen()
4673+ } else if (startMaximized) {
4674+ showMaximized()
4675+ } else {
4676+ show()
4677+ }
4678+ }
4679+
4680+ function showWebView() {
4681+ onlineAccountsController.visible = false
4682+ webappViewLoader.visible = true
4683+ }
4684+
4685+ function showAccountsPage() {
4686+ webappViewLoader.visible = false
4687+ onlineAccountsController.visible = true
4688+ }
4689+
4690+ function startBrowsing() {
4691+ console.log("Start browsing")
4692+ // This will activate the UnityWebApp element used in WebApp.qml
4693+ webappViewLoader.item.webappName = root.webappName
4694+
4695+ // As we use StateSaver to restore the URL, we need to check first if
4696+ // it has not been set previously before setting the URL to the default property
4697+ // homepage.
4698+ var webView = webappViewLoader.item.currentWebview
4699+ var current_url = webView.url.toString();
4700+ if (!current_url || current_url.length === 0) {
4701+ webView.url = root.url
4702+ }
4703+ showWebView()
4704+ }
4705+
4706+ function makeUrlFromResult(result) {
4707+ var scheme = null
4708+ var hostname = null
4709+ var url = root.currentWebview.url || root.url
4710+ if (result.host
4711+ && result.host.length !== 0) {
4712+ hostname = result.host
4713+ }
4714+ else {
4715+ var matchHostname = url.toString().match(/.*:\/\/([^/]*)\/.*/)
4716+ if (matchHostname.length > 1) {
4717+ hostname = matchHostname[1]
4718+ }
4719+ }
4720+
4721+ if (result.scheme
4722+ && result.scheme.length !== 0) {
4723+ scheme = result.scheme
4724+ }
4725+ else {
4726+ var matchScheme = url.toString().match(/(.*):\/\/[^/]*\/.*/)
4727+ if (matchScheme.length > 1) {
4728+ scheme = matchScheme[1]
4729+ }
4730+ }
4731+ return scheme
4732+ + '://'
4733+ + hostname
4734+ + "/"
4735+ + (result.path
4736+ ? result.path : "")
4737+ }
4738+
4739+ /**
4740+ *
4741+ */
4742+ function translateHandlerUri(uri) {
4743+ //
4744+ var scheme = uri.substr(0, uri.indexOf(":"))
4745+ if (scheme.indexOf("http") === 0) {
4746+ schemeUriHandleFilterResult(uri)
4747+ return uri
4748+ }
4749+
4750+ var result = webappSchemeFilter.applyFilter(uri)
4751+ var mapped_uri = makeUrlFromResult(result)
4752+
4753+ uri = mapped_uri
4754+
4755+ // Report the result of the intent uri filtering (if any)
4756+ // Done for testing purposed. It is not possible at this point
4757+ // to have AP call a slot and retrieve its result synchronously.
4758+ schemeUriHandleFilterResult(uri)
4759+
4760+ return uri
4761+ }
4762+
4763+ function openUrls(urls) {
4764+ // only consider the first one (if multiple)
4765+ if (urls.length === 0 || !root.currentWebview) {
4766+ return;
4767+ }
4768+ var requestedUrl = urls[0].toString();
4769+
4770+ if (popupRedirectionUrlPrefixPattern.length !== 0
4771+ && requestedUrl.match(popupRedirectionUrlPrefixPattern)) {
4772+ return;
4773+ }
4774+
4775+ requestedUrl = translateHandlerUri(requestedUrl);
4776+
4777+ // Add a small guard to prevent browsing to invalid urls
4778+ if (currentWebview
4779+ && currentWebview.shouldAllowNavigationTo
4780+ && !currentWebview.shouldAllowNavigationTo(requestedUrl)) {
4781+ return;
4782+ }
4783+
4784+ root.url = requestedUrl
4785+ root.currentWebview.url = requestedUrl
4786+ }
4787+}
4788
4789=== modified file 'webapp-googleplus/manifest.json'
4790--- webapp-googleplus/manifest.json 2016-02-11 11:03:08 +0000
4791+++ webapp-googleplus/manifest.json 2016-12-02 07:06:20 +0000
4792@@ -15,5 +15,5 @@
4793 "maintainer": "Webapps Team <webapps@lists.launchpad.net>",
4794 "name": "com.ubuntu.developer.webapps.googleplus",
4795 "title": "Google+",
4796- "version": "0.7.2"
4797+ "version": "0.7.3"
4798 }
4799
4800=== modified file 'webapp-googleplus/webview-override.qml'
4801--- webapp-googleplus/webview-override.qml 2016-02-10 15:23:59 +0000
4802+++ webapp-googleplus/webview-override.qml 2016-12-02 07:06:20 +0000
4803@@ -24,19 +24,10 @@
4804 import Ubuntu.UnityWebApps 0.1 as UnityWebApps
4805 import Ubuntu.Web 0.2
4806 import Ubuntu.Content 0.1
4807-import "./actions" as Actions
4808-import "./lib"
4809-
4810-Item {
4811- id: webviewWrapper
4812-
4813- property bool developerExtrasEnabled: false
4814- property string webappName: ""
4815- property string localUserAgentOverride: ""
4816- property var webappUrlPatterns: null
4817- property string url: ""
4818- property var currentWebview: webview ? webview.currentWebview : null
4819- property url dataPath
4820+import "./lib/webcontainer"
4821+
4822+WebViewImplOxide {
4823+ id: webview
4824
4825 property var activeFileUrisToShare: []
4826 property var activeTransfer
4827@@ -117,7 +108,7 @@
4828 Component {
4829 id: contentHubSharePassthroughPickerComponent
4830 Item {
4831- anchors.fill: webviewWrapper
4832+ anchors.fill: webview
4833 Component.onCompleted: {
4834 model.accept(activeFileUrisToShare)
4835 clearContentHubShareState()
4836@@ -171,289 +162,19 @@
4837 }
4838 }
4839 webview.onLoadingChanged.connect(onLoadChanged)
4840- webview.url = webviewWrapper.url
4841 }
4842 }
4843
4844- // unused
4845- property string popupRedirectionUrlPrefixPattern: ""
4846- property bool blockOpenExternalUrls: false
4847-
4848- WebViewImpl {
4849- id: webview
4850- anchors.fill: parent
4851-
4852- currentWebview: webview
4853-
4854- context: WebContext {
4855- dataPath: webviewWrapper.dataPath
4856- userAgent: localUserAgentOverride ? localUserAgentOverride : defaultUserAgent
4857-
4858- userScripts: [
4859- Oxide.UserScript {
4860- context: "oxide://share-request-context/"
4861- url: Qt.resolvedUrl("share-request-host.js")
4862- matchAllFrames: false
4863- }
4864- ]
4865- }
4866-
4867- preferences.allowFileAccessFromFileUrls: runningLocalApplication
4868- preferences.allowUniversalAccessFromFileUrls: runningLocalApplication
4869-
4870- contextualActions: ActionList {
4871- Actions.CopyLink {
4872- enabled: webview.contextualData.href.toString()
4873- onTriggered: Clipboard.push([webview.contextualData.href])
4874- }
4875- Actions.CopyImage {
4876- enabled: webview.contextualData.img.toString()
4877- onTriggered: Clipboard.push([webview.contextualData.img])
4878- }
4879- }
4880-
4881- StateSaver.properties: "url"
4882- StateSaver.enabled: !runningLocalApplication
4883-
4884- function isRunningAsANamedWebapp() {
4885- return webview.webappName && typeof(webview.webappName) === 'string' && webview.webappName.length != 0
4886- }
4887-
4888- function haveValidUrlPatterns() {
4889- return webappUrlPatterns && webappUrlPatterns.length !== 0
4890- }
4891-
4892- function isNewForegroundWebViewDisposition(disposition) {
4893- return disposition === Oxide.NavigationRequest.DispositionNewPopup ||
4894- disposition === Oxide.NavigationRequest.DispositionNewForegroundTab;
4895- }
4896-
4897- function openUrlExternally(url) {
4898- Qt.openUrlExternally(url)
4899- }
4900-
4901- function shouldAllowNavigationTo(url) {
4902- // The list of url patterns defined by the webapp takes precedence over command line
4903- if (isRunningAsANamedWebapp()) {
4904- if (unityWebapps.model.exists(unityWebapps.name) &&
4905- unityWebapps.model.doesUrlMatchesWebapp(unityWebapps.name, url)) {
4906- return true;
4907- }
4908- }
4909-
4910- // We still take the possible additional patterns specified in the command line
4911- // (the in the case of finer grained ones specifically for the container and not
4912- // as an 'install source' for the webapp).
4913- if (haveValidUrlPatterns()) {
4914- for (var i = 0; i < webappUrlPatterns.length; ++i) {
4915- var pattern = webappUrlPatterns[i]
4916- if (url.match(pattern)) {
4917- return true;
4918- }
4919- }
4920- }
4921-
4922- return false;
4923- }
4924-
4925- function navigationRequestedDelegate(request) {
4926- var newForegroundPageRequest = isNewForegroundWebViewDisposition(request.disposition)
4927- var url = request.url.toString()
4928-
4929- console.log("navigationRequestedDelegate - newForegroundPageRequest: "
4930- + newForegroundPageRequest
4931- + ', url: ' + url)
4932-
4933- if (runningLocalApplication && url.indexOf("file://") !== 0) {
4934- request.action = Oxide.NavigationRequest.ActionReject
4935- openUrlExternally(url)
4936- return
4937- }
4938-
4939- // Covers some edge cases corresponding to the default window.open() behavior.
4940- // When it is being called, the targetted URL will not load right away but
4941- // will first round trip to an "about:blank".
4942- // See https://developer.mozilla.org/en-US/docs/Web/API/Window.open
4943- if (newForegroundPageRequest) {
4944- if (url == 'about:blank') {
4945- console.log('Accepting a new window request to navigate to "about:blank"')
4946- request.action = Oxide.NavigationRequest.ActionAccept
4947- return
4948- }
4949-
4950- var isRedirectionUrl = false;
4951- var targetUrl = url;
4952- if (popupRedirectionUrlPrefixPattern) {
4953- // NOTE: very nasty workaround to be backward compatibility, will be deleted as soon
4954- // as the FB webapp is updated.
4955- if (popupRedirectionUrlPrefixPattern.indexOf('(') === -1) {
4956- isRedirectionUrl = (url.indexOf(popupRedirectionUrlPrefixPattern) === 0);
4957- targetUrl = isRedirectionUrl ?
4958- url.slice(popupRedirectionUrlPrefixPattern.length) : url;
4959-
4960- // Quick fix for http://pad.lv/1358622 (trim trailing parameters).
4961- var extraParams = targetUrl.indexOf("&");
4962- if (extraParams !== -1) {
4963- targetUrl = targetUrl.slice(0, extraParams);
4964- }
4965- } else {
4966- var redirectionPatternMatch = url.match(popupRedirectionUrlPrefixPattern);
4967- isRedirectionUrl =
4968- popupRedirectionUrlPrefixPattern
4969- && redirectionPatternMatch
4970- && redirectionPatternMatch.length >= 2;
4971-
4972- // Assume that the first group is the matching one
4973- targetUrl = isRedirectionUrl ?
4974- redirectionPatternMatch[1] : url;
4975- }
4976- }
4977-
4978- if (isRedirectionUrl) {
4979- console.debug("Got a redirection URL with target URL: " + targetUrl)
4980- targetUrl = decodeURIComponent(targetUrl)
4981- gotRedirectionUrl(targetUrl)
4982- }
4983-
4984- if (webview.shouldAllowNavigationTo(targetUrl)) {
4985- console.debug('Redirecting popup browsing ' + targetUrl + ' in the current container window.')
4986- request.action = Oxide.NavigationRequest.ActionReject
4987- webappContainerHelper.browseToUrlRequested(webview, targetUrl)
4988- return
4989- }
4990-
4991- console.debug('Opening popup window ' + targetUrl + ' in the browser window.')
4992- request.action = Oxide.NavigationRequest.ActionReject
4993- openUrlExternally(targetUrl)
4994- return
4995- }
4996-
4997- // Pass-through if we are not running as a named webapp (--webapp='Gmail')
4998- // or if we dont have a list of url patterns specified to filter the
4999- // browsing actions
5000- if ( ! webview.haveValidUrlPatterns() && ! webview.isRunningAsANamedWebapp()) {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: