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