Merge lp:~mardy/webbrowser-app/add-onlineaccount-support-for-container2 into lp:webbrowser-app

Proposed by Alberto Mardegan
Status: Merged
Merged at revision: 556
Proposed branch: lp:~mardy/webbrowser-app/add-onlineaccount-support-for-container2
Merge into: lp:webbrowser-app
Diff against target: 1573 lines (+935/-256)
21 files modified
debian/control (+4/-1)
src/app/browserapplication.cpp (+6/-0)
src/app/browserapplication.h (+2/-0)
src/app/webcontainer/AccountsPage.qml (+73/-0)
src/app/webcontainer/CMakeLists.txt (+5/-1)
src/app/webcontainer/chrome-cookie-store.cpp (+218/-0)
src/app/webcontainer/chrome-cookie-store.h (+53/-0)
src/app/webcontainer/cookie-store.cpp (+30/-24)
src/app/webcontainer/cookie-store.h (+16/-28)
src/app/webcontainer/online-accounts-cookie-store.cpp (+8/-12)
src/app/webcontainer/online-accounts-cookie-store.h (+6/-6)
src/app/webcontainer/sqlitecookiestore.cpp (+0/-99)
src/app/webcontainer/sqlitecookiestore.h (+0/-58)
src/app/webcontainer/webapp-container.cpp (+24/-1)
src/app/webcontainer/webapp-container.h (+4/-0)
src/app/webcontainer/webapp-container.qml (+114/-26)
src/app/webcontainer/webkit-cookie-store.cpp (+120/-0)
src/app/webcontainer/webkit-cookie-store.h (+51/-0)
tests/unittests/CMakeLists.txt (+1/-0)
tests/unittests/cookie-store/CMakeLists.txt (+11/-0)
tests/unittests/cookie-store/tst_CookieStore.cpp (+189/-0)
To merge this branch: bzr merge lp:~mardy/webbrowser-app/add-onlineaccount-support-for-container2
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Olivier Tilloy Approve
David Barth (community) Approve
Review via email: mp+211701@code.launchpad.net

Commit message

Add online account support in the webapp container.

A new "accountProvider" command line parameter has been added to allow one to specify an account provider for the specific webapp launch. When used, one can specify a given provider, e.g. "facebook", to pull existing accounts (if any) from the specified provider
from Online Accounts.

When the provider does not have any existing account, an option to delegate the creation of such an account to OA is provided. It is also possible to skip the step and go straight to the target url.

Description of the change

Add online account support in the webapp container.

A new "accountProvider" command line parameter has been added to allow one to specify an account provider for the specific webapp launch. When used, one can specify a given provider, e.g. "facebook", to pull existing accounts (if any) from the specified provider
from Online Accounts.

When the provider does not have any existing account, an option to delegate the creation of such an account to OA is provided. It is also possible to skip the step and go straight to the target url.

In order to use it, one can use a command line such as:

APP_ID=cookie-test ./webapp-container --webapp --accountProvider=facebook https://www.facebook.com

(provided a proper .application file has been installed with the proper name in /usr/share/accounts/applications).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:470
http://jenkins.qa.ubuntu.com/job/webbrowser-app-ci/648/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/4061/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/3646
    SUCCESS: http://jenkins.qa.ubuntu.com/job/webbrowser-app-trusty-amd64-ci/150
    SUCCESS: http://jenkins.qa.ubuntu.com/job/webbrowser-app-trusty-armhf-ci/150
        deb: http://jenkins.qa.ubuntu.com/job/webbrowser-app-trusty-armhf-ci/150/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/webbrowser-app-trusty-i386-ci/150
    FAILURE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/3545/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4113
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4113/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3648
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3648/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5971
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/4970

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/webbrowser-app-ci/648/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
David Barth (dbarth) :
review: Approve
Revision history for this message
Olivier Tilloy (osomon) wrote :

60 +// system
61 +#include <string.h>
62 +#include <unistd.h>

Those changes seem useless, can they be reverted?

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

287 + bool registerCookieQmlTypes(QQmlEngine * engine);

What’s the point of this method returning a boolean value (the return value seems unused)?

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

223 + qmlRegisterType<CookieStore>("Ubuntu.WebContainer.Components", 0, 1, "CookieStore");
224 + qmlRegisterType<SqliteCookieStore>("Ubuntu.WebContainer.Components", 0, 1, "SqliteCookieStore");
225 + qmlRegisterType<OnlineAccountsCookieStore>("Ubuntu.WebContainer.Components", 0, 1, "OnlineAccountsCookieStore");

For consistency with what’s already done in webbrowser-app.cpp (see line 90), and to make it fully explicit that those are not public API exposed through a plugin, could you change the import to "private.webcontainer" (and while at it define a variable with it before the calls to qmlRegisterType)?

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

235 - out << "Usage: " << command << " [-h|--help] [--fullscreen] [--maximized] [--inspector] [--app-id=APP_ID] [--homepage=URL] [--webapp[=name]] [--webappModelSearchPath=PATH] [--webappUrlPatterns=URL_PATTERNS] [--enable-back-forward] [--enable-addressbar] [URL]" << endl;

This was split in several lines for readability (thanks for this!), but it’s missing the new [--accountProvider=PROVIDER_NAME] token.

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

358 + return i18n.tr("Ubuntu Web Application")

Since some strings were updated, the translation template needs to be re-generated. To do that, run:

   cmake . && make webbrowser-app.pot

and then commit the changes to the branch.

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

(apparently, when the initial version of this branch was reverted in trunk, the new C++ files were not removed)

421 + dbPath: ".local/share/" + applicationName + "/.QtWebKit/cookies.db"

Apparently this dbPath property is relative to the user’s home directory. This is not how local files to the applications should be accessed. Instead, use the "dataLocation" global context property being exported by the Ubuntu.Components.Extra.Browser plugin.

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

206 + m_window->setProperty("applicationName", QCoreApplication::applicationName());

In Qt 5.2, the Qt.application global QML object has a 'name' property, which will make this additional property superfluous.

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

=== modified file 'tests/autopilot/webbrowser_app/tests/http_server.py'

Changes to this file are unrelated, please revert.

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

456 +
457 +

Can those two superfluous blank lines be removed?

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

Looks good overall, but I made a bunch of comments for minor changes, so marking needs fixing to ensure they get addressed before landing. Thanks!

review: Needs Fixing
471. By Alberto Mardegan

Address review comments

472. By Alberto Mardegan

remove added empty line

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

The inclusion of <QStandardPaths> in src/app/webcontainer/sqlitecookiestore.cpp is now unused, and should be removed.

473. By Alberto Mardegan

Removed unused header inclusion

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

LGTM.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
474. By Alberto Mardegan

Don't load the webview as soon as a webapp starts

The code in webapp-container.qml initially checks the value of its
"accountProvider" property and loads the webview if that's empty.
If this property is set after the component has been built, this will cause the
webview to be (accidentally) loaded for a fraction of a second, which in turn
will cause the WebProcess to be spawned. The WebProcess will read the
cookies.db file, and the same WebProcess instance will likely be reused for the
webapp, once we really want to use it. This has the unfortunate side-effect
that it will not re-read the cookies which we might have copied over from
Online Accounts in the meantime.

So, with this change we make sure that all properties (including
"accountProvider") will be set on the Window before the component is completed.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
475. By Alberto Mardegan

Fix build

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

I understand the logic in revision 474 (and the need for it), but I’m not very fond of the way it’s implemented. Do we really need an optional CreationMode parameter? Can’t we just make BeginCreation the (non overridable) default?
I.e., what do we gain from keeping webbrowser-app being initialized in CompleteCreation mode?

Revision history for this message
Alberto Mardegan (mardy) wrote :

I agree with you Olivier, I simply wanted to avoid changing webbrowser-app at all. If you don't mind me adding a completeCreate() call in WebbrowserApp::initialize(), we can indeed get rid of that enum.

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

> I agree with you Olivier, I simply wanted to avoid changing webbrowser-app at
> all. If you don't mind me adding a completeCreate() call in
> WebbrowserApp::initialize(), we can indeed get rid of that enum.

Yes, please do. Thanks!

476. By Alberto Mardegan

Always use 2-step creation of the component

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

I haven’t tested again, but the changes look good to me. Please ensure the changes are thoroughly tested before landing.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
477. By Alberto Mardegan

Merge from trunk, partial fixes

[ Ubuntu daily release ]
* New rebuild forced
[ Alexandre Abreu ]
* Fix the network dialog reload (LP: #1309138)
* Oxide (and Chromium) does not inform of non user driven navigations
  (or more specifically redirects that would be part of an
  popup/webview load (after its been granted). Quite a few sites (e.g.
  Youtube), create popups when clicking on links (or following a
  window.open()) with proper youtube.com address but w/ redirection
  params, e.g.:
  http://www.youtube.com/redirect?q=http%3A%2F%2Fgodzillamovie.com%2F&
  redir_token=b8WPI1pq9FHXeHm2bN3KVLAJSfp8MTM5NzI2NDg3NEAxMzk3MTc4NDc0
  In this instance the popup & navigation is granted, but then a
  redirect happens inside the popup to the real target url (here
  http://godzillamovie.com) which is not trapped by a navigation
  requested and therefore not filtered. The only way to do it atm is
  to listen to url changes in popups & also filter there. (LP:
  #1294279)
[ CI bot ]
* Resync trunk
[ Olivier Tilloy ]
* Handle new view requests in the browser. (LP: #1307735)
[ Olivier Tilloy ]
* Force the page title to be reset to an empty string when the
  activity view is being hidden. (LP: #1307420)
[ Michael Sheldon ]
* Add support for file upload via content-hub
[ Ugo Riboni ]
* Add support for file upload via content-hub
[ Alexandre Abreu ]
* Make sure that we dont load unecessary libs (oxide or qtwebkit)
  correspnding to the webengine that we dont use. (LP: #1306037)
* Add a basic set of integration tests for the webapp container
[ Ubuntu daily release ]
* New rebuild forced
[ Olivier Tilloy ]
* Enable UA overrides for all form factors, each in a separate file.
  Add an override for google calendar on desktop. Clean up the
  construction of the default UA string for easier reading and
  maintenance.
[ Bill Filler ]
* Add support for file upload via content-hub
[ David Barth ]
* To prevent https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-
  toolkit/+bug/1305834 caused by a recent UI toolkit change, we are
  returning an empty title for now. (LP: #1305834)
[ Alexandre Abreu ]
* Add support for Oxide's onNavigationRequested in the container (LP:
  #1302769)
* Webapps: maintain the session cookies for the user session Instruct
  Oxide to store/load the session cookies on disk in a per-webapp
  directory under XDG_RUNTIME_DIR. The first time in a user session
  that the webapp is launched, the session cookies (leftover from
  previous sessions) are not loaded, but only stored (this is the
  chrome's "persistent" sessionCookieMode). The next times, session
  cookies are both loaded and stored (chrome's "restored"
  sessionCookieMode).
[ Alberto Mardegan ]
* Webapps: maintain the session cookies for the user session Instruct
  Oxide to store/load the session cookies on disk in a per-webapp
  directory under XDG_RUNTIME_DIR. The first time in a user session
  that the webapp is launched, the session cookies (leftover from
  previous sessions) are not loaded, but only stored (this is the
  chrome's "persistent" sessionCookieMode). The next times, session
  cookies are both loaded and stored (chrome's "restored"
  sessionCookieMode).
[ Ubuntu daily release ]
* New rebuild forced
[ Olivier Tilloy ]
* Update to oxide 1.0.
[ Olivier Tilloy ]
* Re-enable javascript dialogs, now that they are available in oxide.
[ CI bot ]
* Resync trunk
[ Alexandre Abreu ]
* Small update to the --webapp flag documentation
[ Olivier Tilloy ]
* Null-check to fix a segmentation fault when --help is passed to the
  executable.
[ Olivier Tilloy ]
* Land the master Oxide support branch. See individual revisions for
  details. (LP: #1271756)
[ Alexandre Abreu ]
* There are 2 ways for the webapp-container to receive a list of
  patterns to filter url browsing in a webapp container: through the
  manifest.json file that comes with a given (named) webapp, or
  through the command line. At the moment, the 2 mechanisms are
  exclusive in the sense that from the webapp-container's perspective
  it only considers one or another when filtering navigation (the
  webapp manifest one being preferred) but they are NOT semantically
  equivalent. The list of url patterns in the manifest.json file is
  use as a mean to filter the urls that are being browsed to, but ALSO
  in the chromium & FF browsers to know if a webapp is to be
  installed/enabled when browsing in a given url. For example, for
  Gmail, the hostname mail.google.com is used as a trigger to ask the
  user for an installation/enablement of a webapp in the browser. It
  is also implicitely used as a filter for browser once in the
  container. The issue is that for applications like google services,
  the authentication mechanism is common. So when launched in the
  container, the user will be redirected to e.g.
  https://accounts.google.com or https://accounts.google.ca, etc. So,
  the manifest.json cannot be modified to account for those, since we
  dont want to install a webapp from those URLs but we need a way to
  add extra navigation url patterns to allow google service webapps to
  be redirected to e.g. https://accounts.google.* etc. We provide here
  2 things: an way for the url patterns passed down from the command
  line to be also considered in the navigation filtering,. a way to
  simplify url patterns for google apps (LP: #1288982)
[ Olivier Tilloy ]
* Use the renderer only once when rendering a thumbnail. This seems to
  fix the crash that was happening at destruction time. (LP: #1294219)

478. By Alberto Mardegan

WIP

479. By Alberto Mardegan

From trunk

[ Olivier Tilloy ]
* Fix FTBFS with Qt 5.3. (LP: #1321440)
[ Ubuntu daily release ]
* New rebuild forced
[ Olivier Tilloy ]
* Remove an extraneous whitespace in the default UA on mobile.
[ Michael Sheldon ]
* Add support for downloading images via download manager and content-
  hub on non-desktop platforms.
[ Tim Peeters ]
* Push the initial Page on the PageStack.
[ Ubuntu daily release ]
* New rebuild forced
[ Alexandre Abreu ]
* Add --local-webapp-manifest webapp container cli option to simplify
  the command line in the case of a local manifest.json file
  definition. This is to become a bit more important now that the
  manifest support thing like ua overrides that would be beneficial to
  webapp on touch.
[ Ubuntu daily release ]
* New rebuild forced
[ Alexandre Abreu ]
* Add capability for single webapps to have specific UA overrides for
  the website that they serve (LP: #1245465)
[ Olivier Tilloy ]
* Enable cross compilation for an ARM target on an X86 host.
* Port autopilot tests to Python 3.
[ Michael Sheldon ]
* Resolve image URLs beginning with a double slash correctly for
  context menu items (LP: #1311626)
[ Adnane Belmadiaf ]
* Enabled passwordEchoEnabled (LP: #1314251)
[ Alberto Mardegan ]
* Split UbuntuWebContext into two different components:
  UbuntuWebContext, which is a WebContext derivative with the UA
  overrides for Ubuntu. UbuntuSharedWebContext, which is a singleton
  for UbuntuWebContext .
[ Olivier Tilloy ]
* Build the models in a separate static lib, and link the unit tests
  against it. This speeds up build time by avoiding having to
  recompile the models’ source for each unit test.
* Handle javascript console messages.
* Escape literal dots in UA override matching regular expressions.
* Enable localStorage by default in the browser. (LP: #1309673)
* Ensure that the URL actually changes so that the address bar is
  updated in case the user has entered a new address that redirects to
  where she previously was. (LP: #1306615)
* Update bzr ignore rules.
[ Olivier Tilloy ]
* Work around a recent regression by forcing the OSK to show up when
  the address bar is being focused. (LP: #1316057)
[ CI bot ]
* Resync trunk
[ Alberto Mardegan ]
* Webapps: let SAML requests through SAML requests are used for
  instance by Google Apps for your domain; they are implemented as a
  HTTP redirect to a URL containing the query parameter called
  "SAMLRequest". Besides letting the request through, we must also add
  the SAML domain to the list of the allowed hosts. (LP: #1302780)
[ Ubuntu daily release ]
* New rebuild forced

480. By Alberto Mardegan

Fix cookies stores, add tests

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

614 + bool setCookies(Cookies);

Shouldn’t the argument be a "const Cookies&" ? (this applies to other methods that take a Cookies as argument)

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

In CookieStore::doSetCookies(…), you could use the Q_UNIMPLEMENTED() macro to make it explicit that this method is meant to be re-implemented by subclasses.

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

440 + QString dbPath() const;
1310 + QString dbPath() const;

Can those return a "const QString&" ?

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

1108 + WebkitCookieStore {
1109 + id: webkitCookieStore
1110 + dbPath: dataLocation + "/.QtWebKit/cookies.db"
1111 + }
1112 +
1113 + ChromeCookieStore {
1114 + id: chromeCookieStore
1115 + dbPath: dataLocation + "/cookies.sqlite"
1116 + }

The two implementations of CookieStore are instantiated at all times, even though only one (or possibly none) of them is used. Can only one of them be instantiated dynamically in loadLoginView() instead?

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

1344 +set(TEST tst_CookieStore)

Can this be renamed to "tst_CookieStoreTests", so that the bzr ignore rules will match the generated binary and xml output?

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

1436 + makeCleanDir("/tmp/non-existing");
1437 + makeCleanDir("/tmp/non-existing2");

Please use QTemporaryDir instead to create truly unique and temporary directories.

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

1442 + QCOMPARE(dbPathChanged.count(), 0);
1462 + QCOMPARE(dbPathChanged.count(), 0);

Those tests are useless, as you just instantiated the signal spy, so you are guaranteed that the count is 0.

481. By Alberto Mardegan

Fix the webapp container

482. By Alberto Mardegan

Merge from trunk

[ Ubuntu daily release ]
* New rebuild forced
[ Olivier Tilloy ]
* Ensure the main page that contains the webviews fills the main view.
  (LP: #1321462)
[ Olivier Tilloy ]
* Ensure the current webview is hidden while the activity view is
  visible, and work around a bug in oxide that prevented new empty
  tabs from rendering.
[ Ubuntu daily release ]
* New rebuild forced
[ Olivier Tilloy ]
* Various optimizations to the activity view. (LP: #1260980)
* Do not override the default height of the TextField that serves as
  the address bar. (LP: #1317866)

483. By Alberto Mardegan

Revert changes to pot file

484. By Alberto Mardegan

Address review comments

Revision history for this message
Alberto Mardegan (mardy) wrote :

On 05/29/2014 11:27 AM, Olivier Tilloy wrote:
> 614 + bool setCookies(Cookies);
>
> Shouldn’t the argument be a "const Cookies&" ? (this applies to other methods that take a Cookies as argument)

Fixed.

> In CookieStore::doSetCookies(…), you could use the Q_UNIMPLEMENTED() macro to make it explicit that this method is meant to be re-implemented by subclasses.

Done.

> 440 + QString dbPath() const;
> 1310 + QString dbPath() const;
>
> Can those return a "const QString&" ?

They could indeed, but I prefer not to return a reference, because that
exposes an implementation detail (the fact that we store the path as a
member variable in the class). I generally never return by reference,
unless I have a very good reason to; but if you feel strongly about
this, I can change it.

> The two implementations of CookieStore are instantiated at all times, even though only one (or possibly none) of them is used. Can only one of them be instantiated dynamically in loadLoginView() instead?

Done.

> 1344 +set(TEST tst_CookieStore)
>
> Can this be renamed to "tst_CookieStoreTests", so that the bzr ignore rules will match the generated binary and xml output?

Done.

> 1436 + makeCleanDir("/tmp/non-existing");
> 1437 + makeCleanDir("/tmp/non-existing2");
>
> Please use QTemporaryDir instead to create truly unique and temporary directories.

Done.

> 1442 + QCOMPARE(dbPathChanged.count(), 0);
> 1462 + QCOMPARE(dbPathChanged.count(), 0);
>
> Those tests are useless, as you just instantiated the signal spy, so you are guaranteed that the count is 0.

No idea what I was thinking :-) I've now removed them.

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

> 1344 +set(TEST tst_CookieStore)
>
> Can this be renamed to "tst_CookieStoreTests", so that the bzr ignore rules
> will match the generated binary and xml output?

Almost there :)
You renamed it to "tst_CookieStoreTest", so it’s still missing the final "s" to match the other test cases’ naming convention.

Revision history for this message
Olivier Tilloy (osomon) :
485. By Alberto Mardegan

Rename test executable

Revision history for this message
Alberto Mardegan (mardy) wrote :

I changed the test name, and replied to your comment about the SQL connection name.

486. By Alberto Mardegan

Remove support for relative file paths

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

Looks good to me now.

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

FAILED: Continuous integration, rev:486
http://jenkins.qa.ubuntu.com/job/webbrowser-app-ci/844/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/554/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic-touch/139/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/webbrowser-app-utopic-amd64-ci/43
    SUCCESS: http://jenkins.qa.ubuntu.com/job/webbrowser-app-utopic-armhf-ci/43
        deb: http://jenkins.qa.ubuntu.com/job/webbrowser-app-utopic-armhf-ci/43/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/webbrowser-app-utopic-i386-ci/43
    FAILURE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/495/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/693
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/693/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1160
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/1160/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/6775/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/7978

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/webbrowser-app-ci/844/rebuild

review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2014-05-02 05:45:21 +0000
+++ debian/control 2014-06-02 11:59:43 +0000
@@ -51,9 +51,12 @@
51Multi-Arch: foreign51Multi-Arch: foreign
52Depends: ${misc:Depends},52Depends: ${misc:Depends},
53 ${shlibs:Depends},53 ${shlibs:Depends},
54 libqt5webkit5-qmlwebkitplugin,
55 qtdeclarative5-accounts-plugin,
56 qtdeclarative5-qtquick2-plugin (>= 5.2),
54 unity-webapps-qml,57 unity-webapps-qml,
55 libqt5webkit5-qmlwebkitplugin,
56 webbrowser-app (= ${binary:Version}),58 webbrowser-app (= ${binary:Version}),
59Suggests: qtdeclarative5-online-accounts-client0.1 (>= 0.3),
57Description: Ubuntu web applications container60Description: Ubuntu web applications container
58 A lightweight webapps container tailored for Ubuntu, based on the Webkit61 A lightweight webapps container tailored for Ubuntu, based on the Webkit
59 rendering engine and using the Ubuntu UI components.62 rendering engine and using the Ubuntu UI components.
6063
=== modified file 'src/app/browserapplication.cpp'
--- src/app/browserapplication.cpp 2014-05-21 08:01:42 +0000
+++ src/app/browserapplication.cpp 2014-06-02 11:59:43 +0000
@@ -122,6 +122,9 @@
122 if (!isRunningInstalled()) {122 if (!isRunningInstalled()) {
123 m_engine->addImportPath(UbuntuBrowserImportsDirectory());123 m_engine->addImportPath(UbuntuBrowserImportsDirectory());
124 }124 }
125
126 qmlEngineCreated(m_engine);
127
125 QQmlContext* context = m_engine->rootContext();128 QQmlContext* context = m_engine->rootContext();
126 m_component = new QQmlComponent(m_engine);129 m_component = new QQmlComponent(m_engine);
127 m_component->loadUrl(QUrl::fromLocalFile(UbuntuBrowserDirectory() + "/" + qmlFileSubPath));130 m_component->loadUrl(QUrl::fromLocalFile(UbuntuBrowserDirectory() + "/" + qmlFileSubPath));
@@ -141,6 +144,9 @@
141 return true;144 return true;
142}145}
143146
147void BrowserApplication::qmlEngineCreated(QQmlEngine*)
148{}
149
144int BrowserApplication::run()150int BrowserApplication::run()
145{151{
146 Q_ASSERT(m_window != 0);152 Q_ASSERT(m_window != 0);
147153
=== modified file 'src/app/browserapplication.h'
--- src/app/browserapplication.h 2014-04-10 14:47:53 +0000
+++ src/app/browserapplication.h 2014-06-02 11:59:43 +0000
@@ -49,6 +49,8 @@
49 virtual void printUsage() const = 0;49 virtual void printUsage() const = 0;
50 QList<QUrl> urls() const;50 QList<QUrl> urls() const;
5151
52 virtual void qmlEngineCreated(QQmlEngine*);
53
52 QStringList m_arguments;54 QStringList m_arguments;
53 QQmlEngine* m_engine;55 QQmlEngine* m_engine;
54 QQuickWindow* m_window;56 QQuickWindow* m_window;
5557
=== added file 'src/app/webcontainer/AccountsPage.qml'
--- src/app/webcontainer/AccountsPage.qml 1970-01-01 00:00:00 +0000
+++ src/app/webcontainer/AccountsPage.qml 2014-06-02 11:59:43 +0000
@@ -0,0 +1,73 @@
1/*
2 * Copyright 2013-2014 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.0
20import Ubuntu.Components 0.1
21import webcontainer.private 0.1
22
23Page {
24 id: accountsPage
25
26 property alias accountProvider: accountsLogin.accountProvider
27 property alias applicationName: accountsLogin.applicationName
28 property var webappCookieStore: null
29
30 signal done()
31
32 visible: false
33 anchors.fill: parent
34
35 AccountsLoginPage {
36 id: accountsLogin
37
38 anchors.fill: parent
39
40 QtObject {
41 id: internal
42 function onMoved(result) {
43 webappCookieStore.moved.disconnect(internal.onMoved)
44 if (!result) {
45 console.error("Unable to move cookies")
46 }
47 accountsPage.done()
48 }
49 }
50
51 onDone: {
52 if (!accountsPage.visible)
53 return
54 if (!credentialsId) {
55 accountsPage.done()
56 return
57 }
58
59 if (webappCookieStore) {
60 var instance = onlineAccountStoreComponent.createObject(accountsLogin, {accountId: credentialsId})
61 webappCookieStore.moved.connect(internal.onMoved)
62 webappCookieStore.moveFrom(instance)
63 } else {
64 accountsPage.done()
65 }
66 }
67 }
68
69 Component {
70 id: onlineAccountStoreComponent
71 OnlineAccountsCookieStore { }
72 }
73}
074
=== modified file 'src/app/webcontainer/CMakeLists.txt'
--- src/app/webcontainer/CMakeLists.txt 2014-04-03 12:01:59 +0000
+++ src/app/webcontainer/CMakeLists.txt 2014-06-02 11:59:43 +0000
@@ -9,7 +9,11 @@
9set(WEBAPP_CONTAINER webapp-container)9set(WEBAPP_CONTAINER webapp-container)
1010
11set(WEBAPP_CONTAINER_SRC11set(WEBAPP_CONTAINER_SRC
12 chrome-cookie-store.cpp
13 cookie-store.cpp
14 online-accounts-cookie-store.cpp
12 webapp-container.cpp15 webapp-container.cpp
16 webkit-cookie-store.cpp
13 session-utils.cpp17 session-utils.cpp
14 url-pattern-utils.cpp18 url-pattern-utils.cpp
15)19)
@@ -18,7 +22,7 @@
1822
19target_link_libraries(${WEBAPP_CONTAINER} ${COMMONLIB})23target_link_libraries(${WEBAPP_CONTAINER} ${COMMONLIB})
2024
21qt5_use_modules(${WEBAPP_CONTAINER} Core Widgets Quick)25qt5_use_modules(${WEBAPP_CONTAINER} Core Widgets Quick Sql DBus)
2226
23install(TARGETS ${WEBAPP_CONTAINER}27install(TARGETS ${WEBAPP_CONTAINER}
24 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})28 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
2529
=== added file 'src/app/webcontainer/chrome-cookie-store.cpp'
--- src/app/webcontainer/chrome-cookie-store.cpp 1970-01-01 00:00:00 +0000
+++ src/app/webcontainer/chrome-cookie-store.cpp 2014-06-02 11:59:43 +0000
@@ -0,0 +1,218 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "chrome-cookie-store.h"
20
21#include <QDebug>
22#include <QFileInfo>
23#include <QNetworkCookie>
24#include <QSqlError>
25#include <QSqlQuery>
26#include <QStandardPaths>
27
28static int connectionCounter = 0;
29
30static qint64 dateTimeToChrome(const QDateTime &time)
31{
32 /* Chrome uses Mon Jan 01 00:00:00 UTC 1601 as the epoch, hence the
33 * magic number */
34 return (time.toMSecsSinceEpoch() + 11644473600000) * 1000;
35}
36
37static QDateTime dateTimeFromChrome(qint64 chromeTimeStamp)
38{
39 qint64 msecsSinceEpoch = chromeTimeStamp / 1000 - 11644473600000;
40 return QDateTime::fromMSecsSinceEpoch(msecsSinceEpoch);
41}
42
43ChromeCookieStore::ChromeCookieStore(QObject* parent):
44 CookieStore(parent)
45{
46 QString connectionName =
47 QString("chromeCookieStore-%1").arg(connectionCounter++);
48 m_db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
49}
50
51Cookies ChromeCookieStore::doGetCookies()
52{
53 Cookies cookies;
54 m_db.setDatabaseName(m_dbPath);
55
56 if (Q_UNLIKELY(!m_db.open())) {
57 qCritical() << "Could not open cookie database:" << m_dbPath
58 << m_db.lastError();
59 return cookies;
60 }
61
62 QSqlQuery q(m_db);
63 q.exec("SELECT host_key, name, value, path, expires_utc, secure, httponly, has_expires FROM cookies;");
64
65 while (q.next()) {
66 /* Build the cookie string from its parts */
67 QNetworkCookie cookie(q.value(1).toString().toUtf8(),
68 q.value(2).toString().toUtf8());
69 cookie.setSecure(q.value(5).toBool());
70 cookie.setHttpOnly(q.value(6).toBool());
71 if (q.value(7).toBool()) {
72 QDateTime expires = dateTimeFromChrome(q.value(4).toULongLong());
73 cookie.setExpirationDate(expires);
74 }
75 cookie.setDomain(q.value(0).toString());
76 cookie.setPath(q.value(3).toString());
77 cookies.append(cookie.toRawForm());
78 }
79
80 m_db.close();
81 return cookies;
82}
83
84QDateTime ChromeCookieStore::lastUpdateTimeStamp() const
85{
86 QFileInfo dbFileInfo(m_dbPath);
87 return dbFileInfo.lastModified();
88}
89
90bool ChromeCookieStore::createDb()
91{
92 if (Q_UNLIKELY(!m_db.transaction())) return false;
93
94 QSqlQuery q(m_db);
95 bool ok;
96 ok = q.exec("CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,"
97 "value LONGVARCHAR)");
98 if (Q_UNLIKELY(!ok)) {
99 m_db.rollback();
100 return false;
101 }
102
103 ok = q.exec("CREATE TABLE cookies (creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,"
104 "host_key TEXT NOT NULL,"
105 "name TEXT NOT NULL,"
106 "value TEXT NOT NULL,"
107 "path TEXT NOT NULL,"
108 "expires_utc INTEGER NOT NULL,"
109 "secure INTEGER NOT NULL,"
110 "httponly INTEGER NOT NULL,"
111 "last_access_utc INTEGER NOT NULL,"
112 "has_expires INTEGER NOT NULL DEFAULT 1,"
113 "persistent INTEGER NOT NULL DEFAULT 1,"
114 "priority INTEGER NOT NULL DEFAULT 1,"
115 "encrypted_value BLOB DEFAULT '')");
116 if (Q_UNLIKELY(!ok)) {
117 m_db.rollback();
118 return false;
119 }
120
121 ok = q.exec("CREATE INDEX domain ON cookies(host_key)");
122 if (Q_UNLIKELY(!ok)) {
123 m_db.rollback();
124 return false;
125 }
126
127 ok = q.exec("INSERT INTO meta (key, value) VALUES ('version', '7')");
128 if (Q_UNLIKELY(!ok)) {
129 m_db.rollback();
130 return false;
131 }
132
133 ok = q.exec("INSERT INTO meta (key, value) VALUES ('last_compatible_version', '5')");
134 if (Q_UNLIKELY(!ok)) {
135 m_db.rollback();
136 return false;
137 }
138
139 return m_db.commit();
140}
141
142bool ChromeCookieStore::doSetCookies(const Cookies& cookies)
143{
144 m_db.setDatabaseName(m_dbPath);
145
146 if (!m_db.open()) {
147 qCritical() << "Could not open cookie database:" <<
148 m_dbPath << m_db.lastError().text();
149 return false;
150 }
151
152 QSqlQuery q(m_db);
153 // Check whether the table already exists
154 q.exec("SELECT name FROM sqlite_master WHERE type='table' AND name='cookies'");
155 if (!q.next() && !createDb()) {
156 qCritical() << "Could not create cookie database:" <<
157 m_dbPath << m_db.lastError().text();
158 return false;
159 }
160
161 QList<QNetworkCookie> parsedCookies;
162
163 Q_FOREACH(const QByteArray &cookie, cookies) {
164 parsedCookies.append(QNetworkCookie::parseCookies(cookie));
165 }
166
167 q.prepare("INSERT INTO cookies (creation_utc,"
168 "host_key, name, value, path,"
169 "expires_utc, secure, httponly, last_access_utc,"
170 "has_expires, persistent, priority, encrypted_value) "
171 "VALUES (:creation_utc,"
172 ":host_key, :name, :value, :path,"
173 ":expires_utc, :secure, :httponly, :last_access_utc,"
174 ":has_expires, :persistent, :priority, :encrypted_value)");
175 Q_FOREACH(const QNetworkCookie &cookie, parsedCookies) {
176 q.bindValue(":creation_utc",
177 dateTimeToChrome(QDateTime::currentDateTimeUtc()));
178 q.bindValue(":host_key", cookie.domain());
179 q.bindValue(":name", cookie.name());
180 q.bindValue(":value", cookie.value());
181 q.bindValue(":path", cookie.path());
182 q.bindValue(":expires_utc",
183 dateTimeToChrome(cookie.expirationDate().toUTC()));
184 q.bindValue(":secure", cookie.isSecure());
185 q.bindValue(":httponly", cookie.isHttpOnly());
186 q.bindValue(":last_access_utc",
187 dateTimeToChrome(QDateTime::currentDateTimeUtc()));
188 q.bindValue(":has_expires", cookie.expirationDate().isValid());
189 q.bindValue(":persistent", true);
190 q.bindValue(":priority", 1);
191 q.bindValue(":encrypted_value", 1);
192 q.exec();
193 }
194
195 m_db.close();
196
197 return true;
198}
199
200void ChromeCookieStore::setDbPath(const QString &path)
201{
202 // If path is a URL, strip the initial "file://"
203 QString normalizedPath = path.startsWith("file://") ? path.mid(7) : path;
204
205 if (normalizedPath != m_dbPath) {
206 if (Q_UNLIKELY(!normalizedPath.startsWith('/'))) {
207 qWarning() << "Invalid database path (must be absolute):" << path;
208 return;
209 }
210 m_dbPath = normalizedPath;
211 Q_EMIT dbPathChanged();
212 }
213}
214
215QString ChromeCookieStore::dbPath () const
216{
217 return m_dbPath;
218}
0219
=== added file 'src/app/webcontainer/chrome-cookie-store.h'
--- src/app/webcontainer/chrome-cookie-store.h 1970-01-01 00:00:00 +0000
+++ src/app/webcontainer/chrome-cookie-store.h 2014-06-02 11:59:43 +0000
@@ -0,0 +1,53 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef CHROME_COOKIE_STORE_H
20#define CHROME_COOKIE_STORE_H
21
22#include "cookie-store.h"
23
24#include <QSqlDatabase>
25
26class ChromeCookieStore : public CookieStore
27{
28 Q_OBJECT
29 Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged)
30
31public:
32 ChromeCookieStore(QObject* parent = 0);
33
34 void setDbPath(const QString& path);
35 QString dbPath() const;
36
37 QDateTime lastUpdateTimeStamp() const Q_DECL_OVERRIDE;
38
39Q_SIGNALS:
40 void dbPathChanged();
41
42private:
43 virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
44 virtual bool doSetCookies(const Cookies& cookies) Q_DECL_OVERRIDE;
45
46 bool createDb();
47
48private:
49 QString m_dbPath;
50 QSqlDatabase m_db;
51};
52
53#endif // CHROME_COOKIE_STORE_H
054
=== renamed file 'src/app/webcontainer/cookiestore.cpp' => 'src/app/webcontainer/cookie-store.cpp'
--- src/app/webcontainer/cookiestore.cpp 2014-01-27 22:58:55 +0000
+++ src/app/webcontainer/cookie-store.cpp 2014-06-02 11:59:43 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2014 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -18,10 +18,10 @@
1818
19#include <QDebug>19#include <QDebug>
2020
21#include "cookiestore.h"21#include "cookie-store.h"
2222
23CookieStore::CookieStore(QObject *parent)23CookieStore::CookieStore(QObject* parent):
24 : QObject(parent)24 QObject(parent)
25{25{
26 qRegisterMetaType<Cookies>("Cookies");26 qRegisterMetaType<Cookies>("Cookies");
27}27}
@@ -31,19 +31,26 @@
31 return doGetCookies();31 return doGetCookies();
32}32}
3333
34void CookieStore::setCookies(Cookies cookies)34bool CookieStore::setCookies(const Cookies& cookies)
35{35{
36 doSetCookies(cookies);36 if (doSetCookies(cookies)) {
37 Q_EMIT cookiesChanged();
38 return true;
39 } else {
40 return false;
41 }
37}42}
3843
39Cookies CookieStore::doGetCookies()44Cookies CookieStore::doGetCookies()
40{45{
46 Q_UNIMPLEMENTED();
41 return Cookies();47 return Cookies();
42}48}
4349
44void CookieStore::doSetCookies(Cookies cookies)50bool CookieStore::doSetCookies(const Cookies& cookies)
45{51{
46 Q_UNUSED(cookies);52 Q_UNUSED(cookies);
53 Q_UNIMPLEMENTED();
47}54}
4855
49QDateTime CookieStore::lastUpdateTimeStamp() const56QDateTime CookieStore::lastUpdateTimeStamp() const
@@ -51,33 +58,32 @@
51 return _lastUpdateTimeStamp;58 return _lastUpdateTimeStamp;
52}59}
5360
54void CookieStore::updateLastUpdateTimestamp(const QDateTime & timestamp)61void CookieStore::updateLastUpdateTimestamp(const QDateTime& timestamp)
55{62{
56 _lastUpdateTimeStamp = timestamp;63 _lastUpdateTimeStamp = timestamp;
57}64}
5865
59void CookieStore::moveFrom(CookieStore *store)66void CookieStore::moveFrom(CookieStore* store)
60{67{
61 if (! store)68 if (Q_UNLIKELY(!store))
62 return;69 return;
6370
64 Cookies cookies =71 Cookies cookies = store->cookies();
65 store->cookies();72
6673 QDateTime lastRemoteCookieUpdate = store->lastUpdateTimeStamp();
67 QDateTime lastRemoteCookieUpdate =74 QDateTime lastLocalCookieUpdate = lastUpdateTimeStamp();
68 store->lastUpdateTimeStamp();75
6976 if (lastRemoteCookieUpdate.isValid() &&
70 QDateTime lastLocalCookieUpdate =77 lastLocalCookieUpdate.isValid() &&
71 lastUpdateTimeStamp();78 (lastRemoteCookieUpdate < lastLocalCookieUpdate))
72
73 if (lastRemoteCookieUpdate.isValid()
74 && lastLocalCookieUpdate.isValid()
75 && (lastRemoteCookieUpdate < lastLocalCookieUpdate))
76 {79 {
77 Q_EMIT moved(false);80 Q_EMIT moved(false);
78 return;81 return;
79 }82 }
8083
81 setCookies(cookies);84 if (setCookies(cookies)) {
85 Q_EMIT moved(true);
86 } else {
87 Q_EMIT moved(false);
88 }
82}89}
83
8490
=== renamed file 'src/app/webcontainer/cookiestore.h' => 'src/app/webcontainer/cookie-store.h'
--- src/app/webcontainer/cookiestore.h 2014-01-27 22:58:55 +0000
+++ src/app/webcontainer/cookie-store.h 2014-06-02 11:59:43 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2014 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -16,62 +16,50 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19#ifndef __COOKIESTORE_H__19#ifndef __COOKIE_STORE_H__
20#define __COOKIESTORE_H__20#define __COOKIE_STORE_H__
2121
22#include <QByteArray>
23#include <QDateTime>
24#include <QList>
22#include <QObject>25#include <QObject>
23#include <QtCore/QList>
24#include <QtCore/QString>
25#include <QDateTime>
26#include <QString>
27#include <QMap>
2826
29typedef QMap<QString, QString> Cookies;27typedef QList<QByteArray> Cookies;
30Q_DECLARE_METATYPE(Cookies);28Q_DECLARE_METATYPE(Cookies);
3129
3230
33class CookieStore : public QObject31class CookieStore : public QObject
34{32{
35 Q_OBJECT33 Q_OBJECT
36 Q_PROPERTY(Cookies cookies READ \34 Q_PROPERTY(Cookies cookies READ cookies WRITE setCookies \
37 cookies WRITE setCookies \
38 NOTIFY cookiesChanged)35 NOTIFY cookiesChanged)
39 Q_PROPERTY(QDateTime lastUpdateTimeStamp \36 Q_PROPERTY(QDateTime lastUpdateTimeStamp READ lastUpdateTimeStamp \
40 READ lastUpdateTimeStamp \
41 NOTIFY lastUpdateTimeStampChanged)37 NOTIFY lastUpdateTimeStampChanged)
4238
43public:39public:
4440 CookieStore(QObject* parent = 0);
45 CookieStore(QObject *parent = 0);41
4642 bool setCookies(const Cookies& cookies);
47 Cookies cookies();43 Cookies cookies();
48 void setCookies(Cookies);
4944
50 virtual QDateTime lastUpdateTimeStamp() const;45 virtual QDateTime lastUpdateTimeStamp() const;
5146
52 Q_INVOKABLE void moveFrom (CookieStore * store);47 Q_INVOKABLE void moveFrom(CookieStore* store);
5348
54Q_SIGNALS:49Q_SIGNALS:
55
56 void moved(bool);50 void moved(bool);
57 void cookiesChanged();51 void cookiesChanged();
58 void lastUpdateTimeStampChanged();52 void lastUpdateTimeStampChanged();
5953
60protected:54protected:
6155 void updateLastUpdateTimestamp(const QDateTime& timestamp);
62 void updateLastUpdateTimestamp(const QDateTime & timestamp);
63
6456
65private:57private:
66
67 virtual Cookies doGetCookies();58 virtual Cookies doGetCookies();
68 virtual void doSetCookies(Cookies);59 virtual bool doSetCookies(const Cookies& Cookies);
6960
70private:61private:
71
72 QDateTime _lastUpdateTimeStamp;62 QDateTime _lastUpdateTimeStamp;
73};63};
7464
7565#endif // __COOKIE_STORE_H__
76#endif // __COOKIESTORE_H__
77
7866
=== renamed file 'src/app/webcontainer/onlineaccountscookiestore.cpp' => 'src/app/webcontainer/online-accounts-cookie-store.cpp'
--- src/app/webcontainer/onlineaccountscookiestore.cpp 2014-01-27 22:58:55 +0000
+++ src/app/webcontainer/online-accounts-cookie-store.cpp 2014-06-02 11:59:43 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2013-2014 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19#include "onlineaccountscookiestore.h"19#include "online-accounts-cookie-store.h"
2020
21#include <QList>21#include <QList>
22#include <QVariant>22#include <QVariant>
@@ -44,15 +44,12 @@
44# define ONLINE_ACCOUNTS_COOKIE_STORE_METHOD "cookiesForIdentity"44# define ONLINE_ACCOUNTS_COOKIE_STORE_METHOD "cookiesForIdentity"
45#endif45#endif
4646
47class OnlineAccountsCookieStorePrivate : public QObject47class OnlineAccountsCookieStorePrivate
48{48{
49 Q_OBJECT
50
51public:49public:
52 OnlineAccountsCookieStorePrivate (QObject * parent = 0)50 OnlineAccountsCookieStorePrivate():
53 : QObject(parent),51 _id(0),
54 _id (0),52 m_connection(QDBusConnection::sessionBus())
55 m_connection (QDBusConnection::sessionBus())
56 {}53 {}
5754
58 quint32 _id;55 quint32 _id;
@@ -135,9 +132,8 @@
135 return qdbus_cast<Cookies>(arguments.front());132 return qdbus_cast<Cookies>(arguments.front());
136}133}
137134
138void OnlineAccountsCookieStore::doSetCookies(Cookies cookies)135bool OnlineAccountsCookieStore::doSetCookies(const Cookies& cookies)
139{136{
140 Q_UNUSED(cookies);137 Q_UNUSED(cookies);
138 return false;
141}139}
142
143#include "onlineaccountscookiestore.moc"
144140
=== renamed file 'src/app/webcontainer/onlineaccountscookiestore.h' => 'src/app/webcontainer/online-accounts-cookie-store.h'
--- src/app/webcontainer/onlineaccountscookiestore.h 2014-01-27 22:58:55 +0000
+++ src/app/webcontainer/online-accounts-cookie-store.h 2014-06-02 11:59:43 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2013-2014 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -16,10 +16,10 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19#ifndef ONLINEACCOUNTSCOOKIESTORE_H19#ifndef ONLINE_ACCOUNTS_COOKIE_STORE_H
20#define ONLINEACCOUNTSCOOKIESTORE_H20#define ONLINE_ACCOUNTS_COOKIE_STORE_H
2121
22#include "cookiestore.h"22#include "cookie-store.h"
2323
24class OnlineAccountsCookieStorePrivate;24class OnlineAccountsCookieStorePrivate;
2525
@@ -45,7 +45,7 @@
45private:45private:
4646
47 virtual Cookies doGetCookies() Q_DECL_OVERRIDE;47 virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
48 virtual void doSetCookies(Cookies) Q_DECL_OVERRIDE;48 virtual bool doSetCookies(const Cookies& cookies) Q_DECL_OVERRIDE;
4949
5050
51private:51private:
@@ -54,4 +54,4 @@
54 Q_DECLARE_PRIVATE(OnlineAccountsCookieStore)54 Q_DECLARE_PRIVATE(OnlineAccountsCookieStore)
55};55};
5656
57#endif // ONLINEACCOUNTSCOOKIESTORE_H57#endif // ONLINE_ACCOUNTS_COOKIE_STORE_H
5858
=== removed file 'src/app/webcontainer/sqlitecookiestore.cpp'
--- src/app/webcontainer/sqlitecookiestore.cpp 2014-02-07 16:44:50 +0000
+++ src/app/webcontainer/sqlitecookiestore.cpp 1970-01-01 00:00:00 +0000
@@ -1,99 +0,0 @@
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "sqlitecookiestore.h"
20
21#include <QSqlDatabase>
22#include <QSqlError>
23#include <QSqlQuery>
24#include <QFileInfo>
25#include <QStandardPaths>
26#include <QDebug>
27
28
29SqliteCookieStore::SqliteCookieStore(QObject *parent)
30 : CookieStore(parent)
31{}
32
33Cookies SqliteCookieStore::doGetCookies()
34{
35 return Cookies();
36}
37
38QDateTime SqliteCookieStore::lastUpdateTimeStamp() const
39{
40 QFileInfo dbFileInfo(getFullDbPathName ());
41 return dbFileInfo.lastModified();
42}
43
44void SqliteCookieStore::doSetCookies(Cookies cookies)
45{
46 QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
47 db.setDatabaseName (getFullDbPathName ());
48
49 if ( ! db.open())
50 {
51 qCritical() << "Could not open cookie database: " << getFullDbPathName() << db.lastError();
52 Q_EMIT moved(false);
53 return;
54 }
55
56 QSqlQuery q(db);
57 q.exec("CREATE TABLE IF NOT EXISTS cookies "
58 "(cookieId VARCHAR PRIMARY KEY, cookie BLOB)");
59 q.exec ("DELETE FROM cookies;");
60
61 q.prepare("INSERT INTO cookies (cookieId, cookie) "
62 "VALUES (:cookieId, :cookie)");
63
64 for (Cookies::const_iterator it = cookies.constBegin();
65 it != cookies.constEnd();
66 ++it)
67 {
68 q.bindValue(":cookieId", it.key());
69 q.bindValue(":cookie", it.value());
70
71 if ( ! q.exec())
72 {
73 qWarning() << "Couldn't insert cookie into DB"
74 << it.key();
75 }
76 }
77
78 Q_EMIT moved(true);
79}
80
81QString SqliteCookieStore::getFullDbPathName() const
82{
83 return QStandardPaths::standardLocations(QStandardPaths::HomeLocation)[0] + "/" + dbPath();
84}
85
86void SqliteCookieStore::setDbPath(const QString &path)
87{
88 if (path != m_dbPath)
89 {
90 m_dbPath = path;
91 Q_EMIT dbPathChanged();
92 }
93}
94
95QString SqliteCookieStore::dbPath () const
96{
97 return m_dbPath;
98}
99
1000
=== removed file 'src/app/webcontainer/sqlitecookiestore.h'
--- src/app/webcontainer/sqlitecookiestore.h 2014-01-27 22:58:55 +0000
+++ src/app/webcontainer/sqlitecookiestore.h 1970-01-01 00:00:00 +0000
@@ -1,58 +0,0 @@
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef SQLITECOOKIESTORE_H
20#define SQLITECOOKIESTORE_H
21
22#include "cookiestore.h"
23#include <QString>
24
25
26class SqliteCookieStore : public CookieStore
27{
28 Q_OBJECT
29 Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged)
30
31
32public:
33 SqliteCookieStore(QObject *parent = 0);
34
35 void setDbPath (const QString & path);
36 QString dbPath () const;
37
38 QDateTime lastUpdateTimeStamp() const Q_DECL_OVERRIDE;
39
40
41Q_SIGNALS:
42
43 void dbPathChanged();
44
45
46private:
47
48 virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
49 virtual void doSetCookies(Cookies) Q_DECL_OVERRIDE;
50
51 QString getFullDbPathName() const;
52
53
54private:
55 QString m_dbPath;
56};
57
58#endif // SQLITECOOKIESTORE_H
590
=== modified file 'src/app/webcontainer/webapp-container.cpp'
--- src/app/webcontainer/webapp-container.cpp 2014-05-08 16:51:08 +0000
+++ src/app/webcontainer/webapp-container.cpp 2014-06-02 11:59:43 +0000
@@ -19,8 +19,11 @@
19#include "config.h"19#include "config.h"
20#include "webapp-container.h"20#include "webapp-container.h"
2121
22#include "chrome-cookie-store.h"
23#include "online-accounts-cookie-store.h"
22#include "session-utils.h"24#include "session-utils.h"
23#include "url-pattern-utils.h"25#include "url-pattern-utils.h"
26#include "webkit-cookie-store.h"
2427
25// Qt28// Qt
26#include <QtCore/QCoreApplication>29#include <QtCore/QCoreApplication>
@@ -30,14 +33,17 @@
30#include <QtCore/QtGlobal>33#include <QtCore/QtGlobal>
31#include <QtCore/QRegularExpression>34#include <QtCore/QRegularExpression>
32#include <QtCore/QTextStream>35#include <QtCore/QTextStream>
33#include <QtQuick/QQuickWindow>
34#include <QtQml/QQmlComponent>36#include <QtQml/QQmlComponent>
35#include <QtQml/QQmlContext>37#include <QtQml/QQmlContext>
36#include <QtQml/QQmlEngine>38#include <QtQml/QQmlEngine>
39#include <QtQml>
40#include <QtQuick/QQuickWindow>
3741
38#include <QStandardPaths>42#include <QStandardPaths>
39#include <QSettings>43#include <QSettings>
4044
45static const char privateModuleUri[] = "webcontainer.private";
46
41namespace47namespace
42{48{
4349
@@ -103,6 +109,7 @@
103 m_window->setProperty("webappName", m_webappName);109 m_window->setProperty("webappName", m_webappName);
104 m_window->setProperty("backForwardButtonsVisible", m_backForwardButtonsVisible);110 m_window->setProperty("backForwardButtonsVisible", m_backForwardButtonsVisible);
105 m_window->setProperty("addressBarVisible", m_addressBarVisible);111 m_window->setProperty("addressBarVisible", m_addressBarVisible);
112 m_window->setProperty("accountProvider", m_accountProvider);
106113
107 qDebug() << "Using" << (m_withOxide ? "Oxide" : "QtWebkit") << "as the web engine backend";114 qDebug() << "Using" << (m_withOxide ? "Oxide" : "QtWebkit") << "as the web engine backend";
108 m_window->setProperty("oxide", m_withOxide);115 m_window->setProperty("oxide", m_withOxide);
@@ -134,6 +141,18 @@
134 }141 }
135}142}
136143
144void WebappContainer::qmlEngineCreated(QQmlEngine* engine)
145{
146 if (engine) {
147 qmlRegisterType<ChromeCookieStore>(privateModuleUri, 0, 1,
148 "ChromeCookieStore");
149 qmlRegisterType<WebkitCookieStore>(privateModuleUri, 0, 1,
150 "WebkitCookieStore");
151 qmlRegisterType<OnlineAccountsCookieStore>(privateModuleUri, 0, 1,
152 "OnlineAccountsCookieStore");
153 }
154}
155
137void WebappContainer::printUsage() const156void WebappContainer::printUsage() const
138{157{
139 QTextStream out(stdout);158 QTextStream out(stdout);
@@ -147,6 +166,7 @@
147 " [--webapp=name]"166 " [--webapp=name]"
148 " [--webappModelSearchPath=PATH]"167 " [--webappModelSearchPath=PATH]"
149 " [--webappUrlPatterns=URL_PATTERNS]"168 " [--webappUrlPatterns=URL_PATTERNS]"
169 " [--accountProvider=PROVIDER_NAME]"
150 " [--enable-back-forward]"170 " [--enable-back-forward]"
151 " [--enable-addressbar]"171 " [--enable-addressbar]"
152 " [--store-session-cookies]"172 " [--store-session-cookies]"
@@ -162,6 +182,7 @@
162 out << " --webapp=name try to match the webapp by name with an installed integration script" << endl;182 out << " --webapp=name try to match the webapp by name with an installed integration script" << endl;
163 out << " --webappModelSearchPath=PATH alter the search path for installed webapps and set it to PATH. PATH can be an absolute or path relative to CWD" << endl;183 out << " --webappModelSearchPath=PATH alter the search path for installed webapps and set it to PATH. PATH can be an absolute or path relative to CWD" << endl;
164 out << " --webappUrlPatterns=URL_PATTERNS list of comma-separated url patterns (wildcard based) that the webapp is allowed to navigate to" << endl;184 out << " --webappUrlPatterns=URL_PATTERNS list of comma-separated url patterns (wildcard based) that the webapp is allowed to navigate to" << endl;
185 out << " --accountProvider=PROVIDER_NAME Online account provider for the application if the application is to reuse a local account." << endl;
165 out << " --store-session-cookies store session cookies on disk" << endl;186 out << " --store-session-cookies store session cookies on disk" << endl;
166 out << "Chrome options (if none specified, no chrome is shown by default):" << endl;187 out << "Chrome options (if none specified, no chrome is shown by default):" << endl;
167 out << " --enable-back-forward enable the display of the back and forward buttons" << endl;188 out << " --enable-back-forward enable the display of the back and forward buttons" << endl;
@@ -190,6 +211,8 @@
190 QStringList includePatterns = tail.split(URL_PATTERN_SEPARATOR);211 QStringList includePatterns = tail.split(URL_PATTERN_SEPARATOR);
191 m_webappUrlPatterns = UrlPatternUtils::filterAndTransformUrlPatterns(includePatterns);212 m_webappUrlPatterns = UrlPatternUtils::filterAndTransformUrlPatterns(includePatterns);
192 }213 }
214 } else if (argument.startsWith("--accountProvider=")) {
215 m_accountProvider = argument.split("--accountProvider=")[1];
193 } else if (argument == "--store-session-cookies") {216 } else if (argument == "--store-session-cookies") {
194 m_storeSessionCookies = true;217 m_storeSessionCookies = true;
195 } else if (argument == "--enable-back-forward") {218 } else if (argument == "--enable-back-forward") {
196219
=== modified file 'src/app/webcontainer/webapp-container.h'
--- src/app/webcontainer/webapp-container.h 2014-05-08 16:51:08 +0000
+++ src/app/webcontainer/webapp-container.h 2014-06-02 11:59:43 +0000
@@ -34,6 +34,9 @@
3434
35 bool initialize();35 bool initialize();
3636
37protected:
38 void qmlEngineCreated(QQmlEngine *);
39
37private:40private:
38 virtual void printUsage() const;41 virtual void printUsage() const;
39 void parseCommandLine();42 void parseCommandLine();
@@ -44,6 +47,7 @@
44 QString m_webappName;47 QString m_webappName;
45 QString m_webappModelSearchPath;48 QString m_webappModelSearchPath;
46 QStringList m_webappUrlPatterns;49 QStringList m_webappUrlPatterns;
50 QString m_accountProvider;
47 bool m_withOxide;51 bool m_withOxide;
48 bool m_storeSessionCookies;52 bool m_storeSessionCookies;
49 bool m_backForwardButtonsVisible;53 bool m_backForwardButtonsVisible;
5054
=== modified file 'src/app/webcontainer/webapp-container.qml'
--- src/app/webcontainer/webapp-container.qml 2014-04-22 15:35:16 +0000
+++ src/app/webcontainer/webapp-container.qml 2014-06-02 11:59:43 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2013-2014 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -19,22 +19,27 @@
19import QtQuick 2.019import QtQuick 2.0
20import QtQuick.Window 2.020import QtQuick.Window 2.0
21import Ubuntu.Components 0.121import Ubuntu.Components 0.1
22import Ubuntu.Components.Extras.Browser 0.2
23import webcontainer.private 0.1
2224
23Window {25Window {
26 id: root
24 objectName: "webappContainer"27 objectName: "webappContainer"
2528
26 property alias developerExtrasEnabled: browser.developerExtrasEnabled29 property bool developerExtrasEnabled: false
2730
28 property alias backForwardButtonsVisible: browser.backForwardButtonsVisible31 property bool backForwardButtonsVisible: true
29 property alias addressBarVisible: browser.addressBarVisible32 property bool addressBarVisible: true
3033
31 property alias url: browser.url34 property string url: ""
32 property alias webappName: browser.webappName35 property string webappName: ""
33 property alias webappModelSearchPath: browser.webappModelSearchPath36 property string webappModelSearchPath: ""
34 property alias webappUrlPatterns: browser.webappUrlPatterns37 property var webappUrlPatterns
35 property alias oxide: browser.oxide38 property bool oxide: false
3639 property string accountProvider: ""
37 contentOrientation: browser.screenOrientation40 property var __webappCookieStore: null
41
42 contentOrientation: Screen.orientation
3843
39 width: 80044 width: 800
40 height: 60045 height: 600
@@ -42,24 +47,107 @@
42 title: {47 title: {
43 if (typeof(webappName) === 'string' && webappName.length !== 0) {48 if (typeof(webappName) === 'string' && webappName.length !== 0) {
44 return webappName49 return webappName
45 } else if (browser.title) {50 } else if (webappPageComponentLoader.item &&
51 webappPageComponentLoader.item.title) {
46 // TRANSLATORS: %1 refers to the current page’s title52 // TRANSLATORS: %1 refers to the current page’s title
47 return i18n.tr("%1 - Ubuntu Web Browser").arg(browser.title)53 return i18n.tr("%1 - Ubuntu Web Browser").arg(webappPageComponentLoader.item.title)
48 } else {54 } else {
49 return i18n.tr("Ubuntu Web Browser")55 return i18n.tr("Ubuntu Web Browser")
50 }56 }
51 }57 }
5258
53 WebApp {59 Loader {
54 id: browser60 id: webappPageComponentLoader
5561 anchors.fill: parent
56 property int screenOrientation: Screen.orientation62 }
5763
58 chromeless: !backForwardButtonsVisible && !addressBarVisible64 Component {
59 webbrowserWindow: webbrowserWindowProxy65 id: webappPageComponent
6066
61 anchors.fill: parent67 WebApp {
6268 id: browser
63 Component.onCompleted: i18n.domain = "webbrowser-app"69 addressBarVisible: root.addressBarVisible
70 backForwardButtonsVisible: root.backForwardButtonsVisible
71 developerExtrasEnabled: root.developerExtrasEnabled
72 oxide: root.oxide
73 url: root.url
74 webappModelSearchPath: root.webappModelSearchPath
75 webappName: root.webappName
76 webappUrlPatterns: root.webappUrlPatterns
77
78 anchors.fill: parent
79
80 chromeless: !backForwardButtonsVisible && !addressBarVisible
81 webbrowserWindow: webbrowserWindowProxy
82
83 Component.onCompleted: i18n.domain = "webbrowser-app"
84 }
85 }
86
87 Loader {
88 id: accountsPageComponentLoader
89 anchors.fill: parent
90 onStatusChanged: {
91 if (status == Loader.Error) {
92 // Happens on the desktop, if Ubuntu.OnlineAccounts.Client
93 // can't be imported
94 loadWebAppView()
95 } else if (status == Loader.Ready) {
96 item.visible = true
97 }
98 }
99 }
100
101 Connections {
102 target: accountsPageComponentLoader.item
103 onDone: loadWebAppView()
104 }
105
106 Component {
107 id: webkitCookieStoreComponent
108 WebkitCookieStore {
109 dbPath: dataLocation + "/.QtWebKit/cookies.db"
110 }
111 }
112
113 Component {
114 id: chromeCookieStoreComponent
115 ChromeCookieStore {
116 dbPath: dataLocation + "/cookies.sqlite"
117 }
118 }
119
120 Component.onCompleted: updateCurrentView()
121
122 onAccountProviderChanged: updateCurrentView();
123
124 function updateCurrentView() {
125 // check if we are to display the login view
126 // or directly switch to the webapp view
127 if (accountProvider.length !== 0) {
128 loadLoginView();
129 } else {
130 loadWebAppView();
131 }
132 }
133
134 function loadLoginView() {
135 if (!__webappCookieStore) {
136 var cookieStoreComponent =
137 oxide ? chromeCookieStoreComponent : webkitCookieStoreComponent
138 __webappCookieStore = cookieStoreComponent.createObject(this)
139 }
140 accountsPageComponentLoader.setSource("AccountsPage.qml", {
141 "accountProvider": accountProvider,
142 "applicationName": Qt.application.name,
143 "webappCookieStore": __webappCookieStore
144 })
145 }
146
147 function loadWebAppView() {
148 webappPageComponentLoader.sourceComponent = webappPageComponent;
149 if (accountsPageComponentLoader.item)
150 accountsPageComponentLoader.item.visible = false;
151 webappPageComponentLoader.item.visible = true;
64 }152 }
65}153}
66154
=== added file 'src/app/webcontainer/webkit-cookie-store.cpp'
--- src/app/webcontainer/webkit-cookie-store.cpp 1970-01-01 00:00:00 +0000
+++ src/app/webcontainer/webkit-cookie-store.cpp 2014-06-02 11:59:43 +0000
@@ -0,0 +1,120 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "webkit-cookie-store.h"
20
21#include <QDebug>
22#include <QFileInfo>
23#include <QNetworkCookie>
24#include <QSqlError>
25#include <QSqlQuery>
26#include <QStandardPaths>
27
28static int connectionCounter = 0;
29
30WebkitCookieStore::WebkitCookieStore(QObject* parent):
31 CookieStore(parent)
32{
33 QString connectionName =
34 QString("webkitCookieStore-%1").arg(connectionCounter++);
35 m_db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
36}
37
38Cookies WebkitCookieStore::doGetCookies()
39{
40 Cookies cookies;
41 m_db.setDatabaseName(m_dbPath);
42
43 if (!m_db.open()) {
44 qCritical() << "Could not open cookie database:" << m_dbPath << m_db.lastError();
45 return cookies;
46 }
47
48 QSqlQuery q(m_db);
49 q.exec("SELECT cookie FROM cookies;");
50
51 while (q.next()) {
52 cookies.append(q.value(0).toString().toUtf8());
53 }
54
55 m_db.close();
56 return cookies;
57}
58
59QDateTime WebkitCookieStore::lastUpdateTimeStamp() const
60{
61 QFileInfo dbFileInfo(m_dbPath);
62 return dbFileInfo.lastModified();
63}
64
65bool WebkitCookieStore::doSetCookies(const Cookies& cookies)
66{
67 m_db.setDatabaseName(m_dbPath);
68
69 if (!m_db.open()) {
70 qCritical() << "Could not open cookie database:" << m_dbPath << m_db.lastError();
71 return false;
72 }
73
74 QSqlQuery q(m_db);
75 q.exec("CREATE TABLE IF NOT EXISTS cookies "
76 "(cookieId VARCHAR PRIMARY KEY, cookie BLOB)");
77 q.exec ("DELETE FROM cookies;");
78
79 q.prepare("INSERT INTO cookies (cookieId, cookie) "
80 "VALUES (:cookieId, :cookie)");
81
82 Q_FOREACH(const QByteArray& cookie, cookies) {
83 /* The unique key is the hostname + the cookie name */
84 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie);
85 if (parsed.isEmpty()) continue;
86
87 const QNetworkCookie& c = parsed.first();
88 q.bindValue(":cookieId", c.domain() + c.name());
89 q.bindValue(":cookie", cookie);
90
91 if (!q.exec()) {
92 qWarning() << "Couldn't insert cookie into DB" << cookie;
93 }
94 }
95
96 m_db.close();
97
98 return true;
99}
100
101void WebkitCookieStore::setDbPath(const QString& path)
102{
103 // If path is a URL, strip the initial "file://"
104 QString normalizedPath = path.startsWith("file://") ? path.mid(7) : path;
105
106 if (path != m_dbPath) {
107 if (Q_UNLIKELY(!normalizedPath.startsWith('/'))) {
108 qWarning() << "Invalid database path (must be absolute):" << path;
109 return;
110 }
111 m_dbPath = path;
112 Q_EMIT dbPathChanged();
113 }
114}
115
116QString WebkitCookieStore::dbPath() const
117{
118 return m_dbPath;
119}
120
0121
=== added file 'src/app/webcontainer/webkit-cookie-store.h'
--- src/app/webcontainer/webkit-cookie-store.h 1970-01-01 00:00:00 +0000
+++ src/app/webcontainer/webkit-cookie-store.h 2014-06-02 11:59:43 +0000
@@ -0,0 +1,51 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef WEBKIT_COOKIE_STORE_H
20#define WEBKIT_COOKIE_STORE_H
21
22#include "cookie-store.h"
23
24#include <QSqlDatabase>
25
26class WebkitCookieStore : public CookieStore
27{
28 Q_OBJECT
29 Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged)
30
31public:
32 WebkitCookieStore(QObject* parent = 0);
33
34 void setDbPath(const QString& path);
35 QString dbPath() const;
36
37 QDateTime lastUpdateTimeStamp() const Q_DECL_OVERRIDE;
38
39Q_SIGNALS:
40 void dbPathChanged();
41
42private:
43 virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
44 virtual bool doSetCookies(const Cookies& cookies) Q_DECL_OVERRIDE;
45
46private:
47 QString m_dbPath;
48 QSqlDatabase m_db;
49};
50
51#endif // WEBKIT_COOKIE_STORE_H
052
=== modified file 'tests/unittests/CMakeLists.txt'
--- tests/unittests/CMakeLists.txt 2014-04-03 12:54:12 +0000
+++ tests/unittests/CMakeLists.txt 2014-06-02 11:59:43 +0000
@@ -10,3 +10,4 @@
10add_subdirectory(tabs-model)10add_subdirectory(tabs-model)
11add_subdirectory(bookmarks-model)11add_subdirectory(bookmarks-model)
12add_subdirectory(container-url-patterns)12add_subdirectory(container-url-patterns)
13add_subdirectory(cookie-store)
1314
=== added directory 'tests/unittests/cookie-store'
=== added file 'tests/unittests/cookie-store/CMakeLists.txt'
--- tests/unittests/cookie-store/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/unittests/cookie-store/CMakeLists.txt 2014-06-02 11:59:43 +0000
@@ -0,0 +1,11 @@
1set(TEST tst_CookieStoreTests)
2set(SOURCES
3 ${webapp-container_SOURCE_DIR}/chrome-cookie-store.cpp
4 ${webapp-container_SOURCE_DIR}/cookie-store.cpp
5 ${webapp-container_SOURCE_DIR}/webkit-cookie-store.cpp
6 tst_CookieStore.cpp
7)
8add_executable(${TEST} ${SOURCES})
9include_directories(${webapp-container_SOURCE_DIR})
10qt5_use_modules(${TEST} Core Network Sql Test)
11add_test(${TEST} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} -xunitxml -o ${TEST}.xml)
012
=== added file 'tests/unittests/cookie-store/tst_CookieStore.cpp'
--- tests/unittests/cookie-store/tst_CookieStore.cpp 1970-01-01 00:00:00 +0000
+++ tests/unittests/cookie-store/tst_CookieStore.cpp 2014-06-02 11:59:43 +0000
@@ -0,0 +1,189 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This file is part of webbrowser-app.
5 *
6 * webbrowser-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * webbrowser-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19// Qt
20#include <QtCore/QDir>
21#include <QtCore/QSet>
22#include <QtCore/QTemporaryDir>
23#include <QtNetwork/QNetworkCookie>
24#include <QtTest/QSignalSpy>
25#include <QtTest/QtTest>
26
27// local
28#include "chrome-cookie-store.h"
29#include "webkit-cookie-store.h"
30
31uint qHash(const QNetworkCookie &cookie, uint seed)
32{
33 return qHash(cookie.toRawForm(), seed);
34}
35
36class CookieStoreTest : public QObject
37{
38 Q_OBJECT
39
40private Q_SLOTS:
41 void testChromeProperties();
42 void testWebkitProperties();
43
44 void testChromeReadWrite_data() { setupCookieData(); }
45 void testWebkitReadWrite_data() { setupCookieData(); }
46 void testChromeReadWrite();
47 void testWebkitReadWrite();
48
49 void testMoving_data() { setupCookieData(); }
50 void testMoving();
51
52private:
53 void setupCookieData();
54 QSet<QNetworkCookie> parseCookies(const Cookies &rawCookies);
55};
56
57QSet<QNetworkCookie>
58CookieStoreTest::parseCookies(const Cookies &rawCookies)
59{
60 QList<QNetworkCookie> cookies;
61 Q_FOREACH(const QByteArray &rawCookie, rawCookies) {
62 cookies.append(QNetworkCookie::parseCookies(rawCookie));
63 }
64 return cookies.toSet();
65}
66
67void CookieStoreTest::testChromeProperties()
68{
69 QTemporaryDir tmpDir;
70 QVERIFY(tmpDir.isValid());
71 QTemporaryDir tmpDir2;
72 QVERIFY(tmpDir2.isValid());
73
74 ChromeCookieStore store;
75 QSignalSpy dbPathChanged(&store, SIGNAL(dbPathChanged()));
76
77 store.setProperty("dbPath", tmpDir.path());
78 QCOMPARE(dbPathChanged.count(), 1);
79 QCOMPARE(store.property("dbPath").toString(), tmpDir.path());
80 dbPathChanged.clear();
81
82 store.setProperty("dbPath", "file://" + tmpDir2.path());
83 QCOMPARE(dbPathChanged.count(), 1);
84 QCOMPARE(store.property("dbPath").toString(), tmpDir2.path());
85
86 QVERIFY(store.property("cookies").value<Cookies>().isEmpty());
87}
88
89void CookieStoreTest::testWebkitProperties()
90{
91 QTemporaryDir tmpDir;
92 QVERIFY(tmpDir.isValid());
93
94 WebkitCookieStore store;
95 QSignalSpy dbPathChanged(&store, SIGNAL(dbPathChanged()));
96
97 store.setProperty("dbPath", tmpDir.path());
98 QCOMPARE(dbPathChanged.count(), 1);
99 QCOMPARE(store.property("dbPath").toString(), tmpDir.path());
100
101 QVERIFY(store.property("cookies").value<Cookies>().isEmpty());
102}
103
104void CookieStoreTest::setupCookieData()
105{
106 QTest::addColumn<Cookies>("cookies");
107
108 Cookies cookies;
109
110 cookies << "LSID=DQAAAKEaem_vYg; Domain=docs.foo.com; Path=/accounts; "
111 "Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly";
112 QTest::newRow("Single cookie") << cookies;
113
114 cookies.clear();
115 cookies << "LSID=DQAAAKEaem_vYg; Domain=docs.foo.com; Path=/accounts; "
116 "Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly";
117 cookies << "HSID=AYQEVnDKrdst; Domain=.foo.com; Path=/; "
118 "Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly";
119 cookies << "SSID=Ap4PGTEq; Domain=foo.com; Path=/; "
120 "Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure";
121 cookies << "made_write_conn=1295214458; Path=/; Domain=.example.com";
122 QTest::newRow("Few cookies") << cookies;
123}
124
125void CookieStoreTest::testChromeReadWrite()
126{
127 QFETCH(Cookies, cookies);
128
129 QTemporaryDir tmpDir;
130 QVERIFY(tmpDir.isValid());
131 QDir testDir(tmpDir.path());
132
133 ChromeCookieStore store;
134 QSignalSpy cookiesChanged(&store, SIGNAL(cookiesChanged()));
135 store.setDbPath(testDir.filePath("cookies.db"));
136
137 QCOMPARE(cookiesChanged.count(), 0);
138 store.setProperty("cookies", QVariant::fromValue(cookies));
139 QCOMPARE(cookiesChanged.count(), 1);
140 Cookies readCookies = store.property("cookies").value<Cookies>();
141 QCOMPARE(parseCookies(readCookies), parseCookies(cookies));
142}
143
144void CookieStoreTest::testWebkitReadWrite()
145{
146 QFETCH(Cookies, cookies);
147
148 QTemporaryDir tmpDir;
149 QVERIFY(tmpDir.isValid());
150 QDir testDir(tmpDir.path());
151
152 WebkitCookieStore store;
153 QSignalSpy cookiesChanged(&store, SIGNAL(cookiesChanged()));
154 store.setDbPath(testDir.filePath("cookies.db"));
155
156 QCOMPARE(cookiesChanged.count(), 0);
157 store.setProperty("cookies", QVariant::fromValue(cookies));
158 QCOMPARE(cookiesChanged.count(), 1);
159 Cookies readCookies = store.property("cookies").value<Cookies>();
160 QCOMPARE(parseCookies(readCookies), parseCookies(cookies));
161}
162
163void CookieStoreTest::testMoving()
164{
165 QFETCH(Cookies, cookies);
166
167 QTemporaryDir tmpDir;
168 QVERIFY(tmpDir.isValid());
169 QDir testDir(tmpDir.path());
170
171 WebkitCookieStore webkitStore;
172 webkitStore.setDbPath(testDir.filePath("webkit.db"));
173 webkitStore.setProperty("cookies", QVariant::fromValue(cookies));
174
175 ChromeCookieStore chromeStore;
176 chromeStore.setDbPath(testDir.filePath("chrome.db"));
177
178 QSignalSpy moved(&chromeStore, SIGNAL(moved(bool)));
179 chromeStore.moveFrom(&webkitStore);
180
181 QCOMPARE(moved.count(), 1);
182 QCOMPARE(moved.at(0).at(0).toBool(), true);
183
184 Cookies movedCookies = chromeStore.property("cookies").value<Cookies>();
185 QCOMPARE(parseCookies(movedCookies), parseCookies(cookies));
186}
187
188QTEST_MAIN(CookieStoreTest)
189#include "tst_CookieStore.moc"

Subscribers

People subscribed via source and target branches

to status/vote changes: