Merge lp:~ken-vandine/content-hub/pasteboard into lp:content-hub

Proposed by Ken VanDine on 2016-06-02
Status: Merged
Approved by: Ken VanDine on 2016-08-25
Approved revision: 317
Merged at revision: 292
Proposed branch: lp:~ken-vandine/content-hub/pasteboard
Merge into: lp:content-hub
Prerequisite: lp:~ken-vandine/content-hub/qmlplugindump_noinstantiate
Diff against target: 1711 lines (+1245/-18) (has conflicts)
23 files modified
CMakeLists.txt (+4/-4)
debian/changelog (+9/-0)
examples/CMakeLists.txt (+1/-0)
examples/pasteboard/CMakeLists.txt (+55/-0)
examples/pasteboard/copy.cpp (+56/-0)
examples/pasteboard/paste.cpp (+59/-0)
import/Ubuntu/Content/CMakeLists.txt (+2/-0)
include/com/ubuntu/content/hub.h (+31/-4)
include/com/ubuntu/content/paste.h (+70/-0)
src/com/ubuntu/content/CMakeLists.txt (+12/-0)
src/com/ubuntu/content/detail/com.ubuntu.content.Paste.xml (+22/-0)
src/com/ubuntu/content/detail/com.ubuntu.content.Service.xml (+24/-0)
src/com/ubuntu/content/detail/paste.cpp (+132/-0)
src/com/ubuntu/content/detail/paste.h (+72/-0)
src/com/ubuntu/content/detail/service.cpp (+115/-6)
src/com/ubuntu/content/detail/service.h (+10/-0)
src/com/ubuntu/content/hub.cpp (+98/-2)
src/com/ubuntu/content/paste.cpp (+50/-0)
src/com/ubuntu/content/paste_p.h (+100/-0)
src/com/ubuntu/content/utils.cpp (+120/-2)
tests/acceptance-tests/CMakeLists.txt (+21/-0)
tests/acceptance-tests/app_hub_communication_paste.cpp (+138/-0)
tests/acceptance-tests/mimedata_test.cpp (+44/-0)
Text conflict in debian/changelog
To merge this branch: bzr merge lp:~ken-vandine/content-hub/pasteboard
Reviewer Review Type Date Requested Status
Tyler Hicks Approve on 2016-08-25
system-apps-ci-bot continuous-integration Needs Fixing on 2016-08-25
Daniel d'Andrada (community) 2016-06-02 Approve on 2016-08-03
PS Jenkins bot continuous-integration Pending
Review via email: mp+296352@code.launchpad.net

Commit message

Pasteboard implementation

Description of the change

To post a comment you must log in.

FAILED: Continuous integration, rev:287
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/20/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/917/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/917
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/827
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/827
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/827
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/828/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/828/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/20/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:288
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/22/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/920/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/920
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/830
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/830
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/830
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/830/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/830/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/22/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:289
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/24/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/995/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/995
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/896
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/896
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/896
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/890/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/890/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/24/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:290
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/25/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/996/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/996
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/897
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/897
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/897
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/891/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/891/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/25/rebuild

review: Needs Fixing (continuous-integration)
Daniel d'Andrada (dandrader) wrote :

In include/com/ubuntu/content/hub.h:

"""
    Q_INVOKABLE virtual Paste* create_paste(const QMimeData& data);
"""

Who owns the created Paste object? Is the caller free to delete it? Will that Paste object live forever, as long as Hub does? Please document it (I know other methods are undocumented and that sucks).

--------------------------------------------------

In include/com/ubuntu/content/paste.h:

Since Paste is public API, I would like to see it documented. Again, I know existing the API isn't, but we can do better than that.

"""
#include <com/ubuntu/content/item.h>
"""

What do you use from this header?

"""
namespace com
{
namespace ubuntu
{
namespace content
{
namespace detail
{
}
}
}
}
"""

You can remove this as you don't forward-declare anything in there.

"""
    Q_PROPERTY(int id READ id)
[...]
    Q_PROPERTY(QString source READ source)
"""

If those properties never change you should declare them as CONSTANT, like this:
Q_PROPERTY(QString source READ source CONSTANT)

"""
    enum State
    {
        created,
        charged,
        saved,
        collected
    };
"""

What do those states mean and why should user the care about them all?

"""
    Q_INVOKABLE virtual int id() const;
    Q_INVOKABLE virtual State state() const;
    Q_INVOKABLE virtual bool charge(const QMimeData& mimeData);
    Q_INVOKABLE virtual QMimeData* mimeData();
    Q_INVOKABLE virtual QString source() const;
"""

They don't have to (nor should) be Q_INVOKABLE if they're already getters or setters of Q_PROPERTIES. You added the Q_INVOKABLE so they could be called from QML, right?

"""
    //Q_PROPERTY(QMimeData mimeData READ mimeData WRITE charge)
"""

Why commented out?

"""
    Q_INVOKABLE virtual bool charge(const QMimeData& mimeData);
"""

Is the user supposed to call this? What's the use case? He can call Hub::create_paste(mimeData) and later change the paste contents passing a different QMimeData?

What's the use of Paste::source property?

review: Needs Information
Daniel d'Andrada (dandrader) wrote :

"""
    Q_INVOKABLE virtual const QMimeData* latest_paste_buf();
"""

That usually involves a round-trip through the D-Bus session + deserialization of the QMimeData, right?

So if I (the client) wanna get it asynchronously to avoid blocking my current thread (essentially because of the IPC involved), should I call this method from a separate worker thread? Or would it be simple for you to expose an async version of this on the client API?

review: Needs Information
Daniel d'Andrada (dandrader) wrote :

Hub is missing a signal to inform clients that the clibboard content has changed.

review: Needs Fixing
Ken VanDine (ken-vandine) wrote :
Download full text (3.2 KiB)

> In include/com/ubuntu/content/hub.h:
>
> """
> Q_INVOKABLE virtual Paste* create_paste(const QMimeData& data);
> """
>
> Who owns the created Paste object? Is the caller free to delete it? Will that
> Paste object live forever, as long as Hub does? Please document it (I know
> other methods are undocumented and that sucks).

Caller is free to delete it. The object will be available as long as the hub is running. Eventually we'll cache them to disk as well, so the stack will be restored.

>
> --------------------------------------------------
>
> In include/com/ubuntu/content/paste.h:
>
> Since Paste is public API, I would like to see it documented. Again, I know
> existing the API isn't, but we can do better than that.

Paste is technically a public API, but applications won't have direct access to the Paste object under confinement. Which reminds me why create_paste shouldn't return the Paste object. That should really just return a boolean. The Paste object will be used for the clipboard app.

>
> """
> #include <com/ubuntu/content/item.h>
> """
>
> What do you use from this header?

That can be removed

>
> """
> namespace com
> {
> namespace ubuntu
> {
> namespace content
> {
> namespace detail
> {
> }
> }
> }
> }
> """
>
> You can remove this as you don't forward-declare anything in there.
>
> """
> Q_PROPERTY(int id READ id)
> [...]
> Q_PROPERTY(QString source READ source)
> """
>
> If those properties never change you should declare them as CONSTANT, like
> this:
> Q_PROPERTY(QString source READ source CONSTANT)

Agreed, that would be better

>
> """
> enum State
> {
> created,
> charged,
> saved,
> collected
> };
> """
>
> What do those states mean and why should user the care about them all?

The user probably doesn't care, and we might just blow away the state property.

>
>
> """
> Q_INVOKABLE virtual int id() const;
> Q_INVOKABLE virtual State state() const;
> Q_INVOKABLE virtual bool charge(const QMimeData& mimeData);
> Q_INVOKABLE virtual QMimeData* mimeData();
> Q_INVOKABLE virtual QString source() const;
> """
>
> They don't have to (nor should) be Q_INVOKABLE if they're already getters or
> setters of Q_PROPERTIES. You added the Q_INVOKABLE so they could be called
> from QML, right?

Yes, although we probably only need the charge method to be callable from QML.

>
>
> """
> //Q_PROPERTY(QMimeData mimeData READ mimeData WRITE charge)
> """
>
> Why commented out?

I don't see this commented out, maybe you reviewed this before my last push.

>
> """
> Q_INVOKABLE virtual bool charge(const QMimeData& mimeData);
> """
>
> Is the user supposed to call this? What's the use case? He can call
> Hub::create_paste(mimeData) and later change the paste contents passing a
> different QMimeData?

Not directly, this is for use by the hub. Once the Paste object is charged, it can no longer be charged again. So the data won't change. For qtubuntu, you should only use the API exposed by hub.h.

>
> What's the use of Paste::source property?

This is the appId of the application that created the paste. We'll use this in the...

Read more...

Ken VanDine (ken-vandine) wrote :

> Hub is missing a signal to inform clients that the clibboard content has
> changed.

I'm adding property that returns a list of mimetypes on the stack which includes a changed signal.

FAILED: Continuous integration, rev:291
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/26/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1014/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1014
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/912
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/912
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/912
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/906/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/906/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/26/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:293
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/27/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1015/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1015
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/913
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/913
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/913
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/907/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/907/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/27/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:294
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/28/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1018/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1018
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/916
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/916
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/916
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/910/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/910/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/28/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:296
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/29/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1024/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1024
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/922
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/922
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/922
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/916/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/916/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/29/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:297
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/30/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1025/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1025
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/923
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/923
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/923
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/917/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/917/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/30/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:299
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/31/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1035/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1035
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/932
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/932
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/932
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/926/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/926/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/31/rebuild

review: Needs Fixing (continuous-integration)
Daniel d'Andrada (dandrader) wrote :

Made some modifications here:
http://bazaar.launchpad.net/~dandrader/content-hub/pasteboard/revision/285

- Fix unnecessary round trip and memory leak when fetching a Paste from the service
- Simplify D-Bus interface and traffic using ay instead of av
- Create separate sync and async versions of createPaste

Daniel d'Andrada (dandrader) wrote :

Code making use of it is here:
lp:~dandrader/qtubuntu/content-hub-clipboard

In src/ubuntumirclient/clipboard.cpp

Daniel d'Andrada (dandrader) wrote :

> Made some modifications here:
> http://bazaar.launchpad.net/~dandrader/content-hub/pasteboard/revision/285
>
> - Fix unnecessary round trip and memory leak when fetching a Paste from the
> service
> - Simplify D-Bus interface and traffic using ay instead of av
> - Create separate sync and async versions of createPaste

Oh, and added async versions for latestPaste() and pasteById() as well.

Ken VanDine (ken-vandine) wrote :

> > Made some modifications here:
> > http://bazaar.launchpad.net/~dandrader/content-hub/pasteboard/revision/285
> >
> > - Fix unnecessary round trip and memory leak when fetching a Paste from the
> > service
> > - Simplify D-Bus interface and traffic using ay instead of av
> > - Create separate sync and async versions of createPaste
>
> Oh, and added async versions for latestPaste() and pasteById() as well.

These changes are great! Only comment I have is I prefer making createPaste async and making the sync version something like createPasteSync. Makes it feel like the preferred function is the async one. But that's not a must for me, it's just more like I'm used to doing with gobject style code. What do you think is more common for Qt?

Daniel d'Andrada (dandrader) wrote :

On 26/07/2016 18:05, Ken VanDine wrote:
>>> Made some modifications here:
>>> http://bazaar.launchpad.net/~dandrader/content-hub/pasteboard/revision/285
>>>
>>> - Fix unnecessary round trip and memory leak when fetching a Paste from the
>>> service
>>> - Simplify D-Bus interface and traffic using ay instead of av
>>> - Create separate sync and async versions of createPaste
>> Oh, and added async versions for latestPaste() and pasteById() as well.
> These changes are great! Only comment I have is I prefer making createPaste async and making the sync version something like createPasteSync. Makes it feel like the preferred function is the async one. But that's not a must for me, it's just more like I'm used to doing with gobject style code. What do you think is more common for Qt?

I followed the convention used here:
http://doc.qt.io/qt-5/qdbusabstractinterface.html#public-functions

But I also prefer prefer the way you suggest. Made the change (same
revision number).

FAILED: Continuous integration, rev:300
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/32/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1049/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1049
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/946
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/946
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/946
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/937/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/937/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/32/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:301
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/33/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1050/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1050
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/947
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/947
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/947
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/938/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/938/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/33/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:302
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/36/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1064/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1063
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/959
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/959
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/959
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/950/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/950/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/36/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:303
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/37/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1068/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1068
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/965
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/965
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/965
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/956/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/956/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/37/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:305
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/38/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1073/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1073
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/970
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/970
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/970
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/959/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/959/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/38/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:306
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/39/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1074/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1074
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/971
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/971
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/971
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/960/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/960/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/39/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:308
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/40/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1099/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1099
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/996
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/996
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/996
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/985/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/985/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/40/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:309
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/41/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1102/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1102
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/999
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/999
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/999
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/988/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/988/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/41/rebuild

review: Needs Fixing (continuous-integration)

FAILED: Continuous integration, rev:311
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/42/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1104/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1104
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/1001
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/1001
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/1001
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/990/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/990/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/42/rebuild

review: Needs Fixing (continuous-integration)
Daniel d'Andrada (dandrader) wrote :

Looks good to me.

review: Approve
Daniel d'Andrada (dandrader) wrote :

CMakeLists.txt:79:set(CONTENT_HUB_VERSION_MAJOR 0)
CMakeLists.txt:80:set(CONTENT_HUB_VERSION_MINOR 0)
CMakeLists.txt:81:set(CONTENT_HUB_VERSION_PATCH 1)

Please update those to match the version in debian/changelog.

Otherwise things like that will fail:
pkg_check_modules(CONTENT_HUB libcontent-hub>=0.2 REQUIRED)

review: Needs Fixing
Daniel d'Andrada (dandrader) wrote :

CMakeLists.txt:79:set(CONTENT_HUB_VERSION_MAJOR 0)
CMakeLists.txt:80:set(CONTENT_HUB_VERSION_MINOR 0)
CMakeLists.txt:81:set(CONTENT_HUB_VERSION_PATCH 1)

Please update those to match the version in debian/changelog.

Otherwise things like that will fail:
pkg_check_modules(CONTENT_HUB libcontent-hub>=0.2 REQUIRED)

review: Needs Fixing
Daniel d'Andrada (dandrader) wrote :

Would be good also to move over the test for the serialization and deserialization code from lp:qtmir in tests/mirserver/Clipboard/clipboard_test.cpp.

Namely TEST(ClipboardTest, MimeDataSerialization)

Daniel d'Andrada (dandrader) wrote :

Made some changes in lp:~dandrader/content-hub/pasteboard revision 285. Let me know what you think.

It was really annoying me while testing on a laptop that content-hub was refusing to accept a copy from an app that unity8 was displaying (because ubuntu-app-launch wasn't tracking the running app for some reason). That cannot happen and would be a regression since it works with the current clipboard implementation.

FAILED: Continuous integration, rev:312
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/43/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1124/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1124
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/1019
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/1019
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/1019
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1008/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1008/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/43/rebuild

review: Needs Fixing (continuous-integration)
Ken VanDine (ken-vandine) wrote :

> CMakeLists.txt:79:set(CONTENT_HUB_VERSION_MAJOR 0)
> CMakeLists.txt:80:set(CONTENT_HUB_VERSION_MINOR 0)
> CMakeLists.txt:81:set(CONTENT_HUB_VERSION_PATCH 1)
>
> Please update those to match the version in debian/changelog.
>
> Otherwise things like that will fail:
> pkg_check_modules(CONTENT_HUB libcontent-hub>=0.2 REQUIRED)

Done

Ken VanDine (ken-vandine) wrote :

> Would be good also to move over the test for the serialization and
> deserialization code from lp:qtmir in
> tests/mirserver/Clipboard/clipboard_test.cpp.
>
> Namely TEST(ClipboardTest, MimeDataSerialization)

Done

FAILED: Continuous integration, rev:313
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/44/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1127/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1127
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/1020
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/1020
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/1020
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1009/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1009/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/44/rebuild

review: Needs Fixing (continuous-integration)
Ken VanDine (ken-vandine) wrote :

> Made some changes in lp:~dandrader/content-hub/pasteboard revision 285. Let me
> know what you think.
>
> It was really annoying me while testing on a laptop that content-hub was
> refusing to accept a copy from an app that unity8 was displaying (because
> ubuntu-app-launch wasn't tracking the running app for some reason). That
> cannot happen and would be a regression since it works with the current
> clipboard implementation.

This is fine, ultimately I hope it'll be a real corner case. But it's really not that big of a deal if it fails.

Daniel d'Andrada (dandrader) wrote :

Thanks!

review: Approve

FAILED: Continuous integration, rev:314
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/45/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1128/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1128
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/1021
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/1021
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/1021
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1010/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1010/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/45/rebuild

review: Needs Fixing (continuous-integration)
Tyler Hicks (tyhicks) wrote :

Ubuntu Security would like to review this change. We were involved in the early design stages and were awaiting an update to the design doc for this feature. The design doc that we have access to is still based on an old design that doesn't match this implementation. We're blocked until the doc can be updated.

review: Needs Information
Daniel d'Andrada (dandrader) wrote :

Wrote focused surface verification based on persistent surface ids here:
http://bazaar.launchpad.net/~dandrader/content-hub/pasteboard/revision/315

315. By Ken VanDine on 2016-08-24

merged trunk

316. By Ken VanDine on 2016-08-24

Daniel d'Andrada 2016-08-23 Authenticate using surface ids instead of process ids

FAILED: Continuous integration, rev:316
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/46/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1286/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1286
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/1152
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/1152
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/1152
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1135/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1135/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1135/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1135/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1135/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1135/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1135/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1135/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1135
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1135/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/46/rebuild

review: Needs Fixing (continuous-integration)
Daniel d'Andrada (dandrader) wrote :

The client is blocking on startup waiting for PasteFormats value.

Wrote a fix for it here:
http://bazaar.launchpad.net/~dandrader/content-hub/pasteboard/revision/317

There I've also reduced D-Bus round trips by already sending the paste formats on its changed signal.

317. By Ken VanDine on 2016-08-25

Daniel d'Andrada 2016-08-24 Improve PasteFormatsChanged

FAILED: Continuous integration, rev:317
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/48/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1314/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1314
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/1178
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/1178
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/1178
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1158
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1158/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1158
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1158/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1158/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1158
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1158/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1158
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1158/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1158
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1158/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1158
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1158/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1158
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1158/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1158/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-content-hub-ci/48/rebuild

review: Needs Fixing (continuous-integration)
Tyler Hicks (tyhicks) wrote :

I gave this a quick review. It was more of a design review than a detailed code review.

The security of this design is rooted in the random surface ID created by Mir. That surface ID must be randomly generated and of significant size so that bruteforces of the ID is not feasible. I'm told that the ID is randomly generated and evenly distributed throughout a full 128 bits. That should be sufficient.

A future improvement that I'd like to see is a penalty after a number of incorrect surface ID guesses so that a malicious app cannot simply brute force the 128 bit space without any negative side effects. The penalty could be time based, where the pasteboard doesn't return back for several seconds. There are other options, as well.

I had some trouble understanding the intent behind the usage of the APP_ID in the merge proposal. Ken tells me that it is for a future design when there is a pasteboard UI so that the user will be prompted with the APP_ID of the application requesting access to the paste buffer. Since the APP_ID isn't used right now, I'm not concerned, but I'd like to understand more about how the APP_ID is being retrieved before we start prompting users. I'd prefer that we use the APP_ID directly from the D-Bus daemon via the GetConnectionCredentials bus method:

  https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-get-connection-credentials

Thanks for working towards a secure copy and paste solution. I look forward to this design being improved on in the future with the introduction of a pasteboard UI.

review: Approve
Tyler Hicks (tyhicks) wrote :

Upon thinking about my suggestion, for a future enhancement, of a penalty to be handed out upon a number of wrong surface ID guesses, I realized that content-hub is not the correct place to implement the penalty. Mir clients will be able to call isSurfaceFocused() themselves to brute force the surface ID. Once they find a valid surface ID, then they can simply pass that to the content-hub. Therefore, the penalty mechanism would need to be implemented in Mir itself.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-09-23 14:45:09 +0000
3+++ CMakeLists.txt 2016-08-25 13:22:47 +0000
4@@ -24,8 +24,8 @@
5 include (EnableCoverageReport)
6 include (GSettings)
7
8-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -pedantic -Wextra -fPIC -pthread")
9-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -pedantic -Wextra -fPIC -pthread -Wno-unused-function")
10+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -pthread")
11+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing -fPIC -pthread -Wno-unused-function")
12 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
13
14 # Workaround for libexecdir on debian
15@@ -77,8 +77,8 @@
16 add_definitions(-DI18N_DOMAIN="${GETTEXT_PACKAGE}")
17
18 set(CONTENT_HUB_VERSION_MAJOR 0)
19-set(CONTENT_HUB_VERSION_MINOR 0)
20-set(CONTENT_HUB_VERSION_PATCH 1)
21+set(CONTENT_HUB_VERSION_MINOR 2)
22+set(CONTENT_HUB_VERSION_PATCH 0)
23 set(CONTENT_HUB_VERSION "${CONTENT_HUB_VERSION_MAJOR}.${CONTENT_HUB_VERSION_MINOR}.${CONTENT_HUB_VERSION_PATCH}")
24
25 set(QML_API_VERSION_MAJOR 1)
26
27=== modified file 'debian/changelog'
28--- debian/changelog 2016-08-22 17:01:38 +0000
29+++ debian/changelog 2016-08-25 13:22:47 +0000
30@@ -1,9 +1,18 @@
31+<<<<<<< TREE
32 content-hub (0.1+16.10.20160822-0ubuntu1) yakkety; urgency=medium
33
34 * No change rebuild for UAL ABI change
35
36 -- Ted Gould <ted@gould.cx> Mon, 22 Aug 2016 17:01:38 +0000
37
38+=======
39+content-hub (0.2-0ubuntu1) UNRELEASED; urgency=medium
40+
41+ * Pasteboard implementation
42+
43+ -- Ken VanDine <ken.vandine@canonical.com> Wed, 27 Jul 2016 10:49:05 -0400
44+
45+>>>>>>> MERGE-SOURCE
46 content-hub (0.1+16.10.20160809-0ubuntu1) yakkety; urgency=medium
47
48 * build dep on qttools5-dev-tools for qdoc
49
50=== modified file 'examples/CMakeLists.txt'
51--- examples/CMakeLists.txt 2013-08-27 22:15:29 +0000
52+++ examples/CMakeLists.txt 2016-08-25 13:22:47 +0000
53@@ -16,3 +16,4 @@
54
55 add_subdirectory(importer)
56 add_subdirectory(exporter)
57+add_subdirectory(pasteboard)
58
59=== added directory 'examples/pasteboard'
60=== added file 'examples/pasteboard/CMakeLists.txt'
61--- examples/pasteboard/CMakeLists.txt 1970-01-01 00:00:00 +0000
62+++ examples/pasteboard/CMakeLists.txt 2016-08-25 13:22:47 +0000
63@@ -0,0 +1,55 @@
64+# Copyright © 2016 Canonical Ltd.
65+#
66+# This program is free software: you can redistribute it and/or modify
67+# it under the terms of the GNU General Public License version 3 as
68+# published by the Free Software Foundation.
69+#
70+# This program is distributed in the hope that it will be useful,
71+# but WITHOUT ANY WARRANTY; without even the implied warranty of
72+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73+# GNU General Public License for more details.
74+#
75+# You should have received a copy of the GNU General Public License
76+# along with this program. If not, see <http://www.gnu.org/licenses/>.
77+#
78+# Authored by: Ken VanDine <ken.vandine@canonical.com>
79+
80+include_directories(${CMAKE_CURRENT_BINARY_DIR})
81+
82+add_executable(
83+ copy-to-pasteboard
84+
85+ copy.cpp
86+)
87+
88+qt5_use_modules(copy-to-pasteboard Core Gui DBus)
89+
90+set_target_properties(
91+ copy-to-pasteboard
92+ PROPERTIES
93+ AUTOMOC TRUE
94+)
95+
96+target_link_libraries(
97+ copy-to-pasteboard
98+ content-hub
99+)
100+
101+add_executable(
102+ paste-from-pasteboard
103+
104+ paste.cpp
105+)
106+
107+qt5_use_modules(paste-from-pasteboard Core Gui DBus)
108+
109+set_target_properties(
110+ paste-from-pasteboard
111+ PROPERTIES
112+ AUTOMOC TRUE
113+)
114+
115+target_link_libraries(
116+ paste-from-pasteboard
117+ content-hub
118+)
119
120=== added file 'examples/pasteboard/copy.cpp'
121--- examples/pasteboard/copy.cpp 1970-01-01 00:00:00 +0000
122+++ examples/pasteboard/copy.cpp 2016-08-25 13:22:47 +0000
123@@ -0,0 +1,56 @@
124+/*
125+ * Copyright (C) 2016 Canonical, Ltd.
126+ *
127+ * This program is free software; you can redistribute it and/or modify
128+ * it under the terms of the GNU General Public License as published by
129+ * the Free Software Foundation; version 3.
130+ *
131+ * This program is distributed in the hope that it will be useful,
132+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
133+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
134+ * GNU General Public License for more details.
135+ *
136+ * You should have received a copy of the GNU General Public License
137+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
138+ *
139+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
140+ */
141+
142+#include <QCoreApplication>
143+#include <QDebug>
144+#include <QStringList>
145+#include <com/ubuntu/content/hub.h>
146+#include <com/ubuntu/content/paste.h>
147+
148+namespace cuc = com::ubuntu::content;
149+
150+int main(int argc, char *argv[])
151+{
152+ QCoreApplication a(argc, argv);
153+ if (qgetenv("APP_ID").isEmpty()) {
154+ qputenv("APP_ID", "copy-to-pasteboard");
155+ }
156+
157+ QString text("Some text");
158+
159+ if (a.arguments().size() > 1)
160+ text = a.arguments().at(1);
161+
162+ QMimeData data;
163+ data.setText(text);
164+
165+ auto hub = cuc::Hub::Client::instance();
166+
167+ /* Won't work unless you disable the surface Id verification with CONTENT_HUB_TESTING=1 env var
168+ To get the surface Id of a MirSurface in a real GUI app you should to it like the following:
169+ MirPersistentId* mirPermaId = mir_surface_request_persistent_id_sync(mirSurface);
170+ QString surfaceId = mir_persistent_id_as_string(mirPermaId);
171+ mir_persistent_id_release(mirPermaId);
172+ */
173+ QString surfaceId("some-bogus-fake-surface-id");
174+
175+ hub->createPasteSync(surfaceId, const_cast<const QMimeData&>(data));
176+
177+ qDebug() << text;
178+ qDebug() << hub->pasteFormats();
179+}
180
181=== added file 'examples/pasteboard/paste.cpp'
182--- examples/pasteboard/paste.cpp 1970-01-01 00:00:00 +0000
183+++ examples/pasteboard/paste.cpp 2016-08-25 13:22:47 +0000
184@@ -0,0 +1,59 @@
185+/*
186+ * Copyright (C) 2016 Canonical, Ltd.
187+ *
188+ * This program is free software; you can redistribute it and/or modify
189+ * it under the terms of the GNU General Public License as published by
190+ * the Free Software Foundation; version 3.
191+ *
192+ * This program is distributed in the hope that it will be useful,
193+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
194+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
195+ * GNU General Public License for more details.
196+ *
197+ * You should have received a copy of the GNU General Public License
198+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
199+ *
200+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
201+ */
202+
203+#include <QCoreApplication>
204+#include <QStringList>
205+#include <com/ubuntu/content/hub.h>
206+
207+namespace cuc = com::ubuntu::content;
208+
209+int main(int argc, char *argv[])
210+{
211+ QCoreApplication a(argc, argv);
212+ if (qgetenv("APP_ID").isEmpty()) {
213+ qputenv("APP_ID", "paste-from-pasteboard");
214+ }
215+
216+ QString id("latest");
217+
218+ if (a.arguments().size() > 1)
219+ id = a.arguments().at(1);
220+
221+ auto hub = cuc::Hub::Client::instance();
222+
223+ /* Won't work unless you disable the surface Id verification with CONTENT_HUB_TESTING=1 env var
224+ To get the surface Id of a MirSurface in a real GUI app you should to it like the following:
225+ MirPersistentId* mirPermaId = mir_surface_request_persistent_id_sync(mirSurface);
226+ QString surfaceId = mir_persistent_id_as_string(mirPermaId);
227+ mir_persistent_id_release(mirPermaId);
228+ */
229+ QString surfaceId("some-bogus-fake-surface-id");
230+
231+ QMimeData *mimeData = nullptr;
232+ if (id == "latest") {
233+ mimeData = hub->latestPaste(surfaceId);
234+ } else {
235+ mimeData = hub->pasteById(surfaceId, id.toInt());
236+ }
237+ if (mimeData) {
238+ qDebug() << id << ":" << mimeData->text();
239+ } else {
240+ qDebug() << "content-hub returned no mimedata.";
241+ }
242+ return 0;
243+}
244
245=== modified file 'import/Ubuntu/Content/CMakeLists.txt'
246--- import/Ubuntu/Content/CMakeLists.txt 2016-05-18 17:18:55 +0000
247+++ import/Ubuntu/Content/CMakeLists.txt 2016-08-25 13:22:47 +0000
248@@ -39,6 +39,7 @@
249 ${NIH_DBUS_INCLUDE_DIRS}
250 ${DBUS_INCLUDE_DIRS}
251 ${GLIB_INCLUDE_DIRS}
252+ ${UBUNTU_LAUNCH_INCLUDE_DIRS}
253 )
254
255 set(PLUGIN_HDRS
256@@ -81,6 +82,7 @@
257 ${NIH_LIBRARIES}
258 ${NIH_DBUS_LIBRARIES}
259 ${GLIB_LIBRARIES}
260+ ${UBUNTU_LAUNCH_LDFLAGS}
261 )
262
263 install(TARGETS ${PLUGIN} DESTINATION ${CONTENT_HUB_IMPORTS_DIR})
264
265=== modified file 'include/com/ubuntu/content/hub.h'
266--- include/com/ubuntu/content/hub.h 2015-09-29 13:15:58 +0000
267+++ include/com/ubuntu/content/hub.h 2016-08-25 13:22:47 +0000
268@@ -1,5 +1,5 @@
269 /*
270- * Copyright © 2013 Canonical Ltd.
271+ * Copyright © 2013,2016 Canonical Ltd.
272 *
273 * This program is free software: you can redistribute it and/or modify
274 * it under the terms of the GNU Lesser General Public License version 3 as
275@@ -23,7 +23,10 @@
276 #include <com/ubuntu/content/type.h>
277
278 #include <QObject>
279-#include <QVector>
280+#include <QMimeData>
281+
282+class QStringList;
283+class QDBusPendingCall;
284
285 namespace com
286 {
287@@ -38,6 +41,7 @@
288 class Hub : public QObject
289 {
290 Q_OBJECT
291+ Q_PROPERTY(QStringList pasteFormats READ pasteFormats NOTIFY pasteFormatsChanged)
292
293 public:
294 struct Client
295@@ -66,11 +70,34 @@
296 Q_INVOKABLE virtual Transfer* create_share_to_peer_for_type(Peer peer, Type type);
297 Q_INVOKABLE virtual bool has_pending(QString peer_id);
298 Q_INVOKABLE virtual Peer peer_for_app_id(QString app_id);
299-
300+
301+ ///
302+ // Copy & Paste
303+
304+ QDBusPendingCall createPaste(const QString &surfaceId, const QMimeData& data);
305+
306+ QDBusPendingCall requestLatestPaste(const QString &surfaceId);
307+ QDBusPendingCall requestPasteById(const QString &surfaceId, int pasteId);
308+ QMimeData* paste(QDBusPendingCall requestPeply);
309+
310+ // synchronous versions
311+ bool createPasteSync(const QString &surfaceId, const QMimeData& data);
312+ QMimeData* latestPaste(const QString &surfaceId);
313+ QMimeData* pasteById(const QString &surfaceId, int id);
314+
315+ QStringList pasteFormats();
316+
317+ Q_SIGNALS:
318+ void pasteFormatsChanged();
319+ void pasteboardChanged();
320+
321+ private Q_SLOTS:
322+ void onPasteFormatsChanged(const QStringList &);
323 protected:
324 Hub(QObject* = nullptr);
325-
326+
327 private:
328+ void requestPasteFormats();
329 struct Private;
330 QScopedPointer<Private> d;
331 bool eventFilter(QObject *obj, QEvent *event);
332
333=== added file 'include/com/ubuntu/content/paste.h'
334--- include/com/ubuntu/content/paste.h 1970-01-01 00:00:00 +0000
335+++ include/com/ubuntu/content/paste.h 2016-08-25 13:22:47 +0000
336@@ -0,0 +1,70 @@
337+/*
338+ * Copyright © 2016 Canonical Ltd.
339+ *
340+ * This program is free software: you can redistribute it and/or modify
341+ * it under the terms of the GNU Lesser General Public License version 3 as
342+ * published by the Free Software Foundation.
343+ *
344+ * This program is distributed in the hope that it will be useful,
345+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
346+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
347+ * GNU Lesser General Public License for more details.
348+ *
349+ * You should have received a copy of the GNU Lesser General Public License
350+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
351+ *
352+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
353+ */
354+#ifndef COM_UBUNTU_CONTENT_PASTE_H_
355+#define COM_UBUNTU_CONTENT_PASTE_H_
356+
357+#include <QObject>
358+#include <QSharedPointer>
359+#include <QMimeData>
360+#include <QString>
361+
362+namespace com
363+{
364+namespace ubuntu
365+{
366+namespace content
367+{
368+
369+class Paste : public QObject
370+{
371+ Q_OBJECT
372+ Q_ENUMS(State)
373+ Q_PROPERTY(int id READ id)
374+ Q_PROPERTY(QString source READ source)
375+
376+ public:
377+ enum State
378+ {
379+ created,
380+ charged,
381+ saved,
382+ collected
383+ };
384+
385+ Paste(const Paste&) = delete;
386+ virtual ~Paste();
387+
388+ Paste& operator=(const Paste&) = delete;
389+
390+ Q_INVOKABLE virtual int id() const;
391+ Q_INVOKABLE virtual QMimeData* mimeData();
392+ Q_INVOKABLE virtual QString source() const;
393+
394+ private:
395+ struct Private;
396+ friend struct Private;
397+ friend class Hub;
398+ QSharedPointer<Private> d;
399+
400+ Paste(const QSharedPointer<Private>&, QObject* parent = nullptr);
401+};
402+}
403+}
404+}
405+
406+#endif // COM_UBUNTU_CONTENT_PASTE_H_
407
408=== modified file 'src/com/ubuntu/content/CMakeLists.txt'
409--- src/com/ubuntu/content/CMakeLists.txt 2015-09-23 14:45:09 +0000
410+++ src/com/ubuntu/content/CMakeLists.txt 2016-08-25 13:22:47 +0000
411@@ -47,6 +47,13 @@
412 detail/transfer.h com::ubuntu::content::detail::Transfer)
413
414 qt5_add_dbus_interface(
415+ CONTENT_PASTE_STUB ${CMAKE_CURRENT_SOURCE_DIR}/detail/com.ubuntu.content.Paste.xml
416+ ContentPasteInterface)
417+qt5_add_dbus_adaptor(
418+ CONTENT_PASTE_SKELETON ${CMAKE_CURRENT_SOURCE_DIR}/detail/com.ubuntu.content.Paste.xml
419+ detail/paste.h com::ubuntu::content::detail::Paste)
420+
421+qt5_add_dbus_interface(
422 CONTENT_HANDLER_STUB ${CMAKE_CURRENT_SOURCE_DIR}/detail/com.ubuntu.content.Handler.xml
423 ContentHandlerInterface)
424 qt5_add_dbus_adaptor(
425@@ -56,6 +63,7 @@
426 qt5_wrap_cpp(CONTENT_HUB_MOCS ${CMAKE_SOURCE_DIR}/include/com/ubuntu/content/hub.h)
427 qt5_wrap_cpp(CONTENT_HUB_MOCS ${CMAKE_SOURCE_DIR}/include/com/ubuntu/content/import_export_handler.h)
428 qt5_wrap_cpp(CONTENT_HUB_MOCS ${CMAKE_SOURCE_DIR}/include/com/ubuntu/content/item.h)
429+qt5_wrap_cpp(CONTENT_HUB_MOCS ${CMAKE_SOURCE_DIR}/include/com/ubuntu/content/paste.h)
430 qt5_wrap_cpp(CONTENT_HUB_MOCS ${CMAKE_SOURCE_DIR}/include/com/ubuntu/content/peer.h)
431 qt5_wrap_cpp(CONTENT_HUB_MOCS ${CMAKE_SOURCE_DIR}/include/com/ubuntu/content/store.h)
432 qt5_wrap_cpp(CONTENT_HUB_MOCS ${CMAKE_SOURCE_DIR}/include/com/ubuntu/content/transfer.h)
433@@ -67,6 +75,7 @@
434 hub.cpp
435 import_export_handler.cpp
436 item.cpp
437+ paste.cpp
438 peer.cpp
439 store.cpp
440 transfer.cpp
441@@ -75,6 +84,7 @@
442 debug.cpp
443
444 detail/app_manager.cpp
445+ detail/paste.cpp
446 detail/service.cpp
447 detail/transfer.cpp
448 detail/handler.cpp
449@@ -83,6 +93,8 @@
450 ${CONTENT_HUB_MOCS}
451 ${CONTENT_SERVICE_STUB}
452 ${CONTENT_SERVICE_SKELETON}
453+ ${CONTENT_PASTE_STUB}
454+ ${CONTENT_PASTE_SKELETON}
455 ${CONTENT_TRANSFER_STUB}
456 ${CONTENT_TRANSFER_SKELETON}
457 ${CONTENT_HANDLER_STUB}
458
459=== added file 'src/com/ubuntu/content/detail/com.ubuntu.content.Paste.xml'
460--- src/com/ubuntu/content/detail/com.ubuntu.content.Paste.xml 1970-01-01 00:00:00 +0000
461+++ src/com/ubuntu/content/detail/com.ubuntu.content.Paste.xml 2016-08-25 13:22:47 +0000
462@@ -0,0 +1,22 @@
463+<node>
464+ <interface name="com.ubuntu.content.dbus.Paste">
465+ <signal name="StateChanged">
466+ <arg name="state" type="i"/>
467+ </signal>
468+ <method name="Id">
469+ <arg name="id" type="i" direction="out" />
470+ </method>
471+ <method name="State">
472+ <arg name="state" type="i" direction="out" />
473+ </method>
474+ <method name="Charge">
475+ <arg name="mimeData" type="ay" direction="in" />
476+ </method>
477+ <method name="MimeData">
478+ <arg name="mimeData" type="ay" direction="out" />
479+ </method>
480+ <method name="source">
481+ <arg name="source" type="s" direction="out" />
482+ </method>
483+ </interface>
484+</node>
485
486=== modified file 'src/com/ubuntu/content/detail/com.ubuntu.content.Service.xml'
487--- src/com/ubuntu/content/detail/com.ubuntu.content.Service.xml 2015-09-29 13:15:58 +0000
488+++ src/com/ubuntu/content/detail/com.ubuntu.content.Service.xml 2016-08-25 13:22:47 +0000
489@@ -36,6 +36,22 @@
490 <arg name="type_id" type="s" direction="in" />
491 <arg name="transfer_object" type="o" direction="out" />
492 </method>
493+ <method name="CreatePaste">
494+ <arg name="app_id" type="s" direction="in" />
495+ <arg name="surfaceId" type="s" direction="in" />
496+ <arg name="mimeData" type="ay" direction="in" />
497+ <arg name="types" type="as" direction="in" />
498+ <arg name="success" type="b" direction="out" />
499+ </method>
500+ <method name="GetLatestPasteData">
501+ <arg name="surfaceId" type="s" direction="in" />
502+ <arg name="mimeData" type="ay" direction="out" />
503+ </method>
504+ <method name="GetPasteData">
505+ <arg name="surfaceId" type="s" direction="in" />
506+ <arg name="pasteid" type="s" direction="in" />
507+ <arg name="mimeData" type="ay" direction="out" />
508+ </method>
509 <method name="RegisterImportExportHandler">
510 <arg name="peer_id" type="s" direction="in" />
511 <arg name="handler_object" type="o" direction="in" />
512@@ -51,5 +67,13 @@
513 <arg name="app_id" type="s" direction="in" />
514 <arg name="peer" type="v" direction="out" />
515 </method>
516+ <method name="PasteFormats">
517+ <arg name="formats" type="as" direction="out" />
518+ </method>
519+ <signal name="PasteFormatsChanged">
520+ <arg name="formats" type="as" />
521+ </signal>
522+ <signal name="PasteboardChanged">
523+ </signal>
524 </interface>
525 </node>
526
527=== added file 'src/com/ubuntu/content/detail/paste.cpp'
528--- src/com/ubuntu/content/detail/paste.cpp 1970-01-01 00:00:00 +0000
529+++ src/com/ubuntu/content/detail/paste.cpp 2016-08-25 13:22:47 +0000
530@@ -0,0 +1,132 @@
531+/*
532+ * Copyright © 2016 Canonical Ltd.
533+ *
534+ * This program is free software: you can redistribute it and/or modify
535+ * it under the terms of the GNU Lesser General Public License version 3 as
536+ * published by the Free Software Foundation.
537+ *
538+ * This program is distributed in the hope that it will be useful,
539+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
540+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
541+ * GNU Lesser General Public License for more details.
542+ *
543+ * You should have received a copy of the GNU Lesser General Public License
544+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
545+ *
546+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
547+ */
548+
549+#include "debug.h"
550+#include "paste.h"
551+#include "utils.cpp"
552+
553+#include <QFileInfo>
554+#include <com/ubuntu/content/hub.h>
555+#include <com/ubuntu/content/store.h>
556+#include <com/ubuntu/content/paste.h>
557+#include <ubuntu/download_manager/download.h>
558+#include <ubuntu/download_manager/manager.h>
559+
560+namespace cuc = com::ubuntu::content;
561+namespace cucd = com::ubuntu::content::detail;
562+
563+struct cucd::Paste::Private
564+{
565+ Private(const int id,
566+ const QString& source):
567+ state(cuc::Paste::created),
568+ id(id),
569+ source(source)
570+ {
571+ }
572+
573+ cuc::Paste::State state;
574+ const int id;
575+ const QString source;
576+ QString destination;
577+ QByteArray mimeData;
578+};
579+
580+cucd::Paste::Paste(const int id,
581+ const QString& source,
582+ QObject* parent) :
583+ QObject(parent), d(new Private(id, source))
584+{
585+ TRACE() << __PRETTY_FUNCTION__;
586+}
587+
588+cucd::Paste::~Paste()
589+{
590+ TRACE() << __PRETTY_FUNCTION__;
591+}
592+
593+/* unique id of the paste */
594+int cucd::Paste::Id()
595+{
596+ TRACE() << __PRETTY_FUNCTION__;
597+ return d->id;
598+}
599+
600+/* returns the add_id of the source app */
601+QString cucd::Paste::source()
602+{
603+ TRACE() << __PRETTY_FUNCTION__;
604+ return d->source;
605+}
606+
607+/* returns the add_id of the destination app */
608+QString cucd::Paste::destination()
609+{
610+ TRACE() << __PRETTY_FUNCTION__;
611+ if (d->destination.isEmpty())
612+ return d->source;
613+ return d->destination;
614+}
615+
616+void cucd::Paste::setDestination(QString& dest)
617+{
618+ TRACE() << __PRETTY_FUNCTION__;
619+ d->destination = dest;
620+}
621+
622+/* returns the object path for the paste */
623+QString cucd::Paste::path()
624+{
625+ TRACE() << Q_FUNC_INFO << "destination:" << destination();
626+ static const QString path_pattern{"/pastes/%1/%2"};
627+ QString path = path_pattern
628+ .arg(sanitize_id(destination()))
629+ .arg(d->id);
630+ return path;
631+}
632+
633+int cucd::Paste::State()
634+{
635+ TRACE() << __PRETTY_FUNCTION__;
636+ return d->state;
637+}
638+
639+void cucd::Paste::Charge(const QByteArray& mimeData)
640+{
641+ TRACE() << __PRETTY_FUNCTION__ << "STATE:" << d->state;
642+
643+ if (d->state == cuc::Paste::charged)
644+ return;
645+
646+ d->mimeData = mimeData;
647+ d->state = cuc::Paste::charged;
648+ Q_EMIT(StateChanged(d->state));
649+}
650+
651+QByteArray cucd::Paste::MimeData()
652+{
653+ TRACE() << __PRETTY_FUNCTION__;
654+
655+ if (d->state != cuc::Paste::collected)
656+ {
657+ d->state = cuc::Paste::collected;
658+ Q_EMIT(StateChanged(d->state));
659+ }
660+
661+ return d->mimeData;
662+}
663
664=== added file 'src/com/ubuntu/content/detail/paste.h'
665--- src/com/ubuntu/content/detail/paste.h 1970-01-01 00:00:00 +0000
666+++ src/com/ubuntu/content/detail/paste.h 2016-08-25 13:22:47 +0000
667@@ -0,0 +1,72 @@
668+/*
669+ * Copyright © 2016 Canonical Ltd.
670+ *
671+ * This program is free software: you can redistribute it and/or modify
672+ * it under the terms of the GNU Lesser General Public License version 3 as
673+ * published by the Free Software Foundation.
674+ *
675+ * This program is distributed in the hope that it will be useful,
676+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
677+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
678+ * GNU Lesser General Public License for more details.
679+ *
680+ * You should have received a copy of the GNU Lesser General Public License
681+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
682+ *
683+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
684+ */
685+#ifndef PASTE_H_
686+#define PASTE_H_
687+
688+#include <QByteArray>
689+#include <QDir>
690+#include <QObject>
691+#include <QtDBus/QDBusMessage>
692+#include <QtDBus/QDBusContext>
693+
694+namespace com
695+{
696+namespace ubuntu
697+{
698+namespace content
699+{
700+namespace detail
701+{
702+class Paste : public QObject, protected QDBusContext
703+{
704+ Q_OBJECT
705+ Q_PROPERTY(int State READ State NOTIFY StateChanged)
706+ Q_PROPERTY(int id READ Id)
707+ Q_PROPERTY(QString source READ source)
708+
709+ public:
710+ Paste(const int, const QString&, QObject* parent = nullptr);
711+ Paste(const Paste&) = delete;
712+ virtual ~Paste();
713+
714+ Paste& operator=(const Paste&) = delete;
715+
716+Q_SIGNALS:
717+ void StateChanged(int State);
718+
719+ public Q_SLOTS:
720+ int State();
721+ void Charge(const QByteArray& mimeData);
722+ QByteArray MimeData();
723+ int Id();
724+ QString source();
725+ QString destination();
726+ void setDestination(QString&);
727+ QString path();
728+
729+ private:
730+ struct Private;
731+ QScopedPointer<Private> d;
732+
733+};
734+}
735+}
736+}
737+}
738+
739+#endif // PASTE_H_
740
741=== modified file 'src/com/ubuntu/content/detail/service.cpp'
742--- src/com/ubuntu/content/detail/service.cpp 2016-01-29 17:20:58 +0000
743+++ src/com/ubuntu/content/detail/service.cpp 2016-08-25 13:22:47 +0000
744@@ -23,6 +23,8 @@
745 #include "service.h"
746 #include "peer_registry.h"
747 #include "i18n.h"
748+#include "paste.h"
749+#include "pasteadaptor.h"
750 #include "transfer.h"
751 #include "transferadaptor.h"
752 #include "utils.cpp"
753@@ -33,10 +35,12 @@
754 #include <libnotify/notify.h>
755
756 #include <com/ubuntu/content/item.h>
757+#include <com/ubuntu/content/paste.h>
758 #include <com/ubuntu/content/peer.h>
759 #include <com/ubuntu/content/type.h>
760 #include <com/ubuntu/content/transfer.h>
761
762+#include <QDBusInterface>
763 #include <QDBusMetaType>
764 #include <QCache>
765 #include <QCoreApplication>
766@@ -74,14 +78,22 @@
767 registry(registry),
768 app_manager(application_manager)
769 {
770+ unityFocus = new QDBusInterface("com.canonical.Unity.FocusInfo" /* service */,
771+ "/com/canonical/Unity/FocusInfo" /* object path */,
772+ "com.canonical.Unity.FocusInfo" /* interface */,
773+ QDBusConnection::sessionBus(),
774+ this);
775 }
776
777 QDBusConnection connection;
778 QSharedPointer<cucd::PeerRegistry> registry;
779 QSet<cucd::Transfer*> active_transfers;
780+ QList<cucd::Paste*> active_pastes;
781+ QStringList pasteFormats;
782 QSet<RegHandler*> handlers;
783 QSharedPointer<cua::ApplicationManager> app_manager;
784-
785+ QDBusInterface *unityFocus;
786+ const int maxActivePastes = 5;
787 };
788
789 cucd::Service::Service(QDBusConnection connection, const QSharedPointer<cucd::PeerRegistry>& peer_registry,
790@@ -302,14 +314,96 @@
791 return CreateTransfer(peer_id, src_id, cuc::Transfer::Share, type_id);
792 }
793
794+bool cucd::Service::CreatePaste(const QString& app_id, const QString& surfaceId, const QByteArray& mimeData,
795+ const QStringList& types)
796+{
797+ TRACE() << Q_FUNC_INFO << app_id << types;
798+
799+ if (!verifiedSurfaceIsFocused(surfaceId)) {
800+ return false;
801+ }
802+
803+ static size_t import_counter{0}; import_counter++;
804+
805+ pid_t pid = d->connection.interface()->servicePid(this->message().service());
806+ qWarning() << Q_FUNC_INFO << "PID: " << pid;
807+ QString effective_app_id;
808+ if (app_id_matches(app_id, pid)) {
809+ effective_app_id = app_id;
810+ } else {
811+ qWarning() << "APP_ID" << app_id << "doesn't match requesting APP";
812+ effective_app_id = "?";
813+ }
814+
815+ auto paste = new cucd::Paste(import_counter, effective_app_id, this);
816+ new PasteAdaptor(paste);
817+ d->active_pastes.append(paste);
818+
819+ paste->Charge(mimeData);
820+
821+ if (d->active_pastes.count() > d->maxActivePastes) {
822+ // get rid of the oldest one
823+ delete d->active_pastes.takeFirst();
824+ }
825+
826+ Q_EMIT(PasteboardChanged());
827+
828+ bool pendingPasteFormatsChangedSignal = false;
829+ Q_FOREACH (QString t, types) {
830+ TRACE() << Q_FUNC_INFO << "Type: " << t;
831+ if (!d->pasteFormats.contains(t)) {
832+ d->pasteFormats.append(t);
833+ pendingPasteFormatsChangedSignal = true;
834+ }
835+ }
836+ if (pendingPasteFormatsChangedSignal) {
837+ Q_EMIT(PasteFormatsChanged(d->pasteFormats));
838+ }
839+
840+ return true;
841+}
842+
843+QByteArray cucd::Service::GetLatestPasteData(const QString& surfaceId)
844+{
845+ TRACE() << Q_FUNC_INFO;
846+
847+ if (d->active_pastes.isEmpty())
848+ return QByteArray();
849+
850+ return getPasteData(surfaceId, d->active_pastes.last()->Id());
851+}
852+
853+QByteArray cucd::Service::GetPasteData(const QString& surfaceId, const QString& pasteId)
854+{
855+ TRACE() << Q_FUNC_INFO << pasteId;
856+
857+ if (d->active_pastes.isEmpty())
858+ return QByteArray();
859+
860+ return getPasteData(surfaceId, pasteId.toInt());
861+}
862+
863+QByteArray cucd::Service::getPasteData(const QString &surfaceId, int pasteId)
864+{
865+ if (!verifiedSurfaceIsFocused(surfaceId)) {
866+ qWarning().nospace() << "Surface isn't focused. Denying paste.";
867+ return QByteArray();
868+ }
869+
870+ Q_FOREACH (cucd::Paste *p, d->active_pastes)
871+ {
872+ if (p->Id() == pasteId)
873+ return p->MimeData();
874+ }
875+ return QByteArray();
876+}
877+
878 QDBusObjectPath cucd::Service::CreateTransfer(const QString& dest_id, const QString& src_id, int dir, const QString& type_id)
879 {
880 TRACE() << Q_FUNC_INFO << "DEST:" << dest_id << "SRC:" << src_id << "DIRECTION:" << dir;
881
882 static size_t import_counter{0}; import_counter++;
883
884- QUuid uuid{QUuid::createUuid()};
885-
886 Q_FOREACH (cucd::Transfer *t, d->active_transfers)
887 {
888 if (t->destination() == dest_id || t->source() == src_id)
889@@ -384,7 +478,7 @@
890 TRACE() << Q_FUNC_INFO << "Charged";
891 if (transfer->WasSourceStartedByContentHub())
892 d->app_manager->stop_application(transfer->source().toStdString());
893-
894+
895 gchar ** uris = NULL;
896 if (d->registry->peer_is_legacy(transfer->destination())) {
897 TRACE() << Q_FUNC_INFO << "Destination is a legacy app, collecting";
898@@ -439,7 +533,7 @@
899 }
900 }
901 if (shouldStop)
902- d->app_manager->stop_application(transfer->source().toStdString());
903+ d->app_manager->stop_application(transfer->source().toStdString());
904 }
905 gchar ** uris = NULL;
906 d->app_manager->invoke_application(transfer->destination().toStdString(), uris);
907@@ -478,7 +572,7 @@
908 if (d->registry->peer_is_legacy(transfer->destination())) {
909 TRACE() << Q_FUNC_INFO << "Destination is a legacy app, collecting";
910 transfer->SetStore(shared_dir_for_peer(transfer->destination()));
911-
912+
913 auto items = transfer->Collect();
914 gchar* urls[2] = {0};
915 gint i = 0;
916@@ -661,3 +755,18 @@
917 }
918 return false;
919 }
920+
921+QStringList cucd::Service::PasteFormats()
922+{
923+ TRACE() << Q_FUNC_INFO;
924+ return d->pasteFormats;
925+}
926+
927+bool cucd::Service::verifiedSurfaceIsFocused(const QString &surfaceId)
928+{
929+ /* Only verify focus when not running under testing */
930+ if (!qgetenv("CONTENT_HUB_TESTING").isNull())
931+ return true;
932+
933+ return d->unityFocus->call("isSurfaceFocused", surfaceId).arguments().at(0).toBool();
934+}
935
936=== modified file 'src/com/ubuntu/content/detail/service.h'
937--- src/com/ubuntu/content/detail/service.h 2015-09-29 13:15:58 +0000
938+++ src/com/ubuntu/content/detail/service.h 2016-08-25 13:22:47 +0000
939@@ -61,6 +61,10 @@
940 QDBusObjectPath CreateImportFromPeer(const QString&, const QString&, const QString&);
941 QDBusObjectPath CreateExportToPeer(const QString&, const QString&, const QString&);
942 QDBusObjectPath CreateShareToPeer(const QString&, const QString&, const QString&);
943+ bool CreatePaste(const QString&, const QString&, const QByteArray&, const QStringList&);
944+ QByteArray GetLatestPasteData(const QString& surfaceId);
945+ QByteArray GetPasteData(const QString& surfaceId, const QString& pasteId);
946+ QStringList PasteFormats();
947
948 void RegisterImportExportHandler(const QString&, const QDBusObjectPath& handler);
949 void HandlerActive(const QString&);
950@@ -70,12 +74,18 @@
951 QDBusVariant PeerForId(const QString&);
952
953 private:
954+ QByteArray getPasteData(const QString &surfaceId, int pasteId);
955 bool should_cancel(int);
956+ bool verifiedSurfaceIsFocused(const QString &surfaceId);
957 struct Private;
958 struct RegHandler;
959 QDBusServiceWatcher* m_watcher;
960 QScopedPointer<Private> d;
961
962+ Q_SIGNALS:
963+ void PasteFormatsChanged(const QStringList &formats);
964+ void PasteboardChanged();
965+
966 private Q_SLOTS:
967 void handle_imports(int);
968 void handle_exports(int);
969
970=== modified file 'src/com/ubuntu/content/hub.cpp'
971--- src/com/ubuntu/content/hub.cpp 2016-07-15 18:54:41 +0000
972+++ src/com/ubuntu/content/hub.cpp 2016-08-25 13:22:47 +0000
973@@ -21,6 +21,7 @@
974 #include "ContentServiceInterface.h"
975 #include "ContentHandlerInterface.h"
976 #include "handleradaptor.h"
977+#include "paste_p.h"
978 #include "transfer_p.h"
979 #include "utils.cpp"
980
981@@ -32,6 +33,7 @@
982 #include <com/ubuntu/content/type.h>
983 #include <libertine.h>
984
985+#include <QDBusPendingCallWatcher>
986 #include <QIcon>
987 #include <QStandardPaths>
988 #include <QStringList>
989@@ -52,6 +54,7 @@
990 }
991
992 com::ubuntu::content::dbus::Service* service;
993+ QStringList pasteFormats;
994 };
995
996 cuc::Hub::Hub(QObject* parent) : QObject(parent), d{new cuc::Hub::Private{this}}
997@@ -79,6 +82,13 @@
998 iconPaths << QString(path + "/usr/share/icons/");
999 }
1000 QIcon::setThemeSearchPaths(iconPaths);
1001+
1002+ QObject::connect(d->service, &com::ubuntu::content::dbus::Service::PasteFormatsChanged,
1003+ this, &cuc::Hub::Hub::onPasteFormatsChanged);
1004+ requestPasteFormats();
1005+ QObject::connect(d->service, SIGNAL(PasteboardChanged()),
1006+ this,
1007+ SIGNAL(pasteboardChanged()));
1008 }
1009
1010 cuc::Hub::~Hub()
1011@@ -91,6 +101,31 @@
1012 return hub;
1013 }
1014
1015+void cuc::Hub::requestPasteFormats()
1016+{
1017+ auto reply = d->service->PasteFormats();
1018+
1019+ auto replyWatcher = new QDBusPendingCallWatcher(reply, this);
1020+ connect(replyWatcher, &QDBusPendingCallWatcher::finished,
1021+ this, [this, replyWatcher]() {
1022+ QDBusPendingReply<QStringList> reply = *replyWatcher;
1023+ replyWatcher->deleteLater();
1024+ if (!reply.isError()) {
1025+ d->pasteFormats = reply.value();
1026+ Q_EMIT(pasteFormatsChanged());
1027+ }
1028+ });
1029+}
1030+
1031+void cuc::Hub::onPasteFormatsChanged(const QStringList &formats)
1032+{
1033+ TRACE() << Q_FUNC_INFO;
1034+
1035+ d->pasteFormats = formats;
1036+ TRACE() << Q_FUNC_INFO << d->pasteFormats;
1037+ Q_EMIT(pasteFormatsChanged());
1038+}
1039+
1040 bool cuc::Hub::eventFilter(QObject *obj, QEvent *event)
1041 {
1042 if (event->type() == QEvent::ApplicationActivate)
1043@@ -100,7 +135,7 @@
1044 {
1045 TRACE() << Q_FUNC_INFO << id << "Activated";
1046 d->service->HandlerActive(id);
1047- } else
1048+ } else
1049 {
1050 qWarning() << "APP_ID isn't set, the handler ignored";
1051 }
1052@@ -181,7 +216,7 @@
1053
1054 if (reply.isError())
1055 return result;
1056-
1057+
1058 auto peers = reply.value();
1059 QString id = app_id();
1060
1061@@ -340,3 +375,64 @@
1062 auto peer = reply.value();
1063 return qdbus_cast<cuc::Peer>(peer.variant());
1064 }
1065+
1066+QDBusPendingCall cuc::Hub::createPaste(const QString &surfaceId, const QMimeData& mimeData)
1067+{
1068+ /* This needs to be replaced with a better way to get the APP_ID */
1069+ QString appId = app_id();
1070+ TRACE() << Q_FUNC_INFO << appId;
1071+
1072+ auto serializedMimeData = serializeMimeData(mimeData);
1073+ if (serializedMimeData.isEmpty()) {
1074+ return QDBusPendingCall::fromCompletedCall(
1075+ QDBusMessage::createError("Data serialization failed","Could not serialize mimeData"));
1076+ }
1077+
1078+ return d->service->CreatePaste(appId, surfaceId, serializedMimeData, mimeData.formats());
1079+}
1080+
1081+bool cuc::Hub::createPasteSync(const QString &surfaceId, const QMimeData& data)
1082+{
1083+ QDBusPendingCall reply = createPaste(surfaceId, data);
1084+ reply.waitForFinished();
1085+ return !reply.isError();
1086+}
1087+
1088+QDBusPendingCall cuc::Hub::requestLatestPaste(const QString &surfaceId)
1089+{
1090+ TRACE() << Q_FUNC_INFO;
1091+ return d->service->GetLatestPasteData(surfaceId);
1092+}
1093+
1094+QDBusPendingCall cuc::Hub::requestPasteById(const QString &surfaceId, int pasteId)
1095+{
1096+ TRACE() << Q_FUNC_INFO;
1097+ return d->service->GetPasteData(surfaceId, QString::number(pasteId));
1098+}
1099+
1100+QMimeData* cuc::Hub::paste(QDBusPendingCall pendingCall)
1101+{
1102+ auto reply = QDBusPendingReply<QByteArray>(pendingCall);
1103+ reply.waitForFinished();
1104+
1105+ if (reply.isError())
1106+ return nullptr;
1107+
1108+ QByteArray serializedMimeData = qdbus_cast<QByteArray>(reply.value());
1109+ return deserializeMimeData(serializedMimeData);
1110+}
1111+
1112+QMimeData* cuc::Hub::latestPaste(const QString &surfaceId)
1113+{
1114+ return paste(requestLatestPaste(surfaceId));
1115+}
1116+
1117+QMimeData* cuc::Hub::pasteById(const QString &surfaceId, int pasteId)
1118+{
1119+ return paste(requestPasteById(surfaceId, pasteId));
1120+}
1121+
1122+QStringList cuc::Hub::pasteFormats() {
1123+ TRACE() << Q_FUNC_INFO;
1124+ return d->pasteFormats;
1125+}
1126
1127=== added file 'src/com/ubuntu/content/paste.cpp'
1128--- src/com/ubuntu/content/paste.cpp 1970-01-01 00:00:00 +0000
1129+++ src/com/ubuntu/content/paste.cpp 2016-08-25 13:22:47 +0000
1130@@ -0,0 +1,50 @@
1131+/*
1132+ * Copyright © 2016 Canonical Ltd.
1133+ *
1134+ * This program is free software: you can redistribute it and/or modify
1135+ * it under the terms of the GNU Lesser General Public License version 3 as
1136+ * published by the Free Software Foundation.
1137+ *
1138+ * This program is distributed in the hope that it will be useful,
1139+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1140+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1141+ * GNU Lesser General Public License for more details.
1142+ *
1143+ * You should have received a copy of the GNU Lesser General Public License
1144+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1145+ *
1146+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
1147+ */
1148+
1149+#include <com/ubuntu/content/paste.h>
1150+
1151+#include "paste_p.h"
1152+#include "utils.cpp"
1153+
1154+namespace cuc = com::ubuntu::content;
1155+
1156+cuc::Paste::Paste(const QSharedPointer<cuc::Paste::Private>& d, QObject* parent)
1157+ : QObject(parent),
1158+ d(d)
1159+{
1160+}
1161+
1162+cuc::Paste::~Paste()
1163+{
1164+ TRACE() << Q_FUNC_INFO;
1165+}
1166+
1167+int cuc::Paste::id() const
1168+{
1169+ return d->id();
1170+}
1171+
1172+QMimeData* cuc::Paste::mimeData()
1173+{
1174+ return deserializeMimeData(d->mimeData());
1175+}
1176+
1177+QString cuc::Paste::source() const
1178+{
1179+ return d->source();
1180+}
1181
1182=== added file 'src/com/ubuntu/content/paste_p.h'
1183--- src/com/ubuntu/content/paste_p.h 1970-01-01 00:00:00 +0000
1184+++ src/com/ubuntu/content/paste_p.h 2016-08-25 13:22:47 +0000
1185@@ -0,0 +1,100 @@
1186+/*
1187+ * Copyright © 2016 Canonical Ltd.
1188+ *
1189+ * This program is free software: you can redistribute it and/or modify
1190+ * it under the terms of the GNU Lesser General Public License version 3 as
1191+ * published by the Free Software Foundation.
1192+ *
1193+ * This program is distributed in the hope that it will be useful,
1194+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1195+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1196+ * GNU Lesser General Public License for more details.
1197+ *
1198+ * You should have received a copy of the GNU Lesser General Public License
1199+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1200+ *
1201+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
1202+ */
1203+#ifndef COM_UBUNTU_CONTENT_PASTE_P_H_
1204+#define COM_UBUNTU_CONTENT_PASTE_P_H_
1205+
1206+#include "common.h"
1207+#include "ContentPasteInterface.h"
1208+
1209+#include <com/ubuntu/content/item.h>
1210+#include <com/ubuntu/content/paste.h>
1211+
1212+#include <QByteArray>
1213+#include <QMimeData>
1214+#include <QObject>
1215+
1216+namespace com
1217+{
1218+namespace ubuntu
1219+{
1220+namespace content
1221+{
1222+class Paste::Private : public QObject
1223+{
1224+ Q_OBJECT
1225+ public:
1226+ static Paste* make_paste(const QDBusObjectPath& paste, QObject* parent)
1227+ {
1228+ QSharedPointer<Private> d{new Private{paste, parent}};
1229+ return new Paste{d, parent};
1230+ }
1231+
1232+ Private(const QDBusObjectPath& paste, QObject* parent)
1233+ : QObject(parent),
1234+ remote_paste(
1235+ new com::ubuntu::content::dbus::Paste(
1236+ HUB_SERVICE_NAME,
1237+ paste.path(),
1238+ QDBusConnection::sessionBus(), this))
1239+ {
1240+ }
1241+
1242+ int id()
1243+ {
1244+ auto reply = remote_paste->Id();
1245+ reply.waitForFinished();
1246+
1247+ return reply.value();
1248+ }
1249+
1250+ State state()
1251+ {
1252+ auto reply = remote_paste->State();
1253+ reply.waitForFinished();
1254+
1255+ return static_cast<Paste::State>(reply.value());
1256+ }
1257+
1258+ QByteArray mimeData()
1259+ {
1260+ auto reply = remote_paste->MimeData();
1261+ reply.waitForFinished();
1262+
1263+ if (reply.isError())
1264+ return nullptr;
1265+
1266+ QByteArray serializedMimeData = qdbus_cast<QByteArray>(reply.value());
1267+
1268+ return serializedMimeData;
1269+ }
1270+
1271+ QString source()
1272+ {
1273+ auto reply = remote_paste->source();
1274+ reply.waitForFinished();
1275+
1276+ return static_cast<QString>(reply.value());
1277+ }
1278+
1279+ com::ubuntu::content::dbus::Paste* remote_paste;
1280+};
1281+}
1282+}
1283+}
1284+
1285+#endif // COM_UBUNTU_CONTENT_PASTE_P_H_
1286
1287=== modified file 'src/com/ubuntu/content/utils.cpp'
1288--- src/com/ubuntu/content/utils.cpp 2015-10-23 15:12:48 +0000
1289+++ src/com/ubuntu/content/utils.cpp 2016-08-25 13:22:47 +0000
1290@@ -1,5 +1,5 @@
1291 /*
1292- * Copyright © 2013 Canonical Ltd.
1293+ * Copyright © 2013-2016 Canonical Ltd.
1294 *
1295 * This program is free software: you can redistribute it and/or modify
1296 * it under the terms of the GNU Lesser General Public License version 3 as
1297@@ -20,6 +20,7 @@
1298 #include <QDir>
1299 #include <QFile>
1300 #include <QFileInfo>
1301+#include <QMimeData>
1302 #include <QProcess>
1303 #include <QtCore>
1304 #include <QtDBus/QDBusMessage>
1305@@ -33,6 +34,9 @@
1306 #include "com/ubuntu/content/type.h"
1307 #include <unistd.h>
1308 #include <liblibertine/libertine.h>
1309+#include <ubuntu-app-launch/appid.h>
1310+#include <ubuntu-app-launch/application.h>
1311+#include <ubuntu-app-launch/registry.h>
1312
1313 #include <sys/apparmor.h>
1314 /* need to be exposed in libapparmor but for now ... */
1315@@ -40,9 +44,100 @@
1316 #define AA_MAY_READ (1 << 2)
1317
1318 namespace cuc = com::ubuntu::content;
1319+namespace ual = ubuntu::app_launch;
1320
1321 namespace {
1322
1323+/* Used for pasteboard */
1324+const int maxFormatsCount = 16;
1325+const int maxBufferSize = 4 * 1024 * 1024; // 4 Mb
1326+
1327+/*
1328+ Data format:
1329+ number of mime types (sizeof(int))
1330+ data layout ((4 * sizeof(int)) * number of mime types)
1331+ mime type string offset (sizeof(int))
1332+ mime type string size (sizeof(int))
1333+ data offset (sizeof(int))
1334+ data size (sizeof(int))
1335+ data (n bytes)
1336+*/
1337+QByteArray serializeMimeData(const QMimeData &mimeData)
1338+{
1339+ const QStringList formats = mimeData.formats();
1340+ const int formatCount = qMin(formats.size(), maxFormatsCount);
1341+ const int headerSize = sizeof(int) + (formatCount * 4 * sizeof(int));
1342+ int bufferSize = headerSize;
1343+
1344+ for (int i = 0; i < formatCount; i++)
1345+ bufferSize += formats[i].size() + mimeData.data(formats[i]).size();
1346+
1347+ QByteArray serializedMimeData;
1348+ if (bufferSize <= maxBufferSize) {
1349+ // Serialize data.
1350+ serializedMimeData.resize(bufferSize);
1351+ {
1352+ char *buffer = serializedMimeData.data();
1353+ int* header = reinterpret_cast<int*>(serializedMimeData.data());
1354+ int offset = headerSize;
1355+ header[0] = formatCount;
1356+ for (int i = 0; i < formatCount; i++) {
1357+ const QByteArray data = mimeData.data(formats[i]);
1358+ const int formatOffset = offset;
1359+ const int formatSize = formats[i].size();
1360+ const int dataOffset = offset + formatSize;
1361+ const int dataSize = data.size();
1362+ memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize);
1363+ memcpy(&buffer[dataOffset], data.data(), dataSize);
1364+ header[i*4+1] = formatOffset;
1365+ header[i*4+2] = formatSize;
1366+ header[i*4+3] = dataOffset;
1367+ header[i*4+4] = dataSize;
1368+ offset += formatSize + dataSize;
1369+ }
1370+ }
1371+ } else {
1372+ qWarning("Not sending contents (%d bytes) to the global clipboard as it's"
1373+ " bigger than the maximum allowed size of %d bytes", bufferSize, maxBufferSize);
1374+ }
1375+
1376+ return serializedMimeData;
1377+}
1378+
1379+QMimeData *deserializeMimeData(const QByteArray &serializedMimeData)
1380+{
1381+ if (static_cast<std::size_t>(serializedMimeData.size()) < sizeof(int)) {
1382+ // Data is invalid
1383+ return nullptr;
1384+ }
1385+
1386+ QMimeData *mimeData = new QMimeData;
1387+
1388+ const char* const buffer = serializedMimeData.constData();
1389+ const int* const header = reinterpret_cast<const int*>(serializedMimeData.constData());
1390+
1391+ const int count = qMin(header[0], maxFormatsCount);
1392+
1393+ for (int i = 0; i < count; i++) {
1394+ const int formatOffset = header[i*4+1];
1395+ const int formatSize = header[i*4+2];
1396+ const int dataOffset = header[i*4+3];
1397+ const int dataSize = header[i*4+4];
1398+
1399+ if (formatOffset + formatSize <= serializedMimeData.size()
1400+ && dataOffset + dataSize <= serializedMimeData.size()) {
1401+
1402+ QString mimeType = QString::fromLatin1(&buffer[formatOffset], formatSize);
1403+ QByteArray mimeDataBytes(&buffer[dataOffset], dataSize);
1404+
1405+ mimeData->setData(mimeType, mimeDataBytes);
1406+ }
1407+ }
1408+
1409+ return mimeData;
1410+}
1411+
1412+
1413 QList<cuc::Type> known_types()
1414 {
1415 QList<cuc::Type> types;
1416@@ -104,6 +199,29 @@
1417 }
1418
1419
1420+bool app_id_matches(QString id, pid_t pid)
1421+{
1422+ TRACE() << Q_FUNC_INFO << id << pid;
1423+
1424+ /* Don't verify app_id while testing */
1425+ if (!qgetenv("CONTENT_HUB_TESTING").isNull())
1426+ return true;
1427+
1428+ std::shared_ptr<ual::Registry> reg = ual::Registry::getDefault();
1429+ auto app_id = ual::AppID::find(id.toStdString());
1430+ if (app_id.empty())
1431+ return false;
1432+ auto app = ual::Application::create(app_id, reg);
1433+ if (!app.get()->hasInstances())
1434+ return false;
1435+ Q_FOREACH (std::shared_ptr<ual::Application::Instance> instance, app.get()->instances()) {
1436+ if (instance.get()->hasPid(pid))
1437+ return true;
1438+ }
1439+ return false;
1440+}
1441+
1442+
1443 QString aa_profile(QString uniqueConnectionId)
1444 {
1445 TRACE() << Q_FUNC_INFO << uniqueConnectionId;
1446@@ -235,7 +353,7 @@
1447 qWarning() << "error:" << strerror(errno) << path;
1448 return false;
1449 }
1450-
1451+
1452 if (allowed) {
1453 TRACE() << "ALLOWED:" << QString::number(allowed);
1454 return true;
1455
1456=== modified file 'tests/acceptance-tests/CMakeLists.txt'
1457--- tests/acceptance-tests/CMakeLists.txt 2015-06-29 13:46:54 +0000
1458+++ tests/acceptance-tests/CMakeLists.txt 2016-08-25 13:22:47 +0000
1459@@ -41,6 +41,12 @@
1460 )
1461
1462 add_executable(
1463+ app_hub_communication_paste
1464+ app_hub_communication_paste.cpp
1465+ ${MOCS}
1466+)
1467+
1468+add_executable(
1469 app_hub_communication_handler
1470 app_hub_communication_handler.cpp
1471 ${MOCS}
1472@@ -68,32 +74,47 @@
1473 source_all.json
1474 )
1475
1476+add_executable(
1477+ mimedata_test
1478+ mimedata_test.cpp
1479+ ${MOCS}
1480+)
1481+
1482 qt5_use_modules(app_hub_communication_default_source Core Gui DBus Test)
1483 qt5_use_modules(app_hub_communication_known_sources Core Gui DBus Test)
1484 qt5_use_modules(app_hub_communication_stores Core Gui DBus Test)
1485 qt5_use_modules(app_hub_communication_transfer Core Gui DBus Test)
1486+qt5_use_modules(app_hub_communication_paste Core Gui DBus Test)
1487 qt5_use_modules(app_hub_communication_handler Core Gui DBus Test)
1488 qt5_use_modules(test_utils Core Test)
1489 qt5_use_modules(test_hook Core Gui DBus Test)
1490+qt5_use_modules(mimedata_test Core Test)
1491
1492 target_link_libraries(app_hub_communication_stores content-hub gmock gtest gtest_main)
1493 target_link_libraries(app_hub_communication_default_source content-hub gmock gtest gtest_main)
1494 target_link_libraries(app_hub_communication_known_sources content-hub gmock gtest gtest_main)
1495 target_link_libraries(app_hub_communication_stores content-hub gmock gtest gtest_main)
1496 target_link_libraries(app_hub_communication_transfer content-hub gmock gtest gtest_main)
1497+target_link_libraries(app_hub_communication_paste content-hub gmock gtest gtest_main)
1498 target_link_libraries(app_hub_communication_handler content-hub gmock gtest gtest_main)
1499 target_link_libraries(test_utils content-hub gmock gtest gtest_main)
1500 target_link_libraries(test_types content-hub gmock gtest gtest_main)
1501 target_link_libraries(test_hook content-hub gmock gtest gtest_main ${GSETTINGS_LDFLAGS})
1502+target_link_libraries(mimedata_test content-hub gmock gtest gtest_main)
1503
1504 add_test(app_hub_communication_default_source app_hub_communication_default_source)
1505 add_test(app_hub_communication_known_sources app_hub_communication_known_sources)
1506 add_test(app_hub_communication_stores app_hub_communication_stores)
1507 add_test(app_hub_communication_transfer app_hub_communication_transfer)
1508+add_test(app_hub_communication_paste app_hub_communication_transfer)
1509 add_test(app_hub_communication_handler app_hub_communication_handler)
1510 add_test(test_utils test_utils)
1511 add_test(test_types test_types)
1512 add_test(test_hook test_hook)
1513+add_test(mimedata_test mimedata_test)
1514+
1515+SET_TESTS_PROPERTIES(app_hub_communication_paste
1516+ PROPERTIES ENVIRONMENT "CONTENT_HUB_TESTING=1")
1517
1518 set_target_properties(
1519 test_hook
1520
1521=== added file 'tests/acceptance-tests/app_hub_communication_paste.cpp'
1522--- tests/acceptance-tests/app_hub_communication_paste.cpp 1970-01-01 00:00:00 +0000
1523+++ tests/acceptance-tests/app_hub_communication_paste.cpp 2016-08-25 13:22:47 +0000
1524@@ -0,0 +1,138 @@
1525+/*
1526+ * Copyright © 2016 Canonical Ltd.
1527+ *
1528+ * This program is free software: you can redistribute it and/or modify
1529+ * it under the terms of the GNU General Public License version 3 as
1530+ * published by the Free Software Foundation.
1531+ *
1532+ * This program is distributed in the hope that it will be useful,
1533+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1534+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1535+ * GNU Lesser General Public License for more details.
1536+ *
1537+ * You should have received a copy of the GNU Lesser General Public License
1538+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1539+ *
1540+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
1541+ */
1542+
1543+#include "app_manager_mock.h"
1544+#include "test_harness.h"
1545+#include "../cross_process_sync.h"
1546+#include "../fork_and_run.h"
1547+
1548+#include <com/ubuntu/content/hub.h>
1549+#include <com/ubuntu/content/item.h>
1550+#include <com/ubuntu/content/paste.h>
1551+
1552+#include "com/ubuntu/content/detail/peer_registry.h"
1553+#include "com/ubuntu/content/detail/service.h"
1554+#include "com/ubuntu/content/serviceadaptor.h"
1555+
1556+#include <gmock/gmock.h>
1557+#include <gtest/gtest.h>
1558+
1559+#include <QCoreApplication>
1560+#include <QtDBus/QDBusConnection>
1561+#include <QStandardPaths>
1562+#include <QTemporaryDir>
1563+#include <QtTest/QTest>
1564+
1565+#include <thread>
1566+
1567+namespace cua = com::ubuntu::ApplicationManager;
1568+namespace cuc = com::ubuntu::content;
1569+namespace cucd = com::ubuntu::content::detail;
1570+
1571+void PrintTo(const QString& s, ::std::ostream* os) {
1572+ *os << std::string(qPrintable(s));
1573+}
1574+
1575+namespace
1576+{
1577+QString service_name{"com.ubuntu.content.dbus.Service"};
1578+
1579+struct MockedPeerRegistry : public cucd::PeerRegistry
1580+{
1581+ MockedPeerRegistry() : cucd::PeerRegistry()
1582+ {
1583+ using namespace ::testing;
1584+
1585+ ON_CALL(*this, default_source_for_type(_)).WillByDefault(Return(cuc::Peer::unknown()));
1586+ ON_CALL(*this, install_default_source_for_type(_,_)).WillByDefault(Return(false));
1587+ ON_CALL(*this, install_source_for_type(_,_)).WillByDefault(Return(false));
1588+ }
1589+
1590+ MOCK_METHOD1(default_source_for_type, cuc::Peer(cuc::Type t));
1591+ MOCK_METHOD1(enumerate_known_peers, void(const std::function<void(const cuc::Peer&)>&));
1592+ MOCK_METHOD2(enumerate_known_sources_for_type, void(cuc::Type, const std::function<void(const cuc::Peer&)>&));
1593+ MOCK_METHOD2(enumerate_known_destinations_for_type, void(cuc::Type, const std::function<void(const cuc::Peer&)>&));
1594+ MOCK_METHOD2(enumerate_known_shares_for_type, void(cuc::Type, const std::function<void(const cuc::Peer&)>&));
1595+ MOCK_METHOD2(install_default_source_for_type, bool(cuc::Type, cuc::Peer));
1596+ MOCK_METHOD2(install_source_for_type, bool(cuc::Type, cuc::Peer));
1597+ MOCK_METHOD2(install_destination_for_type, bool(cuc::Type, cuc::Peer));
1598+ MOCK_METHOD2(install_share_for_type, bool(cuc::Type, cuc::Peer));
1599+ MOCK_METHOD1(remove_peer, bool(cuc::Peer));
1600+ MOCK_METHOD1(peer_is_legacy, bool(QString));
1601+};
1602+}
1603+
1604+TEST(Hub, transfer_creation_and_states_work)
1605+{
1606+ using namespace ::testing;
1607+
1608+ test::CrossProcessSync sync;
1609+
1610+ auto parent = [&sync]()
1611+ {
1612+ int argc = 0;
1613+ QCoreApplication app{argc, nullptr};
1614+
1615+ QDBusConnection connection = QDBusConnection::sessionBus();
1616+
1617+ auto mock = new ::testing::NiceMock<MockedPeerRegistry>{};
1618+
1619+ QSharedPointer<cucd::PeerRegistry> registry{mock};
1620+ auto app_manager = QSharedPointer<cua::ApplicationManager>(new MockedAppManager());
1621+ cucd::Service implementation(connection, registry, app_manager, &app);
1622+ new ServiceAdaptor(std::addressof(implementation));
1623+
1624+ ASSERT_TRUE(connection.registerService(service_name));
1625+ ASSERT_TRUE(connection.registerObject("/", std::addressof(implementation)));
1626+
1627+ sync.signal_ready();
1628+
1629+ app.exec();
1630+
1631+ connection.unregisterObject("/");
1632+ connection.unregisterService(service_name);
1633+ };
1634+
1635+ auto child = [&sync]()
1636+ {
1637+ int argc = 0;
1638+ QCoreApplication app(argc, nullptr);
1639+
1640+ sync.wait_for_signal_ready();
1641+
1642+ test::TestHarness harness;
1643+ harness.add_test_case([]()
1644+ {
1645+ qputenv("APP_ID", "some-app");
1646+
1647+ QMimeData data;
1648+ data.setText("some text");
1649+ auto hub = cuc::Hub::Client::instance();
1650+ QString surfaceId("some-bogus-fake-surface-id");
1651+ bool ok = hub->createPasteSync(surfaceId, const_cast<const QMimeData&>(data));
1652+ ASSERT_TRUE(ok);
1653+ EXPECT_EQ(QString(data.text()), QString(hub->latestPaste(surfaceId)->text()));
1654+ EXPECT_EQ(QString(data.text()), QString(hub->pasteById(surfaceId, 1)->text()));
1655+
1656+ hub->quit();
1657+ });
1658+ EXPECT_EQ(0, QTest::qExec(std::addressof(harness)));
1659+ };
1660+
1661+ EXPECT_EQ(EXIT_SUCCESS, test::fork_and_run(child, parent));
1662+}
1663
1664=== added file 'tests/acceptance-tests/mimedata_test.cpp'
1665--- tests/acceptance-tests/mimedata_test.cpp 1970-01-01 00:00:00 +0000
1666+++ tests/acceptance-tests/mimedata_test.cpp 2016-08-25 13:22:47 +0000
1667@@ -0,0 +1,44 @@
1668+/*
1669+ * Copyright (C) 2014-2016 Canonical, Ltd.
1670+ *
1671+ * This program is free software: you can redistribute it and/or modify it under
1672+ * the terms of the GNU Lesser General Public License version 3, as published by
1673+ * the Free Software Foundation.
1674+ *
1675+ * This program is distributed in the hope that it will be useful, but WITHOUT
1676+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1677+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1678+ * Lesser General Public License for more details.
1679+ *
1680+ * You should have received a copy of the GNU Lesser General Public License
1681+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1682+ */
1683+
1684+#include <gtest/gtest.h>
1685+
1686+#include "../../src/com/ubuntu/content/utils.cpp"
1687+
1688+#include <QMimeData>
1689+
1690+TEST(PasteBoardTest, MimeDataSerialization)
1691+{
1692+ QMimeData mimeData;
1693+ mimeData.setData("text/plain", "Hello World!");
1694+ mimeData.setData("text/html", "<html lang=\"en\"><body>Hello World!</body></html>");
1695+
1696+ QByteArray serializedMimeData = serializeMimeData(const_cast<const QMimeData&>(mimeData));
1697+
1698+ ASSERT_TRUE(serializedMimeData.size() > 0);
1699+
1700+ QMimeData *deserializedMimeData = deserializeMimeData(serializedMimeData);
1701+
1702+ ASSERT_TRUE(deserializedMimeData != nullptr);
1703+
1704+ ASSERT_TRUE(deserializedMimeData->hasFormat("text/plain"));
1705+ ASSERT_EQ(mimeData.data("text/plain"), deserializedMimeData->data("text/plain"));
1706+
1707+ ASSERT_TRUE(deserializedMimeData->hasFormat("text/html"));
1708+ ASSERT_EQ(mimeData.data("text/html"), deserializedMimeData->data("text/html"));
1709+
1710+ delete deserializedMimeData;
1711+}

Subscribers

People subscribed via source and target branches