Merge lp:~michihenning/unity-scopes-api/scope-cache-dir into lp:unity-scopes-api/devel

Proposed by Michi Henning
Status: Merged
Approved by: Michal Hruby
Approved revision: 419
Merged at revision: 423
Proposed branch: lp:~michihenning/unity-scopes-api/scope-cache-dir
Merge into: lp:unity-scopes-api/devel
Diff against target: 2237 lines (+609/-346)
60 files modified
CONFIGFILES (+1/-1)
HACKING (+14/-9)
RELEASE_NOTES.md (+15/-0)
debian/changelog (+5/-2)
debian/libunity-scopes2.symbols (+14/-6)
debian/tests/scopebuild (+5/-54)
debian/tests/scopetest.cpp (+62/-0)
demo/click/scope-click/scope-click.cpp (+1/-1)
demo/scopes/scope-A/scope-A.cpp (+1/-1)
demo/scopes/scope-B/scope-B.cpp (+4/-4)
demo/scopes/scope-C/scope-C.cpp (+1/-1)
demo/scopes/scope-D/scope-D.cpp (+1/-1)
demo/scopes/scope-N/scope-N.cpp (+1/-1)
demo/scopes/scope-S/scope-S.cpp (+1/-1)
doc/tutorial.dox (+3/-3)
include/unity/scopes/AbstractScopeBase.h (+65/-0)
include/unity/scopes/ScopeBase.h (+56/-29)
include/unity/scopes/internal/DfltConfig.h.in (+1/-0)
include/unity/scopes/internal/RuntimeImpl.h (+1/-0)
include/unity/scopes/internal/ScopeBaseImpl.h (+21/-3)
include/unity/scopes/internal/ScopeConfig.h (+12/-12)
include/unity/scopes/internal/ScopeLoader.h (+3/-11)
include/unity/scopes/testing/TypedScopeFixture.h (+6/-6)
scoperegistry/scoperegistry.cpp (+27/-19)
scoperunner/scoperunner.cpp (+20/-43)
smartscopesproxy/smartscopesproxy.cpp (+3/-2)
src/scopes/ScopeBase.cpp (+12/-1)
src/scopes/internal/RegistryConfig.cpp (+1/-1)
src/scopes/internal/RuntimeConfig.cpp (+1/-1)
src/scopes/internal/RuntimeImpl.cpp (+66/-23)
src/scopes/internal/ScopeBaseImpl.cpp (+67/-1)
src/scopes/internal/ScopeConfig.cpp (+7/-7)
src/scopes/internal/ScopeLoader.cpp (+4/-35)
src/scopes/internal/zmq_middleware/ZmqConfig.cpp (+1/-1)
test/CMakeLists.txt (+1/-0)
test/autopkg/CMakeLists.txt (+4/-0)
test/gtest/scopes/Activation/TestScope.h (+1/-1)
test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp (+1/-1)
test/gtest/scopes/IdleShutdown/SlowSearchScope.h (+1/-1)
test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp (+1/-1)
test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp (+1/-1)
test/gtest/scopes/Runtime/PusherScope.h (+5/-6)
test/gtest/scopes/Runtime/SlowCreateScope.h (+5/-6)
test/gtest/scopes/ScopeBase/ScopeBase_test.cpp (+1/-1)
test/gtest/scopes/ScopeBase/scopelib.cpp (+1/-1)
test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp (+1/-1)
test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in (+1/-0)
test/gtest/scopes/internal/ScopeLoader/MyScope.h (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp (+20/-26)
test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp (+1/-1)
test/gtest/scopes/testing/IsolatedScope/scope.cpp (+32/-5)
test/gtest/scopes/testing/IsolatedScope/scope.h (+15/-3)
test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp (+1/-1)
test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp (+1/-1)
test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h (+1/-1)
test/headers/CMakeLists.txt (+6/-3)
test/headers/check_public_headers.py (+1/-1)
To merge this branch: bzr merge lp:~michihenning/unity-scopes-api/scope-cache-dir
Reviewer Review Type Date Requested Status
Michal Hruby (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Jamie Strandboge Approve
Review via email: mp+225773@code.launchpad.net

Commit message

  - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.

  - Refactored scoperunner and ScopeLoader. ScopeLoader no longer knows about the registry and
    scoperunner now calls RuntimeImpl::run_scope() to set the scope running, instead of duplicating
    lots of functionality.

  - Removed registry parameter from ScopeBase::start(). The registry is now available via a registry()
    accessor on ScopeBase. The original start() method is still present, but deprecated. The default
    implementation of the new start() method forwards to the old one so, if a scope implements only the
    old one but not the new one, things still work.

  - Made methods on ScopeBase virtual, so the testing framework can override them in a test scope.

Description of the change

  - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.

  - Refactored scoperunner and ScopeLoader. ScopeLoader no longer knows about the registry and
    scoperunner now calls RuntimeImpl::run_scope() to set the scope running, instead of duplicating
    lots of functionality.

  - Removed registry parameter from ScopeBase::start(). The registry is now available via a registry()
    accessor on ScopeBase. The original start() method is still present, but deprecated. The default
    implementation of the new start() method forwards to the old one so, if a scope implements only the
    old one but not the new one, things still work.

  - Made methods on ScopeBase virtual, so the testing framework can override them in a test scope.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
403. By Michi Henning

Added encoding = utf-8 to file open(), so the 'ß' in Thomas's headers won't break
the tests :-)

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

43 + $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>
851 + data_dir_ + "/leaf-fs/" + scope_id_

The local content template doesn't exist, so there's no need to try to support it.

42 + $HOME/.local/share/unity-scopes/leaf-net/<scope_id>

Who's responsible for creating this directory? I suppose the leaf could be created by the scope itself (does it have permissions to do that?), but the parents have to be created by something unconfined, so who's doing it? The click hook?

review: Needs Information
Revision history for this message
Michal Hruby (mhr3) wrote :

41 + $HOME/.local/share/unity-scopes/aggregator/<scope_id>

Same as for leaf-fs, there's no apparmor template for aggregator scopes, so this should really be $HOME/.local/share/unity-scopes/unconfined/<scope_id>

Revision history for this message
Michi Henning (michihenning) wrote :

> 43 + $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>
> 851 + data_dir_ +
> "/leaf-fs/" + scope_id_
>
> The local content template doesn't exist, so there's no need to try to support
> it.

Not sure what you mean here. We have net, fs, and unconfined scopes. All of these can have a scratch area. I'm going by Jamie's comments here: https://bugs.launchpad.net/unity-scopes-api/+bug/1327426

> 42 + $HOME/.local/share/unity-scopes/leaf-net/<scope_id>
>
> Who's responsible for creating this directory? I suppose the leaf could be
> created by the scope itself (does it have permissions to do that?), but the
> parents have to be created by something unconfined, so who's doing it? The
> click hook?

Yes, the directory needs to be created as part of the installation.

Revision history for this message
Michi Henning (michihenning) wrote :

> 41 + $HOME/.local/share/unity-scopes/aggregator/<scope_id>
>
> Same as for leaf-fs, there's no apparmor template for aggregator scopes, so
> this should really be $HOME/.local/share/unity-scopes/unconfined/<scope_id>

Referring to: https://bugs.launchpad.net/unity-scopes-api/+bug/1327426

I don't mind whether we call it "aggregator" or "unconfined". Jamie?

Personally, I think "unconfined" is a slightly better name though. I think it better expresses the semantics, and we may want to have unconfined scopes at some point in the future that are not aggregators.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

There are plans to support the local content scope at some point and so I don't see any harm in using 'leaf-fs' for it. There is no reason why we couldn't also provide an aggregator template for us and trusted 3rd parties to use to help confine the scope somewhat (we just wouldn't make it available to unknown 3rd party developers). As for 'aggregator' vs 'unconfined', I personally like the idea of expressing the functionality there. While 'leaf-net', 'leaf-fs', 'aggregator' or anything else does have to do with what is expressed in the apparmor policy for the specified template, I'm not sure you want to have to worry about what templates are defined and what aren't in your code. Wouldn't it be best to just use these 3 different types so that if we ever supply the templates at a future date nothing in your code has to change?

Revision history for this message
Michi Henning (michihenning) wrote :

Hi Jamie, not totally sure whether your response is in favour of "aggregator" or "unconfined' here :-) Can you clarify?

As far as the scopes run time is concerned, all we care about is that there are three different kinds of scope who use different locations in the filesystem. So, I wouldn't really care if those locations were called "a", "b", and "c", and whether the directory names are the same as the apparmor policy or not.

Basically, all we need to do is agree on the three names :-)

Revision history for this message
Michal Hruby (mhr3) wrote :

> > 43 + $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>
> > 851 + data_dir_
> +
> > "/leaf-fs/" + scope_id_
> >
> > The local content template doesn't exist, so there's no need to try to
> support
> > it.
>
> Not sure what you mean here. We have net, fs, and unconfined scopes. All of
> these can have a scratch area. I'm going by Jamie's comments here:
> https://bugs.launchpad.net/unity-scopes-api/+bug/1327426

No, we don't support fs scopes, cause there are unresolved security issues with them.

Revision history for this message
Michal Hruby (mhr3) wrote :

374 - std::string scope_directory() const;
377 + virtual std::string scope_directory() const;
412 - VariantMap settings() const;
413 + virtual VariantMap settings() const;

I really don't like these changes, other than tests there's absolutely no reason for these to be virtual and therefore to allow the scope to override them. Can't we do something different, like setting a special envvar for the tests and have the impl look at that first? Yes, making it virtual does make it easily unit-testable, but imo such a test is really just testing itself.

404. By Michi Henning

Fixed broken autopkg test by changing code to match the new API.
Added build and run of the autopkg test to the test target. That
way, we'll at least notice if the code for the autopkg test
no longer compiles/runs.
Update HACKING for autopkg tests with instructions for how
to run the tests in a VM (thanks Saviq!) and a pointer to
the corresponding subdir in the test subtree, so we don't
forget to add new autopkg tests to the local test suite.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
405. By Michi Henning

Merged devel and resolved conflict.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
406. By Michi Henning

Added AbstractScopeBase and made the following
methods final in ScopeBase:

- scope_directory()
- cache_directory()
- registry()
- settings()

This allows the tests to mock a scope implementation
while preventing real scope implementations from overriding
methods they shouldn't override.

Revision history for this message
Michi Henning (michihenning) wrote :

> I really don't like these changes, other than tests there's absolutely no
> reason for these to be virtual and therefore to allow the scope to override
> them.

The testing frameworks needs to allow a scope to be mocked, so it's not just
our tests. But I agree, the scope author should not be able to override these.

> Can't we do something different, like setting a special envvar for the
> tests and have the impl look at that first? Yes, making it virtual does make
> it easily unit-testable, but imo such a test is really just testing itself.

No more env vars! I'm going to institute a blanket ban on them. The are worse
than global variables: not declared anywhere totally invisible.

I've made the relevant methods final in ScopeBase, so it's no longer possible
to override them.

407. By Michi Henning

Changed "aggregator" to "unconfined" when looking for cache directories.

Revision history for this message
Michi Henning (michihenning) wrote :

> 41 + $HOME/.local/share/unity-scopes/aggregator/<scope_id>
>
> Same as for leaf-fs, there's no apparmor template for aggregator scopes, so
> this should really be $HOME/.local/share/unity-scopes/unconfined/<scope_id>

OK, it's "unconfined" now. I've left leaf-fs there because Jamie mentioned that confined local content scopes might come back.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
408. By Michi Henning

Fixed symbols file.

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

602 virtual void start(std::string const& scope_id, RegistryProxy const& registry);

The point of keeping this was to preserve ABI compatibility, but with the introduction of AbstractScopeBase that is moot, so feel free to get rid of it.

Also, since it is breaking the ABI, we probably want to merge the 4.9 branch as well before the next "release" to distro?

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

"Hi Jamie, not totally sure whether your response is in favour of "aggregator" or "unconfined' here :-) Can you clarify?"

I preferred leaf-net, leaf-fs and aggregator so that you don't have to change your code if we ever do implement leaf-fs or aggregator policy in the future (note, just because we may never make these available to third party developers, it doesn't mean we won't want apparmor policy for our own stuff).

409. By Michi Henning

Removed deprecated start() method.

Revision history for this message
Michi Henning (michihenning) wrote :

> 602 virtual void start(std::string const& scope_id, RegistryProxy
> const& registry);
>
> The point of keeping this was to preserve ABI compatibility, but with the
> introduction of AbstractScopeBase that is moot, so feel free to get rid of it.

OK, done.

> Also, since it is breaking the ABI, we probably want to merge the 4.9 branch
> as well before the next "release" to distro?

Is the default gcc in distro 4.9 now? It would be good to merge, yes, but we also need to merge the 4.9 unity-api. And, once we've done that, there will essentially be no going back :-)

The (now inappropriately named) set-env-vars should also be merged in the same batch, because it adds another virtual to AbstractScopeBase.

Revision history for this message
Michi Henning (michihenning) wrote :

> I preferred leaf-net, leaf-fs and aggregator so that you don't have to change
> your code if we ever do implement leaf-fs or aggregator policy in the future
> (note, just because we may never make these available to third party
> developers, it doesn't mean we won't want apparmor policy for our own stuff).

Would the policy for an aggregator every be different from an unconfined scope?
I guess the question is whether I should use "leaf-fs", "leaf-net", "aggregator", and "unconfined"?

It's really neither here nor there to me--the list can be as long as we like and, if some of the directories in there don't exist, the right things still happen.

For the time being, I'll just check for both "aggregator" and "unconfined". That way, we have our bases covered. Michal, Jamie, please speak up if you think this is wrong or if I'm missing something!

410. By Michi Henning

Added "aggregator" to list of directories looked at for cache_directory().

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
411. By Michi Henning

Fixed symbols file by hand without gcc 4.8 installed. Fingers crossed...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
412. By Michi Henning

Fixed symbols file using gcc 4.8.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

> Who's responsible for creating this directory? I suppose the leaf could be
> created by the scope itself (does it have permissions to do that?), but the
> parents have to be created by something unconfined, so who's doing it? The
> click hook?

Yes, the directory needs to be created as part of the installation.

Still not solved afaict, without it, this branch is useless.

review: Needs Fixing
Revision history for this message
Michi Henning (michihenning) wrote :

> Yes, the directory needs to be created as part of the installation.
>
> Still not solved afaict, without it, this branch is useless.

Well, I wouldn't quite say "useless" because the branch will do the right thing once the directory is there :-)

I'll open a separate bug for this because that's really a separate issue.

Revision history for this message
Michi Henning (michihenning) wrote :
Revision history for this message
Michal Hruby (mhr3) wrote :

Sorry, didn't mean to sound harsh, but we need the dirs for scopes to be able to use this.

Revision history for this message
Michi Henning (michihenning) wrote :

> Sorry, didn't mean to sound harsh, but we need the dirs for scopes to be able
> to use this.

Not a problem, relax! :-)

Revision history for this message
Michi Henning (michihenning) wrote :

OK, so the approach of looking for the scope's data dir and setting cache_directory() to the right value isn't going to work because the click install can't create the directory.

So, next best idea:

The registry can look for each scope in the manifests and parse the JSON to figure out what kind of scope it is looking at. Then it can go to $HOME/.local/unity-scopes and create the scope cache directory if it doesn't exist, with permission 0700. The registry adds the scope cache directory to the scope's metadata, which is available remotely.

On the scope side, during initialization of the run time, we go to the registry and grab the metadata, so cache_directory() can return the correct location.

Down-sides and questions:

- If no registry is running, we have to wait for the metadata() call to time out. Currently, the default timeout is 5 seconds, due to the slow emulator problem. This will probably break some tests, and will be inconvenient during development. The work-around would be to change the default registry timeout to something short, so things don't hang around all the time waiting to time out.

- I can look through /var/lib/apparmor/clicks for JSON files. In there, I find things such as

com.ubuntu.clock_clock_1.0.430.json
com.ubuntu.music_music_1.3.511.json

When I look at the clock one, I see:

{
    "policy_groups": [
        "calendar",
        "networking"
        ],
    "policy_version": 1.1
}

When I look at the music one, I see:

{
    "policy_version": 1.2,
    "template": "unconfined",
    "policy_groups": []
}

So, it's not clear to me what exactly I should be parsing ("template" or "policy_groups") to figure out whether a scope is leaf-net or aggregator/unconfined.

- We have scopes that come pre-installed, scopes installed by the OEM, plus scopes installed by the user(s). Is it sufficient to look through /var/lib/apparmor/clicks to guarantee that I won't be missing any scopes? For the approach I outlined above, I need to be sure that I find something for every local scope.

- I'm questioning the wisdom of what I suggested above. It seems that the registry is forced to do a lot more than it should have to just so it can let a scope know what its writable tmp dir is. Isn't this something that should somehow be available via an apparmor call? Or should there be a way for click to be able to create the directory in the right place?

- There are potentially many cache and settings directories for a single scope (one for each user). When a new user is added to the device, who should create the cache dir and settings dir?

My apologies for all the questions, but it seems that I don't have all the pieces of the puzzle yet, so I don't want to rush and implement something only to have it fall over for some reason I don't know about. I'd appreciate any and all feedback!

Revision history for this message
Michi Henning (michihenning) wrote :

Following up on this:

> - I'm questioning the wisdom of what I suggested above. It seems that the
> registry is forced to do a lot more than it should have to

How is this going to work for apps? I expect that applications also will need a writable area in the file system somewhere. How do apps find out where they can write their files?

Revision history for this message
Michal Hruby (mhr3) wrote :

> On the scope side, during initialization of the run time, we go to the
> registry and grab the metadata, so cache_directory() can return the correct
> location.

Eh, remote call during startup? /me frowns.

>
> Down-sides and questions:
>
> - If no registry is running, we have to wait for the metadata() call to time
> out. Currently, the default timeout is 5 seconds, due to the slow emulator
> problem. This will probably break some tests, and will be inconvenient during
> development. The work-around would be to change the default registry timeout
> to something short, so things don't hang around all the time waiting to time
> out.
>
> - I can look through /var/lib/apparmor/clicks for JSON files. In there, I find
> things such as
>
> com.ubuntu.clock_clock_1.0.430.json
> com.ubuntu.music_music_1.3.511.json
>
> When I look at the clock one, I see:
>
> {
> "policy_groups": [
> "calendar",
> "networking"
> ],
> "policy_version": 1.1
> }
>
> When I look at the music one, I see:
>
> {
> "policy_version": 1.2,
> "template": "unconfined",
> "policy_groups": []
> }
>
> So, it's not clear to me what exactly I should be parsing ("template" or
> "policy_groups") to figure out whether a scope is leaf-net or
> aggregator/unconfined.

According to our tutorial:

> "template": "ubuntu-scope-network"

Is what you should find in the manifest.

> - We have scopes that come pre-installed, scopes installed by the OEM, plus
> scopes installed by the user(s). Is it sufficient to look through
> /var/lib/apparmor/clicks to guarantee that I won't be missing any scopes? For
> the approach I outlined above, I need to be sure that I find something for
> every local scope.

You won't, obviously only click-packaged scopes will have there something.

> - I'm questioning the wisdom of what I suggested above. It seems that the
> registry is forced to do a lot more than it should have to just so it can let
> a scope know what its writable tmp dir is. Isn't this something that should
> somehow be available via an apparmor call? Or should there be a way for click
> to be able to create the directory in the right place?

Sounds reasonable to me, but can't answer that.

>
> - There are potentially many cache and settings directories for a single scope
> (one for each user). When a new user is added to the device, who should create
> the cache dir and settings dir?

The registry again. Afterall it's run per-user.

Revision history for this message
Michal Hruby (mhr3) wrote :

> Following up on this:
>
> > - I'm questioning the wisdom of what I suggested above. It seems that the
> > registry is forced to do a lot more than it should have to
>
> How is this going to work for apps? I expect that applications also will need
> a writable area in the file system somewhere. How do apps find out where they
> can write their files?

https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement but iiuic Qt itself was patched to build the directory based on a few envvars. Imo we should just do the same, afterall the path has to be "prefix + scope_id", and the prefix can be passed as an envvar - it's not like a single process can be both unconfined and leaf-net at the same time.

Revision history for this message
Michi Henning (michihenning) wrote :

> https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement but
> iiuic Qt itself was patched to build the directory based on a few envvars. Imo
> we should just do the same, afterall the path has to be "prefix + scope_id",
> and the prefix can be passed as an envvar - it's not like a single process can
> be both unconfined and leaf-net at the same time.

I'm still not happy about this, as I mentioned earlier: if we have multiple instances of the run time in a single address space, the setting will be wrong for all but one of them.

But getting the value into the scope is just a side-issue. The real problem is that I don't know how to figure out what to set "prefix" to. It seems I can't even reliably get at all the manifests for pre-installed, OEM, and click scopes.

Jamie, instead of having something like $HOME/.local/share/unity-scopes/leaf-net/<scope_id>, could we get rid of the "leaf-fs"/"leaf-net"/"aggregator"/"confined" sub-directory?

If so, we could just make it $HOME/.local/share/unity-scopes/data_home/<scope_id>.

The core problem here is that I don't know which confinement profile belongs to what scope ID, so I don't know how to set the path correctly. If we have a path that doesn't change depending on the confinement profile, the problem would go away because the prefix would be independent of the confinement type.

Revision history for this message
Michal Hruby (mhr3) wrote :

> > https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement
> but
> > iiuic Qt itself was patched to build the directory based on a few envvars.
> Imo
> > we should just do the same, afterall the path has to be "prefix + scope_id",
> > and the prefix can be passed as an envvar - it's not like a single process
> can
> > be both unconfined and leaf-net at the same time.
>
> I'm still not happy about this, as I mentioned earlier: if we have multiple
> instances of the run time in a single address space, the setting will be wrong
> for all but one of them.

My point was that you can apply only one apparmor profile, so if there are multiple runtimes and scopes in a single process, they either have to share the apparmor template or need to be unconfined, otherwise things won't work anyway. So the prefix is indeed per process, not per runtime.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

> > https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement
> but
> > iiuic Qt itself was patched to build the directory based on a few envvars.
> Imo
> > we should just do the same, afterall the path has to be "prefix + scope_id",
> > and the prefix can be passed as an envvar - it's not like a single process
> can
> > be both unconfined and leaf-net at the same time.
>
> I'm still not happy about this, as I mentioned earlier: if we have multiple
> instances of the run time in a single address space, the setting will be wrong
> for all but one of them.
>
> But getting the value into the scope is just a side-issue. The real problem is
> that I don't know how to figure out what to set "prefix" to. It seems I can't
> even reliably get at all the manifests for pre-installed, OEM, and click
> scopes.
>
> Jamie, instead of having something like $HOME/.local/share/unity-scopes/leaf-
> net/<scope_id>, could we get rid of the "leaf-fs"/"leaf-
> net"/"aggregator"/"confined" sub-directory?
>
> If so, we could just make it $HOME/.local/share/unity-
> scopes/data_home/<scope_id>.
>
> The core problem here is that I don't know which confinement profile belongs
> to what scope ID, so I don't know how to set the path correctly. If we have a
> path that doesn't change depending on the confinement profile, the problem
> would go away because the prefix would be independent of the confinement type.

As mentioned, that breaks the confinement separation for the case when a scope changes from leaf-fs to leaf-net. We need to have these scope type (eg, leaf-net, leaf-fs) for whenever we confine both types. Putting it in $HOME/.local/share/unity-scopes/<scope_id> or $HOME/.local/share/unity-copes/data_home/<scope_id> breaks that. People have asked what apps do: apps are different because there is no concept of 'local-fs'. All apps are expected to be able to have network access to all the app templates are very tightly confined. leaf-fs and aggregator scopes are very different from apps in that by design they need wide access to the user's data.

Why not just add this to the scope runner .ini file:
[ScopeConfig]
Type=Network # or LocalContent or Aggregator

The downside is the scope author has to keep this in sync with the declared template in the security manifest, but that is something the SDK can help with (not to mention, people shouldn't be changing from one scope type to another except in the most unusual circumstances).

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

> > Who's responsible for creating this directory? I suppose the leaf could be
> > created by the scope itself (does it have permissions to do that?), but the
> > parents have to be created by something unconfined, so who's doing it? The
> > click hook?
>
> Yes, the directory needs to be created as part of the installation.
>
> Still not solved afaict, without it, this branch is useless.

The leaf-net, leaf-fs, or aggregator directories can all be unconditionally created by the scope click hook if they don't already exist. The scope click hook could also consider a new 'Type' field added to ScopeConfig (see below for discussion), but I don't think it needs to (just create all 3 and be done with it).

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

> > I preferred leaf-net, leaf-fs and aggregator so that you don't have to
> change
> > your code if we ever do implement leaf-fs or aggregator policy in the future
> > (note, just because we may never make these available to third party
> > developers, it doesn't mean we won't want apparmor policy for our own
> stuff).
>
> Would the policy for an aggregator every be different from an unconfined
> scope?
> I guess the question is whether I should use "leaf-fs", "leaf-net",
> "aggregator", and "unconfined"?
>
> It's really neither here nor there to me--the list can be as long as we like
> and, if some of the directories in there don't exist, the right things still
> happen.
>
> For the time being, I'll just check for both "aggregator" and "unconfined".
> That way, we have our bases covered. Michal, Jamie, please speak up if you
> think this is wrong or if I'm missing something!

I think it is conceivable that an aggregator can be confined, especially when considering that we might want to confine it for code execution, etc even if the aggregator is still only for trusted 3rd parties. I don't think the scopes team should worry about what confinement goes with what-- just worry about keeping the types (leaf-net, leaf-fs, aggregator, whatever) separate and don't let them share writable when changing between them with the understanding that confinement will enforce this separation.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

> > Following up on this:
> >
> > > - I'm questioning the wisdom of what I suggested above. It seems that the
> > > registry is forced to do a lot more than it should have to
> >
> > How is this going to work for apps? I expect that applications also will
> need
> > a writable area in the file system somewhere. How do apps find out where
> they
> > can write their files?
>
> https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement but
> iiuic Qt itself was patched to build the directory based on a few envvars. Imo
> we should just do the same, afterall the path has to be "prefix + scope_id",
> and the prefix can be passed as an envvar - it's not like a single process can
> be both unconfined and leaf-net at the same time.

The app toolkits all understand XDG We make sure all the XDG directories are set correctly to *system* values, not app-specific values. Then have the app declare its applicationName. The toolkits all known how to known to append applicationName to the XDG directories (this is standard practice going back years and years). Applications can then use QStandardPath to query for these values.

As mentioned, apps are quite different than scopes and there is no concept of 'an app has wide filesystem/data access but no network access). All apps are assumed that they may have networking and therefore all apps are very tightly confined wrt filesystem/data access, so there is no need draw a distinction between app templates like we are for scope templates.

We can use the same idea for scopes though-- just like applications declare their applicationName in their QML and that adjusts their application directories, scopes can declare in their .ini file what scope type they are which will adjust their writable scope directory.

Revision history for this message
Michi Henning (michihenning) wrote :

> My point was that you can apply only one apparmor profile, so if there are
> multiple runtimes and scopes in a single process, they either have to share
> the apparmor template or need to be unconfined, otherwise things won't work
> anyway. So the prefix is indeed per process, not per runtime.

Ah, yes, that's true. I'm still trying to avoid environment variables though,
for the simple reason that they are global hidden state. The less we use
env vars, the better, IMO.

Revision history for this message
Michi Henning (michihenning) wrote :

> > Yes, the directory needs to be created as part of the installation.
> >
> > Still not solved afaict, without it, this branch is useless.
>
> The leaf-net, leaf-fs, or aggregator directories can all be unconditionally
> created by the scope click hook if they don't already exist. The scope click
> hook could also consider a new 'Type' field added to ScopeConfig (see below
> for discussion), but I don't think it needs to (just create all 3 and be done
> with it).

One thing I don't understand here: because the dir is underneath $HOME, that means the click hook would have to create the dir for *all* users of the device? What if a user is added later, after a scope was installed? In that case, whatever script runs to add a user would have to make sure that this directory is create along with everything else.

Unless I'm missing something, this seems brittle to me.

Revision history for this message
Michi Henning (michihenning) wrote :

> I think it is conceivable that an aggregator can be confined, especially when
> considering that we might want to confine it for code execution, etc even if
> the aggregator is still only for trusted 3rd parties. I don't think the scopes
> team should worry about what confinement goes with what-- just worry about
> keeping the types (leaf-net, leaf-fs, aggregator, whatever) separate and don't
> let them share writable when changing between them with the understanding that
> confinement will enforce this separation.

Yes, I like this. The less we tie the semantics together, the better.

Revision history for this message
Michi Henning (michihenning) wrote :

> > The core problem here is that I don't know which confinement profile belongs
> > to what scope ID, so I don't know how to set the path correctly. If we have
> a
> > path that doesn't change depending on the confinement profile, the problem
> > would go away because the prefix would be independent of the confinement
> type.
>
> As mentioned, that breaks the confinement separation for the case when a scope
> changes from leaf-fs to leaf-net. We need to have these scope type (eg, leaf-
> net, leaf-fs) for whenever we confine both types. Putting it in
> $HOME/.local/share/unity-scopes/<scope_id> or $HOME/.local/share/unity-
> copes/data_home/<scope_id> breaks that.

Right, yes, this makes sense, thanks!

> Why not just add this to the scope runner .ini file:
> [ScopeConfig]
> Type=Network # or LocalContent or Aggregator

I think this approach has merit, at least to tidy us over until after RTM. I could make the setting optional, with the default being Type=Network. That means the setting would effectively be invisible to scope authors (though still documented), and only aggregators (us, mostly) would need to set it.

The path would be set accordingly, as "leaf-net" or "unconfined".

Directory creation can be done by the scoperunner, I think: if the directory doesn't exist, it'll be created on the fly.

> The downside is the scope author has to keep this in sync with the declared
> template in the security manifest, but that is something the SDK can help with
> (not to mention, people shouldn't be changing from one scope type to another
> except in the most unusual circumstances).

Seeing that, at the moment, we have only two policies for scopes, I don't think that's a big deal. Longer term, once we have a fancier Apparmor query API, we should be able to ditch the config item again and just rely on what we learn from the query API. What I would like to have from the API is functionality that allows me to ask the question "what is the root of my writable data area?"

Ideally, I should get an answer even if that directory doesn't exist yet. And, if it doesn't exist, I should still be able to create that (and only that) directory. That way, the scoperunner wouldn't have to do anything on behalf of the scope before exec'ing it. Instead, the scope, after it was exec'd (and is confined already), could still create its own data directory if it doesn't exist.

413. By Michi Henning

Changed the way cache_directory() is set. New config setting
in <scope_id>.ini, ConfinementType, now determines the
confinement type, which is part of the path for the cache
directory. scoperegistry creates the cache directory if
it doesn't exist.

414. By Michi Henning

Merged devel.

415. By Michi Henning

Updated symbols file.

Revision history for this message
Michi Henning (michihenning) wrote :

OK, latest version now uses a ConfinementType setting in <scope_id>.ini.

The setting can be either "leaf-net" or "unconfined".

The default is "leaf-net", so scope authors are unaffected. If an unconfined scope wants to use the cache dir, it needs to set this to "unconfined".

cache_directory() returns the appropriate path, with the type substituted:

$HOME/.local/share/unity-scopes/<type>/<scope_id>

The registry creates the directory if it doesn't exist, with permissions 0700.

For now, I think this is good enough. It gets us off the hook until Apparmor can provide a fancier query API.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Jamie Strandboge (jdstrand) wrote :

> > > Yes, the directory needs to be created as part of the installation.
> > >
> > > Still not solved afaict, without it, this branch is useless.
> >
> > The leaf-net, leaf-fs, or aggregator directories can all be unconditionally
> > created by the scope click hook if they don't already exist. The scope click
> > hook could also consider a new 'Type' field added to ScopeConfig (see below
> > for discussion), but I don't think it needs to (just create all 3 and be
> done
> > with it).
>
> One thing I don't understand here: because the dir is underneath $HOME, that
> means the click hook would have to create the dir for *all* users of the
> device? What if a user is added later, after a scope was installed? In that
> case, whatever script runs to add a user would have to make sure that this
> directory is create along with everything else.
>
> Unless I'm missing something, this seems brittle to me.

That is the job of the click hook system. We don't support multi-user yet, but when we do, click user hooks will have to be run anyway. When the click user hooks are run on adding a new user, you get this for free.

In other words-- running click user hooks (of which the scope is but one) have to be solved for the case you mentioned anyway. Nothing special has to be done for scopes when it is.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :
Download full text (3.1 KiB)

> > > The core problem here is that I don't know which confinement profile
> belongs
> > > to what scope ID, so I don't know how to set the path correctly. If we
> have
> > a
> > > path that doesn't change depending on the confinement profile, the problem
> > > would go away because the prefix would be independent of the confinement
> > type.
> >
> > As mentioned, that breaks the confinement separation for the case when a
> scope
> > changes from leaf-fs to leaf-net. We need to have these scope type (eg,
> leaf-
> > net, leaf-fs) for whenever we confine both types. Putting it in
> > $HOME/.local/share/unity-scopes/<scope_id> or $HOME/.local/share/unity-
> > copes/data_home/<scope_id> breaks that.
>
> Right, yes, this makes sense, thanks!
>
> > Why not just add this to the scope runner .ini file:
> > [ScopeConfig]
> > Type=Network # or LocalContent or Aggregator
>
> I think this approach has merit, at least to tidy us over until after RTM. I
> could make the setting optional, with the default being Type=Network. That
> means the setting would effectively be invisible to scope authors (though
> still documented), and only aggregators (us, mostly) would need to set it.
>
> The path would be set accordingly, as "leaf-net" or "unconfined".
>
> Directory creation can be done by the scoperunner, I think: if the directory
> doesn't exist, it'll be created on the fly.
>
> > The downside is the scope author has to keep this in sync with the declared
> > template in the security manifest, but that is something the SDK can help
> with
> > (not to mention, people shouldn't be changing from one scope type to another
> > except in the most unusual circumstances).
>
> Seeing that, at the moment, we have only two policies for scopes, I don't
> think that's a big deal. Longer term, once we have a fancier Apparmor query
> API, we should be able to ditch the config item again and just rely on what we
> learn from the query API. What I would like to have from the API is
> functionality that allows me to ask the question "what is the root of my
> writable data area?"
>
> Ideally, I should get an answer even if that directory doesn't exist yet. And,
> if it doesn't exist, I should still be able to create that (and only that)
> directory. That way, the scoperunner wouldn't have to do anything on behalf of
> the scope before exec'ing it. Instead, the scope, after it was exec'd (and is
> confined already), could still create its own data directory if it doesn't
> exist.

The libapparmor query API won't be able to answer 'what is the base of my writable area'. It will be able to say 'can I write to $HOME/.local/share/unity-scopes/leaf-net/<scope_id>' or 'can I write to $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>' so you can determine which is your writable area.

IMPORTANT: I think this is understood, the confined process will be able to create the '<scope id>' subdirectory (eg, $HOME/.local/share/unity-scopes/leaf-net/<scope_id>), so the scoperunner/API can do that. The confined process will *not* be able to create the 'scope type' directory (eg, $HOME/.local/share/unity-scopes/leaf-net), which is why I said the scope click user hook could just make su...

Read more...

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

I am going to approve this, for my part. I did glance through the code and made a couple of inline comments. While I do think the approach here couples the scope type with security policy more than is required, I understand that this is temporary until we have the libapparmor query interface up and running for files. For now, we only have leaf-net and unconfined and this MR handles that. By the looks of it, it shouldn't be difficult to transition away from ConfinementType when you move to the apparmor query API, and after you do, maintenance of that bit of code shouldn't be much more than managing an 'if/else if/else' statement.

review: Approve
Revision history for this message
Michal Hruby (mhr3) wrote :

> IMPORTANT: I think this is understood, the confined process will be able to
> create the '<scope id>' subdirectory (eg, $HOME/.local/share/unity-scopes
> /leaf-net/<scope_id>), so the scoperunner/API can do that.

This actually wasn't clear, if that's the case, I think the scope itself should just try to create / open the dir and use that, then we don't need a new config item that would just be deprecated as soon as possible. (and scoperegistry can just create the parent dirs unconditionally)

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

> > IMPORTANT: I think this is understood, the confined process will be able to
> > create the '<scope id>' subdirectory (eg, $HOME/.local/share/unity-scopes
> > /leaf-net/<scope_id>), so the scoperunner/API can do that.
>
> This actually wasn't clear, if that's the case, I think the scope itself
> should just try to create / open the dir and use that, then we don't need a
> new config item that would just be deprecated as soon as possible. (and
> scoperegistry can just create the parent dirs unconditionally)

As long as the process creating the $HOME/.local/share/unity-scopes/leaf-net/ is unconfined, it doesn't matter who creates it. However, don't you still need the config item for the API to know what to return to the confined process so it can create $HOME/.local/share/unity-scopes/leaf-net/<scope_id>?

416. By Michi Henning

Backed out changes for config file setting. Using the
try-and-make-conclusions-if-it-doesn't-work approach now.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
417. By Michi Henning

Merged devel and resolved conflicts.

418. By Michi Henning

scoperegistry now creates the root of the data directory for confined
scopes, e.g. $HOME/.local/share/unity-scopes/leaf-net.

The directory <scope_id> within that directory is created by
each confined scope itself when the scope is run.
(The scope's Apparmor profile allows this.)

Revision history for this message
Michi Henning (michihenning) wrote :

The registry now creates the leaf-net directory in case it isn't there already, e.g

$HOME/.local/share/unity-scopes/leaf-net

The <scope_id> subdir under that is created by each confined scope itself when it
is run.

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

Merged devel and resolved conflicts.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

Let's merge this and fix any remaining issues afterwards, it's been sitting here for far too long.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CONFIGFILES'
--- CONFIGFILES 2014-07-21 06:34:24 +0000
+++ CONFIGFILES 2014-07-28 11:21:43 +0000
@@ -92,7 +92,7 @@
9292
93- DataDir93- DataDir
9494
95 The parent directory under the run time writes scope-specific data files95 The parent directory under which the run time writes scope-specific data files
96 (such as settings).96 (such as settings).
9797
98 The default value is $HOME/.local/share/unity-scopes.98 The default value is $HOME/.local/share/unity-scopes.
9999
=== modified file 'HACKING'
--- HACKING 2014-06-26 15:53:22 +0000
+++ HACKING 2014-07-28 11:21:43 +0000
@@ -193,12 +193,17 @@
193Running the test manually is simple. After building and installing the193Running the test manually is simple. After building and installing the
194new packages, just run 'sh debian/tests/scopebuild'.194new packages, just run 'sh debian/tests/scopebuild'.
195195
196When making API breaks, make sure to check if autopkg test scripts196To run the autopkg tests the same way Jenkins does, without installing
197need changing. The point of autopkg is not to exercise the API197the packages, follow the instructions here:
198thoroughly, so it should not need changing all that often.198
199199http://packaging.ubuntu.com/html/auto-pkg-test.html
200At the moment it is unclear if these tests are executed during Jenkins200
201builds. This will lead to autopkgtest failing later if scopes' API is201When adding new tests to debian/tests, be sure that the new tests
202changed in a backwards incompatible way. If this happens the test202are built and run by adding them to tests/autopkg. Doing this doesn't
203needs to be fixed either by updating the test or backing out the API203run the tests exactly the same way as on Jenkins because they will
204breaking change.204be built and run against the headers and library in the build area,
205rather than against the installed packages. But it provides a basic
206sanity check for them. Without this, it's very easy to make a breaking
207change to the API and forgetting to update the autopkg tests too,
208meaning that the failure will show up only in Jenkins, but not
209when running the tests locally.
205210
=== modified file 'RELEASE_NOTES.md'
--- RELEASE_NOTES.md 2014-07-24 12:12:13 +0000
+++ RELEASE_NOTES.md 2014-07-28 11:21:43 +0000
@@ -3,8 +3,23 @@
33
4Changes in version 0.6.04Changes in version 0.6.0
5========================5========================
6 - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.
7
8 - Refactored scoperunner and ScopeLoader. ScopeLoader no longer knows about the registry and
9 scoperunner now calls RuntimeImpl::run_scope() to set the scope running, instead of duplicating
10 lots of functionality.
11
12 - Removed registry parameter from ScopeBase::start(). The registry is now available via a registry()
13 accessor on ScopeBase. The original start() method is still present, but deprecated. The default
14 implementation of the new start() method forwards to the old one so, if a scope implements only the
15 old one but not the new one, things still work.
16
17 - Made methods on ScopeBase virtual, so the testing framework can override them in a test scope.
18
6 - Added support for additional query reply info.19 - Added support for additional query reply info.
20
7 - Introduced QueryMetadata base for shared functionality of *Metadata classes.21 - Introduced QueryMetadata base for shared functionality of *Metadata classes.
22
8 - Added set_internet_connectivity() and internet_connectivity() to QueryMetadata.23 - Added set_internet_connectivity() and internet_connectivity() to QueryMetadata.
924
10Changes in version 0.5.225Changes in version 0.5.2
1126
=== modified file 'debian/changelog'
--- debian/changelog 2014-07-28 10:02:00 +0000
+++ debian/changelog 2014-07-28 11:21:43 +0000
@@ -1,10 +1,13 @@
1unity-scopes-api (0.6.0-0ubuntu1) UNRELEASED; urgency=medium1unity-scopes-api (0.6.0-0ubuntu1) UNRELEASED; urgency=medium
22
3 * Added support for additional query reply info.3 * Added cache_directory() method and refactored scoperunner and RuntimeImpl.
4
5 [ Marcus Tomlinson ]
4 * Introduced QueryMetadata base for shared functionality of *Metadata classes.6 * Introduced QueryMetadata base for shared functionality of *Metadata classes.
5 * Added set_internet_connectivity() and internet_connectivity() to QueryMetadata.7 * Added set_internet_connectivity() and internet_connectivity() to QueryMetadata.
8 * Added support for additional query reply info.
69
7 -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Mon, 21 Jul 2014 09:14:39 +020010 -- Michi Henning <michi.henning@canonical.com> Mon, 07 Jul 2014 14:34:04 +1000
811
9unity-scopes-api (0.5.2+14.10.20140723-0ubuntu1) utopic; urgency=low12unity-scopes-api (0.5.2+14.10.20140723-0ubuntu1) utopic; urgency=low
1013
1114
=== modified file 'debian/libunity-scopes2.symbols'
--- debian/libunity-scopes2.symbols 2014-07-28 10:02:00 +0000
+++ debian/libunity-scopes2.symbols 2014-07-28 11:21:43 +0000
@@ -408,8 +408,10 @@
408 (c++)"unity::scopes::testing::Benchmark::Result::load_from(std::basic_istream<char, std::char_traits<char> >&)@Base" 0.4.0+14.04.20140312.1408 (c++)"unity::scopes::testing::Benchmark::Result::load_from(std::basic_istream<char, std::char_traits<char> >&)@Base" 0.4.0+14.04.20140312.1
409 (c++)"unity::scopes::testing::operator==(unity::scopes::testing::Benchmark::Result const&, unity::scopes::testing::Benchmark::Result const&)@Base" 0.4.0+14.04.20140312.1409 (c++)"unity::scopes::testing::operator==(unity::scopes::testing::Benchmark::Result const&, unity::scopes::testing::Benchmark::Result const&)@Base" 0.4.0+14.04.20140312.1
410 (c++)"unity::scopes::testing::operator<<(std::basic_ostream<char, std::char_traits<char> >&, unity::scopes::testing::Benchmark::Result const&)@Base" 0.4.0+14.04.20140312.1410 (c++)"unity::scopes::testing::operator<<(std::basic_ostream<char, std::char_traits<char> >&, unity::scopes::testing::Benchmark::Result const&)@Base" 0.4.0+14.04.20140312.1
411 (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::CategoryRenderer const&)@Base" 0.4.0+14.04.20140312.1411 (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::CategoryRenderer const&)@Base" 0replaceme
412 (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::CannedQuery const> const&, unity::scopes::CategoryRenderer const&)@Base" 0replaceme
412 (c++)"unity::scopes::Category::Category(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.0+14.04.20140312.1413 (c++)"unity::scopes::Category::Category(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.0+14.04.20140312.1
414 (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::CategoryRenderer const&)@Base" 0replaceme
413 (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::CannedQuery const> const&, unity::scopes::CategoryRenderer const&)@Base" 0.5.2+14.10.20140709.2415 (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::CannedQuery const> const&, unity::scopes::CategoryRenderer const&)@Base" 0.5.2+14.10.20140709.2
414 (c++)"unity::scopes::Category::Category(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.0+14.04.20140312.1416 (c++)"unity::scopes::Category::Category(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.0+14.04.20140312.1
415 (c++)"unity::scopes::Category::~Category()@Base" 0.4.0+14.04.20140312.1417 (c++)"unity::scopes::Category::~Category()@Base" 0.4.0+14.04.20140312.1
@@ -424,11 +426,11 @@
424 (c++)"unity::scopes::internal::ScopeConfig::parse_appearance_attribute(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.5.2+14.10.20140709.2426 (c++)"unity::scopes::internal::ScopeConfig::parse_appearance_attribute(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.5.2+14.10.20140709.2
425 (c++)"unity::scopes::internal::ScopeConfig::ScopeConfig(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1427 (c++)"unity::scopes::internal::ScopeConfig::ScopeConfig(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1
426 (c++)"unity::scopes::internal::ScopeConfig::~ScopeConfig()@Base" 0.4.0+14.04.20140312.1428 (c++)"unity::scopes::internal::ScopeConfig::~ScopeConfig()@Base" 0.4.0+14.04.20140312.1
427 (c++)"unity::scopes::internal::ScopeLoader::load(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::Registry> const&)@Base" 0.5.2+14.10.20140709.2429 (c++)"unity::scopes::internal::ScopeLoader::load(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme
428 (c++)"unity::scopes::internal::ScopeLoader::stop()@Base" 0.4.0+14.04.20140312.1430 (c++)"unity::scopes::internal::ScopeLoader::stop()@Base" 0.4.0+14.04.20140312.1
429 (c++)"unity::scopes::internal::ScopeLoader::start()@Base" 0.4.0+14.04.20140312.1431 (c++)"unity::scopes::internal::ScopeLoader::start()@Base" 0.4.0+14.04.20140312.1
430 (c++)"unity::scopes::internal::ScopeLoader::unload()@Base" 0.4.0+14.04.20140312.1432 (c++)"unity::scopes::internal::ScopeLoader::unload()@Base" 0.4.0+14.04.20140312.1
431 (c++)"unity::scopes::internal::ScopeLoader::ScopeLoader(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::Registry> const&)@Base" 0.5.2+14.10.20140709.2433 (c++)"unity::scopes::internal::ScopeLoader::ScopeLoader(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme
432 (c++)"unity::scopes::internal::ScopeLoader::~ScopeLoader()@Base" 0.4.0+14.04.20140312.1434 (c++)"unity::scopes::internal::ScopeLoader::~ScopeLoader()@Base" 0.4.0+14.04.20140312.1
433 (c++)"unity::scopes::internal::ScopeObject::perform_action(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1435 (c++)"unity::scopes::internal::ScopeObject::perform_action(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
434 (c++)"unity::scopes::internal::ScopeObject::query(std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::MiddlewareBase*, std::function<std::shared_ptr<unity::scopes::QueryBase> ()> const&, std::function<std::shared_ptr<unity::scopes::internal::QueryObjectBase> (std::shared_ptr<unity::scopes::QueryBase>, std::shared_ptr<unity::scopes::internal::MWQueryCtrl>)> const&)@Base" 0.4.0+14.04.20140312.1436 (c++)"unity::scopes::internal::ScopeObject::query(std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::MiddlewareBase*, std::function<std::shared_ptr<unity::scopes::QueryBase> ()> const&, std::function<std::shared_ptr<unity::scopes::internal::QueryObjectBase> (std::shared_ptr<unity::scopes::QueryBase>, std::shared_ptr<unity::scopes::internal::MWQueryCtrl>)> const&)@Base" 0.4.0+14.04.20140312.1
@@ -545,7 +547,7 @@
545 (c++)"unity::scopes::ScopeBase::runtime_version(int&, int&, int&)@Base" 0.4.0+14.04.20140312.1547 (c++)"unity::scopes::ScopeBase::runtime_version(int&, int&, int&)@Base" 0.4.0+14.04.20140312.1
546 (c++)"unity::scopes::ScopeBase::run()@Base" 0.4.0+14.04.20140312.1548 (c++)"unity::scopes::ScopeBase::run()@Base" 0.4.0+14.04.20140312.1
547 (c++)"unity::scopes::ScopeBase::stop()@Base" 0.5.0+14.10.20140619549 (c++)"unity::scopes::ScopeBase::stop()@Base" 0.5.0+14.10.20140619
548 (c++)"unity::scopes::ScopeBase::start(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::Registry> const&)@Base" 0.5.0+14.10.20140619550 (c++)"unity::scopes::ScopeBase::start(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme
549 (c++)"unity::scopes::ScopeBase::activate(unity::scopes::Result const&, unity::scopes::ActionMetadata const&)@Base" 0.4.0+14.04.20140312.1551 (c++)"unity::scopes::ScopeBase::activate(unity::scopes::Result const&, unity::scopes::ActionMetadata const&)@Base" 0.4.0+14.04.20140312.1
550 (c++)"unity::scopes::ScopeBase::ScopeBase()@Base" 0.4.0+14.04.20140312.1552 (c++)"unity::scopes::ScopeBase::ScopeBase()@Base" 0.4.0+14.04.20140312.1
551 (c++)"unity::scopes::ScopeBase::~ScopeBase()@Base" 0.4.0+14.04.20140312.1553 (c++)"unity::scopes::ScopeBase::~ScopeBase()@Base" 0.4.0+14.04.20140312.1
@@ -733,6 +735,7 @@
733 (c++)"unity::scopes::internal::RuntimeImpl::reply_reaper() const@Base" 0.4.0+14.04.20140312.1735 (c++)"unity::scopes::internal::RuntimeImpl::reply_reaper() const@Base" 0.4.0+14.04.20140312.1
734 (c++)"unity::scopes::internal::RuntimeImpl::ss_configfile() const@Base" 0.4.4+14.10.20140508736 (c++)"unity::scopes::internal::RuntimeImpl::ss_configfile() const@Base" 0.4.4+14.10.20140508
735 (c++)"unity::scopes::internal::RuntimeImpl::waiter_thread(std::shared_ptr<unity::scopes::internal::ThreadSafeQueue<std::future<void> > > const&) const@Base" 0.4.3+14.10.20140428737 (c++)"unity::scopes::internal::RuntimeImpl::waiter_thread(std::shared_ptr<unity::scopes::internal::ThreadSafeQueue<std::future<void> > > const&) const@Base" 0.4.3+14.10.20140428
738 (c++)"unity::scopes::internal::RuntimeImpl::find_cache_dir() const@Base" 0replaceme
736 (c++)"unity::scopes::internal::RuntimeImpl::proxy_to_string(std::shared_ptr<unity::scopes::Object> const&) const@Base" 0.4.0+14.04.20140312.1739 (c++)"unity::scopes::internal::RuntimeImpl::proxy_to_string(std::shared_ptr<unity::scopes::Object> const&) const@Base" 0.4.0+14.04.20140312.1
737 (c++)"unity::scopes::internal::RuntimeImpl::string_to_proxy(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const@Base" 0.4.0+14.04.20140312.1740 (c++)"unity::scopes::internal::RuntimeImpl::string_to_proxy(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const@Base" 0.4.0+14.04.20140312.1
738 (c++)"unity::scopes::internal::RuntimeImpl::registry_identity() const@Base" 0.4.0+14.04.20140312.1741 (c++)"unity::scopes::internal::RuntimeImpl::registry_identity() const@Base" 0.4.0+14.04.20140312.1
@@ -815,9 +818,11 @@
815 (c++)"unity::scopes::internal::JsonSettingsSchema::definitions() const@Base" 0.5.2+14.10.20140709.2818 (c++)"unity::scopes::internal::JsonSettingsSchema::definitions() const@Base" 0.5.2+14.10.20140709.2
816 (c++)"unity::scopes::internal::StateReceiverObject::state_received() const@Base" 0.4.2+14.04.20140404.2819 (c++)"unity::scopes::internal::StateReceiverObject::state_received() const@Base" 0.4.2+14.04.20140404.2
817 (c++)"unity::scopes::QueryBase::valid() const@Base" 0.4.3+14.10.20140428820 (c++)"unity::scopes::QueryBase::valid() const@Base" 0.4.3+14.10.20140428
818 (c++)"unity::scopes::QueryBase::settings() const@Base" 0.5.2+14.10.20140709.2821 (c++)"unity::scopes::QueryBase::settings() const@Base" 0replaceme
822 (c++)"unity::scopes::ScopeBase::cache_directory() const@Base" 0replaceme
819 (c++)"unity::scopes::ScopeBase::scope_directory() const@Base" 0.4.2+14.04.20140404.2823 (c++)"unity::scopes::ScopeBase::scope_directory() const@Base" 0.4.2+14.04.20140404.2
820 (c++)"unity::scopes::ScopeBase::settings() const@Base" 0.5.2+14.10.20140709.2824 (c++)"unity::scopes::ScopeBase::registry() const@Base" 0replaceme
825 (c++)"unity::scopes::ScopeBase::settings() const@Base" 0replaceme
821 (c++)"typeinfo for unity::scopes::FilterBase@Base" 0.4.0+14.04.20140312.1826 (c++)"typeinfo for unity::scopes::FilterBase@Base" 0.4.0+14.04.20140312.1
822 (c++)"typeinfo for unity::scopes::SearchReply@Base" 0.4.0+14.04.20140312.1827 (c++)"typeinfo for unity::scopes::SearchReply@Base" 0.4.0+14.04.20140312.1
823 (c++)"typeinfo for unity::scopes::ListenerBase@Base" 0.4.0+14.04.20140312.1828 (c++)"typeinfo for unity::scopes::ListenerBase@Base" 0.4.0+14.04.20140312.1
@@ -838,6 +843,7 @@
838 (c++)"typeinfo for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1843 (c++)"typeinfo for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1
839 (c++)"typeinfo for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1844 (c++)"typeinfo for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1
840 (c++)"typeinfo for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1845 (c++)"typeinfo for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1
846 (c++)"typeinfo for unity::scopes::AbstractScopeBase@Base" 0replaceme
841 (c++)"typeinfo for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1847 (c++)"typeinfo for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1
842 (c++)"typeinfo for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1848 (c++)"typeinfo for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1
843 (c++)"typeinfo for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1849 (c++)"typeinfo for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1
@@ -883,6 +889,7 @@
883 (c++)"typeinfo name for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1889 (c++)"typeinfo name for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1
884 (c++)"typeinfo name for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1890 (c++)"typeinfo name for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1
885 (c++)"typeinfo name for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1891 (c++)"typeinfo name for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1
892 (c++)"typeinfo name for unity::scopes::AbstractScopeBase@Base" 0replaceme
886 (c++)"typeinfo name for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1893 (c++)"typeinfo name for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1
887 (c++)"typeinfo name for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1894 (c++)"typeinfo name for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1
888 (c++)"typeinfo name for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1895 (c++)"typeinfo name for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1
@@ -939,6 +946,7 @@
939 (c++)"vtable for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1946 (c++)"vtable for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1
940 (c++)"vtable for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1947 (c++)"vtable for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1
941 (c++)"vtable for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1948 (c++)"vtable for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1
949 (c++)"vtable for unity::scopes::AbstractScopeBase@Base" 0replaceme
942 (c++)"vtable for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1950 (c++)"vtable for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1
943 (c++)"vtable for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1951 (c++)"vtable for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1
944 (c++)"vtable for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1952 (c++)"vtable for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1
945953
=== modified file 'debian/tests/scopebuild'
--- debian/tests/scopebuild 2014-06-03 12:49:04 +0000
+++ debian/tests/scopebuild 2014-07-28 11:21:43 +0000
@@ -9,60 +9,11 @@
99
10WORKDIR=$(mktemp -d)10WORKDIR=$(mktemp -d)
11trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM11trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM
12cp scopetest.cpp $WORKDIR
12cd $WORKDIR13cd $WORKDIR
13cat <<EOF > scopetest.cpp14
14#include <unity/scopes/ScopeBase.h>15g++ -std=c++11 -o scopetest scopetest.cpp `pkg-config --cflags --libs libunity-scopes`
15#include <unity/scopes/QueryBase.h>
16#include <unity/scopes/ReplyProxyFwd.h>
17#include <unity/scopes/QueryBase.h>
18#include <unity/scopes/PreviewQueryBase.h>
19
20class DemoScope : public unity::scopes::ScopeBase
21{
22public:
23 virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override;
24
25 virtual void stop() override;
26
27 unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,
28 const unity::scopes::ActionMetadata&) override;
29
30 virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const& q,
31 unity::scopes::SearchMetadata const&) override;
32};
33
34using namespace unity::scopes;
35
36int DemoScope::start(std::string const&, unity::scopes::RegistryProxy const&)
37{
38 return 0;
39}
40
41void DemoScope::stop()
42{
43}
44
45SearchQueryBase::UPtr DemoScope::search(unity::scopes::CannedQuery const &q,
46 unity::scopes::SearchMetadata const&)
47{
48 unity::scopes::SearchQueryBase::UPtr query(nullptr);
49 return query;
50}
51
52PreviewQueryBase::UPtr DemoScope::preview(Result const& result, ActionMetadata const& /*metadata*/) {
53 unity::scopes::PreviewQueryBase::UPtr preview(nullptr);
54 return preview;
55}
56
57int main(int, char**)
58{
59 DemoScope d;
60 return 0;
61}
62EOF
63
64g++ -std=c++11 -o scopebin scopetest.cpp `pkg-config --cflags --libs libunity-scopes`
65echo "Scope build: OK"16echo "Scope build: OK"
66[ -x scopebin ]17[ -x scopetest ]
67./scopebin18./scopetest
68echo "Scope run: OK"19echo "Scope run: OK"
6920
=== added file 'debian/tests/scopetest.cpp'
--- debian/tests/scopetest.cpp 1970-01-01 00:00:00 +0000
+++ debian/tests/scopetest.cpp 2014-07-28 11:21:43 +0000
@@ -0,0 +1,62 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <unity/scopes/PreviewQueryBase.h>
18#include <unity/scopes/QueryBase.h>
19#include <unity/scopes/ReplyProxyFwd.h>
20#include <unity/scopes/ScopeBase.h>
21
22class DemoScope : public unity::scopes::ScopeBase
23{
24public:
25 virtual void start(std::string const&) override;
26
27 virtual void stop() override;
28
29 virtual unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,
30 const unity::scopes::ActionMetadata&) override;
31
32 virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const& q,
33 unity::scopes::SearchMetadata const&) override;
34};
35
36using namespace unity::scopes;
37
38void DemoScope::start(std::string const&)
39{
40}
41
42void DemoScope::stop()
43{
44}
45
46SearchQueryBase::UPtr DemoScope::search(unity::scopes::CannedQuery const& /*q*/,
47 unity::scopes::SearchMetadata const&)
48{
49 unity::scopes::SearchQueryBase::UPtr query(nullptr);
50 return query;
51}
52
53PreviewQueryBase::UPtr DemoScope::preview(Result const& /*result*/, ActionMetadata const& /*metadata*/) {
54 unity::scopes::PreviewQueryBase::UPtr preview(nullptr);
55 return preview;
56}
57
58int main(int, char**)
59{
60 DemoScope d;
61 return 0;
62}
063
=== modified file 'demo/click/scope-click/scope-click.cpp'
--- demo/click/scope-click/scope-click.cpp 2014-06-17 11:20:48 +0000
+++ demo/click/scope-click/scope-click.cpp 2014-07-28 11:21:43 +0000
@@ -56,7 +56,7 @@
56class MyScope : public ScopeBase56class MyScope : public ScopeBase
57{57{
58public:58public:
59 virtual void start(string const&, RegistryProxy const&) override {}59 virtual void start(string const&) override {}
6060
61 virtual void stop() override {}61 virtual void stop() override {}
6262
6363
=== modified file 'demo/scopes/scope-A/scope-A.cpp'
--- demo/scopes/scope-A/scope-A.cpp 2014-06-25 16:41:51 +0000
+++ demo/scopes/scope-A/scope-A.cpp 2014-07-28 11:21:43 +0000
@@ -160,7 +160,7 @@
160class MyScope : public ScopeBase160class MyScope : public ScopeBase
161{161{
162public:162public:
163 virtual void start(string const& scope_id, RegistryProxy const&) override163 virtual void start(string const& scope_id) override
164 {164 {
165 scope_id_ = scope_id;165 scope_id_ = scope_id;
166 }166 }
167167
=== modified file 'demo/scopes/scope-B/scope-B.cpp'
--- demo/scopes/scope-B/scope-B.cpp 2014-06-17 11:20:48 +0000
+++ demo/scopes/scope-B/scope-B.cpp 2014-07-28 11:21:43 +0000
@@ -140,18 +140,18 @@
140class MyScope : public ScopeBase140class MyScope : public ScopeBase
141{141{
142public:142public:
143 virtual void start(string const& scope_id, RegistryProxy const& registry) override143 virtual void start(string const& scope_id) override
144 {144 {
145 scope_id_ = scope_id;145 scope_id_ = scope_id;
146146
147 if (!registry)147 if (!registry())
148 {148 {
149 throw ConfigException(scope_id + ": No registry available, cannot locate child scopes");149 throw ConfigException(scope_id + ": No registry available, cannot locate child scopes");
150 }150 }
151 // Lock up scopes C and D in the registry and remember their proxies.151 // Lock up scopes C and D in the registry and remember their proxies.
152 auto meta_c = registry->get_metadata("scope-C");152 auto meta_c = registry()->get_metadata("scope-C");
153 scope_c_ = meta_c.proxy();153 scope_c_ = meta_c.proxy();
154 auto meta_d = registry->get_metadata("scope-D");154 auto meta_d = registry()->get_metadata("scope-D");
155 scope_d_ = meta_d.proxy();155 scope_d_ = meta_d.proxy();
156 }156 }
157157
158158
=== modified file 'demo/scopes/scope-C/scope-C.cpp'
--- demo/scopes/scope-C/scope-C.cpp 2014-06-17 11:20:48 +0000
+++ demo/scopes/scope-C/scope-C.cpp 2014-07-28 11:21:43 +0000
@@ -184,7 +184,7 @@
184class MyScope : public ScopeBase184class MyScope : public ScopeBase
185{185{
186public:186public:
187 virtual void start(string const& scope_id, RegistryProxy const&) override187 virtual void start(string const& scope_id) override
188 {188 {
189 scope_id_ = scope_id;189 scope_id_ = scope_id;
190 }190 }
191191
=== modified file 'demo/scopes/scope-D/scope-D.cpp'
--- demo/scopes/scope-D/scope-D.cpp 2014-06-17 11:20:48 +0000
+++ demo/scopes/scope-D/scope-D.cpp 2014-07-28 11:21:43 +0000
@@ -183,7 +183,7 @@
183class MyScope : public ScopeBase183class MyScope : public ScopeBase
184{184{
185public:185public:
186 virtual void start(string const& scope_id, RegistryProxy const&) override186 virtual void start(string const& scope_id) override
187 {187 {
188 scope_id_ = scope_id;188 scope_id_ = scope_id;
189 }189 }
190190
=== modified file 'demo/scopes/scope-N/scope-N.cpp'
--- demo/scopes/scope-N/scope-N.cpp 2014-06-17 11:20:48 +0000
+++ demo/scopes/scope-N/scope-N.cpp 2014-07-28 11:21:43 +0000
@@ -68,7 +68,7 @@
68class MyScope : public ScopeBase68class MyScope : public ScopeBase
69{69{
70public:70public:
71 virtual void start(string const& scope_id, RegistryProxy const&) override71 virtual void start(string const& scope_id) override
72 {72 {
73 scope_id_ = scope_id;73 scope_id_ = scope_id;
74 }74 }
7575
=== modified file 'demo/scopes/scope-S/scope-S.cpp'
--- demo/scopes/scope-S/scope-S.cpp 2014-06-17 11:20:48 +0000
+++ demo/scopes/scope-S/scope-S.cpp 2014-07-28 11:21:43 +0000
@@ -85,7 +85,7 @@
85class MyScope : public ScopeBase85class MyScope : public ScopeBase
86{86{
87public:87public:
88 virtual void start(string const& scope_id, RegistryProxy const&) override88 virtual void start(string const& scope_id) override
89 {89 {
90 scope_id_ = scope_id;90 scope_id_ = scope_id;
91 }91 }
9292
=== modified file 'doc/tutorial.dox'
--- doc/tutorial.dox 2014-07-22 10:38:18 +0000
+++ doc/tutorial.dox 2014-07-28 11:21:43 +0000
@@ -615,10 +615,10 @@
615With the above classes a test case that checks if MyScope calls appropriate methods of unity::scopes::SearchReply may look like this (note that it just checks615With the above classes a test case that checks if MyScope calls appropriate methods of unity::scopes::SearchReply may look like this (note that it just checks
616if proper methods get called and uses _ matchers that match any values; put actual values in there for stricts checks):616if proper methods get called and uses _ matchers that match any values; put actual values in there for stricts checks):
617\code{.cpp}617\code{.cpp}
618typedef unity::scopes::testing::TypedScopeFixture<MyScope> TestScopeFixutre;618typedef unity::scopes::testing::TypedScopeFixture<MyScope> TestScopeFixture;
619using namespace ::testing;619using namespace ::testing;
620620
621TEST_F(TestScopeFixutre, search_results)621TEST_F(TestScopeFixture, search_results)
622{622{
623 const unity::scopes::CategoryRenderer renderer;623 const unity::scopes::CategoryRenderer renderer;
624624
@@ -724,7 +724,7 @@
724The `ScopeConfig` group is mandatory and must contain settings for at least `DisplayName`, `Description`, and `Author`.724The `ScopeConfig` group is mandatory and must contain settings for at least `DisplayName`, `Description`, and `Author`.
725`DisplayName` and `Description` can (and should) be localized. For example:725`DisplayName` and `Description` can (and should) be localized. For example:
726726
727`Description[de] = Fu&szlig;ballergebnisse`727`Description[de_DE] = Fu&szlig;ballergebnisse`
728728
729In addition to allowing the registry to make the scope available, this information controls how the scope appears729In addition to allowing the registry to make the scope available, this information controls how the scope appears
730in the "Scopes" scope.730in the "Scopes" scope.
731731
=== added file 'include/unity/scopes/AbstractScopeBase.h'
--- include/unity/scopes/AbstractScopeBase.h 1970-01-01 00:00:00 +0000
+++ include/unity/scopes/AbstractScopeBase.h 2014-07-28 11:21:43 +0000
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#ifndef UNITY_SCOPES_ABSTRACTSCOPEBASE_H
20#define UNITY_SCOPES_ABSTRACTSCOPEBASE_H
21
22#include <unity/scopes/ActivationQueryBase.h>
23#include <unity/scopes/PreviewQueryBase.h>
24#include <unity/scopes/Registry.h>
25#include <unity/scopes/SearchQueryBase.h>
26
27namespace unity
28{
29
30namespace scopes
31{
32
33/**
34\brief Abstract base class for a scope implementation.
35
36This class allows a scope to be replaced by a mock implementation.
37See unity::scopes::ScopeBase for documentation of the member functions.
38*/
39
40class AbstractScopeBase
41{
42public:
43/// @cond
44 virtual void start(std::string const& scope_id) = 0;
45 virtual void stop() = 0;
46 virtual void run() = 0;
47 virtual SearchQueryBase::UPtr search(CannedQuery const& query, SearchMetadata const& metadata) = 0;
48 virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& metadata) = 0;
49 virtual ActivationQueryBase::UPtr perform_action(Result const& result,
50 ActionMetadata const& metadata,
51 std::string const& widget_id,
52 std::string const& action_id) = 0;
53 virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) = 0;
54 virtual std::string scope_directory() const = 0;
55 virtual std::string cache_directory() const = 0;
56 virtual unity::scopes::RegistryProxy registry() const = 0;
57 virtual VariantMap settings() const = 0;
58/// @endcond
59};
60
61} // namespace scopes
62
63} // namespace unity
64
65#endif
066
=== modified file 'include/unity/scopes/ScopeBase.h'
--- include/unity/scopes/ScopeBase.h 2014-06-24 11:11:11 +0000
+++ include/unity/scopes/ScopeBase.h 2014-07-28 11:21:43 +0000
@@ -19,14 +19,10 @@
19#ifndef UNITY_SCOPES_SCOPEBASE_H19#ifndef UNITY_SCOPES_SCOPEBASE_H
20#define UNITY_SCOPES_SCOPEBASE_H20#define UNITY_SCOPES_SCOPEBASE_H
2121
22#include <unity/scopes/SearchQueryBase.h>22#include <unity/scopes/AbstractScopeBase.h>
23#include <unity/scopes/PreviewQueryBase.h>
24#include <unity/scopes/RegistryProxyFwd.h>
25#include <unity/scopes/ActivationQueryBase.h>
26#include <unity/scopes/Version.h>
27#include <unity/scopes/Result.h>
28#include <unity/scopes/ActionMetadata.h>23#include <unity/scopes/ActionMetadata.h>
29#include <unity/scopes/SearchMetadata.h>24#include <unity/scopes/SearchMetadata.h>
25#include <unity/scopes/Version.h>
3026
31/**27/**
32\brief Expands to the identifier of the scope create function. @hideinitializer28\brief Expands to the identifier of the scope create function. @hideinitializer
@@ -68,9 +64,10 @@
6864
69namespace internal65namespace internal
70{66{
67
71class ScopeBaseImpl;68class ScopeBaseImpl;
72class ScopeLoader;
73class RuntimeImpl;69class RuntimeImpl;
70
74}71}
7572
76/**73/**
@@ -90,9 +87,9 @@
90 MyScope();87 MyScope();
91 virtual ~MyScope();88 virtual ~MyScope();
9289
93 virtual void start(); // Optional90 virtual void start(std::string const& scope_id); // Optional
94 virtual void stop(); // Optional91 virtual void stop(); // Optional
95 virtual void run(); // Optional92 virtual void run(); // Optional
96};93};
97~~~94~~~
9895
@@ -134,7 +131,7 @@
134call to stop() in a timely manner.131call to stop() in a timely manner.
135*/132*/
136133
137class ScopeBase134class ScopeBase : public AbstractScopeBase
138{135{
139public:136public:
140 /// @cond137 /// @cond
@@ -150,11 +147,8 @@
150 The call to start() is made by the same thread that calls the create function.147 The call to start() is made by the same thread that calls the create function.
151148
152 \param scope_id The name of the scope as defined by the scope's configuration file.149 \param scope_id The name of the scope as defined by the scope's configuration file.
153
154 \param registry A proxy to the scope registry. This parameter is provided for aggregating
155 scopes that need to retrieve proxies to their child scopes.
156 */150 */
157 virtual void start(std::string const& scope_id, RegistryProxy const& registry);151 virtual void start(std::string const& scope_id);
158152
159 /**153 /**
160 \brief Called by the scopes run time when the scope should shut down.154 \brief Called by the scopes run time when the scope should shut down.
@@ -184,7 +178,7 @@
184 /**178 /**
185 \brief Called by the scopes run time when a scope needs to instantiate a query.179 \brief Called by the scopes run time when a scope needs to instantiate a query.
186180
187 This method must return an instance that is derived from QueryBase. The implementation181 This method must return an instance that is derived from `QueryBase`. The implementation
188 of this method must return in a timely manner, that is, it should perform only minimal182 of this method must return in a timely manner, that is, it should perform only minimal
189 initialization that is guaranteed to complete quickly. The call to search() is made183 initialization that is guaranteed to complete quickly. The call to search() is made
190 by an arbitrary thread.184 by an arbitrary thread.
@@ -197,7 +191,7 @@
197 /**191 /**
198 \brief Called by the scopes run time when a scope needs to respond to a result activation request.192 \brief Called by the scopes run time when a scope needs to respond to a result activation request.
199193
200 This method must return an instance that is derived from ActivationQueryBase. The implementation194 This method must return an instance that is derived from `ActivationQueryBase`. The implementation
201 of this method must return in a timely manner, that is, it should perform only minimal195 of this method must return in a timely manner, that is, it should perform only minimal
202 initialization that is guaranteed to complete quickly. The call to activate() is made196 initialization that is guaranteed to complete quickly. The call to activate() is made
203 by an arbitrary thread.197 by an arbitrary thread.
@@ -206,13 +200,13 @@
206 \param result The result that should be activated.200 \param result The result that should be activated.
207 \param metadata additional data sent by the client.201 \param metadata additional data sent by the client.
208 \return The activation instance.202 \return The activation instance.
209 */203 */
210 virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& metadata);204 virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& metadata);
211205
212 /**206 /**
213 \brief Invoked when a scope is requested to handle a preview action.207 \brief Invoked when a scope is requested to handle a preview action.
214208
215 This method must return an instance that is derived from ActivationQueryBase. The implementation209 This method must return an instance that is derived from `ActivationQueryBase`. The implementation
216 of this method must return in a timely manner, that is, it should perform only minimal210 of this method must return in a timely manner, that is, it should perform only minimal
217 initialization that is guaranteed to complete quickly. The call to activate() is made211 initialization that is guaranteed to complete quickly. The call to activate() is made
218 by an arbitrary thread.212 by an arbitrary thread.
@@ -223,20 +217,23 @@
223 \param widget_id The identifier of the 'actions' widget of the activated action.217 \param widget_id The identifier of the 'actions' widget of the activated action.
224 \param action_id The identifier of the action that was activated.218 \param action_id The identifier of the action that was activated.
225 \return The activation instance.219 \return The activation instance.
226 */220 */
227 virtual ActivationQueryBase::UPtr perform_action(Result const& result, ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id);221 virtual ActivationQueryBase::UPtr perform_action(Result const& result,
222 ActionMetadata const& metadata,
223 std::string const& widget_id,
224 std::string const& action_id);
228225
229 /**226 /**
230 \brief Invoked when a scope is requested to create a preview for a particular result.227 \brief Invoked when a scope is requested to create a preview for a particular result.
231228
232 This method must return an instance that is derived from PreviewQueryBase. The implementation229 This method must return an instance that is derived from `PreviewQueryBase`. The implementation
233 of this method must return in a timely manner, that is, it should perform only minimal230 of this method must return in a timely manner, that is, it should perform only minimal
234 initialization that is guaranteed to complete quickly. The call to activate() is made231 initialization that is guaranteed to complete quickly. The call to activate() is made
235 by an arbitrary thread.232 by an arbitrary thread.
236 \param result The result that should be previewed.233 \param result The result that should be previewed.
237 \param metadata Additional data sent by the client.234 \param metadata Additional data sent by the client.
238 \return The preview instance.235 \return The preview instance.
239 */236 */
240 virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) = 0;237 virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) = 0;
241238
242 /**239 /**
@@ -251,8 +248,34 @@
251 call this method from the constructor!248 call this method from the constructor!
252249
253 \return The scope's configuration directory.250 \return The scope's configuration directory.
254 */251 \throws LogicException if called from the constructor of this instance.
255 std::string scope_directory() const;252 */
253 virtual std::string scope_directory() const final;
254
255 /**
256 \brief Returns a directory that is (exclusively) writable for the scope.
257
258 This directory allows scopes to store persistent information, such
259 as cached content or similar.
260
261 \note The cache directory is available only after this ScopeBase is instantiated; do not
262 call this method from the constructor!
263
264 \return The root directory of the filesystem sub-tree that is writable for the scope.
265 \throws LogicException if called from the constructor of this instance.
266 */
267 virtual std::string cache_directory() const final;
268
269 /**
270 \brief Returns the proxy to the registry.
271
272 \note The registr proxy is available only after this ScopeBase is instantiated; do not
273 call this method from the constructor!
274
275 \return The proxy to the registry.
276 \throws LogicException if called from the constructor of this instance.
277 */
278 virtual unity::scopes::RegistryProxy registry() const final;
256279
257 /**280 /**
258 \brief Returns a dictionary with the scope's current settings.281 \brief Returns a dictionary with the scope's current settings.
@@ -266,8 +289,9 @@
266 call this method from the constructor!289 call this method from the constructor!
267290
268 \return The scope's current settings.291 \return The scope's current settings.
292 \throws LogicException if called from the constructor of this instance.
269 */293 */
270 VariantMap settings() const;294 virtual VariantMap settings() const final;
271295
272protected:296protected:
273 /// @cond297 /// @cond
@@ -275,9 +299,8 @@
275private:299private:
276 std::unique_ptr<internal::ScopeBaseImpl> p;300 std::unique_ptr<internal::ScopeBaseImpl> p;
277301
278 friend class internal::ScopeLoader;302 friend class internal::RuntimeImpl;
279 friend class internal::ScopeObject;303 friend class internal::ScopeObject;
280 friend class internal::RuntimeImpl;
281 /// @endcond304 /// @endcond
282};305};
283306
@@ -287,13 +310,17 @@
287310
288/**311/**
289\brief The function called by the scopes run time to initialize the scope.312\brief The function called by the scopes run time to initialize the scope.
290It must return a pointer to an instance derived from ScopeBase. The returned313It must return a pointer to an instance derived from `ScopeBase`. The returned
291instance need not be heap-allocated, but must remain in scope until the314instance need not be heap-allocated, but must remain in scope until the
292destroy function is called by the scopes run time.315destroy function is called by the scopes run time.
293316
294If this function throws an exception, the destroy function will _not_ be called. If this function returns NULL,317If this function throws an exception, the destroy function will _not_ be called. If this function returns NULL,
295the destroy function _will_ be called with NULL as its argument.318the destroy function _will_ be called with NULL as its argument.
296319
320\note The only purpose of the create function is to return the an instance.
321Do not do anything in the implementation that might block, and do
322not attempt to call any methods on `ScopeBase` from the constructor.
323
297\return The pointer to the ScopeBase instance.324\return The pointer to the ScopeBase instance.
298*/325*/
299extern "C" unity::scopes::ScopeBase* UNITY_SCOPE_CREATE_FUNCTION();326extern "C" unity::scopes::ScopeBase* UNITY_SCOPE_CREATE_FUNCTION();
300327
=== modified file 'include/unity/scopes/internal/DfltConfig.h.in'
--- include/unity/scopes/internal/DfltConfig.h.in 2014-07-21 06:34:24 +0000
+++ include/unity/scopes/internal/DfltConfig.h.in 2014-07-28 11:21:43 +0000
@@ -39,6 +39,7 @@
39static constexpr char const* DFLT_MIDDLEWARE_INI = DFLT_ZMQ_MIDDLEWARE_INI;39static constexpr char const* DFLT_MIDDLEWARE_INI = DFLT_ZMQ_MIDDLEWARE_INI;
40static constexpr char const* DFLT_SCOPE_INSTALL_DIR = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@";40static constexpr char const* DFLT_SCOPE_INSTALL_DIR = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@";
41static constexpr char const* DFLT_OEM_INSTALL_DIR = "/custom/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@";41static constexpr char const* DFLT_OEM_INSTALL_DIR = "/custom/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@";
42static constexpr char const* DFLT_CONFINEMENT_TYPE = "leaf-net";
4243
43static constexpr int DFLT_SS_HTTP_TIMEOUT = 20; // seconds44static constexpr int DFLT_SS_HTTP_TIMEOUT = 20; // seconds
44static constexpr int DFLT_SS_REG_REFRESH_RATE = 86400; // 24 hours as seconds45static constexpr int DFLT_SS_REG_REFRESH_RATE = 86400; // 24 hours as seconds
4546
=== modified file 'include/unity/scopes/internal/RuntimeImpl.h'
--- include/unity/scopes/internal/RuntimeImpl.h 2014-06-24 03:05:19 +0000
+++ include/unity/scopes/internal/RuntimeImpl.h 2014-07-28 11:21:43 +0000
@@ -64,6 +64,7 @@
64private:64private:
65 RuntimeImpl(std::string const& scope_id, std::string const& configfile);65 RuntimeImpl(std::string const& scope_id, std::string const& configfile);
66 void waiter_thread(ThreadSafeQueue<std::future<void>>::SPtr const& queue) const noexcept;66 void waiter_thread(ThreadSafeQueue<std::future<void>>::SPtr const& queue) const noexcept;
67 std::string find_cache_dir() const;
6768
68 bool destroyed_;69 bool destroyed_;
69 std::string scope_id_;70 std::string scope_id_;
7071
=== modified file 'include/unity/scopes/internal/ScopeBaseImpl.h'
--- include/unity/scopes/internal/ScopeBaseImpl.h 2014-06-24 03:05:19 +0000
+++ include/unity/scopes/internal/ScopeBaseImpl.h 2014-07-28 11:21:43 +0000
@@ -19,9 +19,9 @@
19#ifndef UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H19#ifndef UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H
20#define UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H20#define UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H
2121
22#include <unity/scopes/RegistryProxyFwd.h>
22#include <unity/scopes/Variant.h>23#include <unity/scopes/Variant.h>
2324
24#include <memory>
25#include <mutex>25#include <mutex>
26#include <string>26#include <string>
2727
@@ -39,17 +39,35 @@
39class ScopeBaseImpl final39class ScopeBaseImpl final
40{40{
41public:41public:
42 ScopeBaseImpl() = default;42 ScopeBaseImpl();
43 ~ScopeBaseImpl() = default;43 ~ScopeBaseImpl() = default;
44 void set_scope_directory(std::string const &path);44
45 void set_scope_directory(std::string const& path);
45 std::string scope_directory() const;46 std::string scope_directory() const;
47
48 void set_cache_directory(std::string const& path);
49 std::string cache_directory() const;
50
51 void set_registry(RegistryProxy const& registry);
52 RegistryProxy registry() const;
53
46 std::shared_ptr<unity::scopes::internal::SettingsDB> settings_db() const;54 std::shared_ptr<unity::scopes::internal::SettingsDB> settings_db() const;
47 void set_settings_db(std::shared_ptr<unity::scopes::internal::SettingsDB> const& db);55 void set_settings_db(std::shared_ptr<unity::scopes::internal::SettingsDB> const& db);
48 unity::scopes::VariantMap settings() const;56 unity::scopes::VariantMap settings() const;
4957
50private:58private:
51 std::string scope_directory_;59 std::string scope_directory_;
60 bool scope_dir_initialized_;
61
62 std::string cache_directory_;
63 bool cache_dir_initialized_;
64
65 unity::scopes::RegistryProxy registry_;
66 bool registry_initialized_;
67
52 std::shared_ptr<unity::scopes::internal::SettingsDB> db_;68 std::shared_ptr<unity::scopes::internal::SettingsDB> db_;
69 bool settings_db_initialized_;
70
53 mutable std::mutex mutex_;71 mutable std::mutex mutex_;
54};72};
5573
5674
=== modified file 'include/unity/scopes/internal/ScopeConfig.h'
--- include/unity/scopes/internal/ScopeConfig.h 2014-06-26 12:49:46 +0000
+++ include/unity/scopes/internal/ScopeConfig.h 2014-07-28 11:21:43 +0000
@@ -39,18 +39,18 @@
39 ScopeConfig(std::string const& configfile);39 ScopeConfig(std::string const& configfile);
40 ~ScopeConfig();40 ~ScopeConfig();
4141
42 bool overrideable() const; // Optional, returns false if not present42 bool overrideable() const; // Optional, returns false if not present
43 std::string display_name() const; // Mandatory, localizable43 std::string display_name() const; // Mandatory, localizable
44 std::string description() const; // Mandatory, localizable44 std::string description() const; // Mandatory, localizable
45 std::string author() const; // Mandatory45 std::string author() const; // Mandatory
46 std::string art() const; // Optional, throws NotFoundException if not present46 std::string art() const; // Optional, throws NotFoundException if not present
47 std::string icon() const; // Optional, throws NotFoundException if not present47 std::string icon() const; // Optional, throws NotFoundException if not present
48 std::string search_hint() const; // Optional, localizable, throws NotFoundException if not present48 std::string search_hint() const; // Optional, localizable, throws NotFoundException if not present
49 std::string hot_key() const; // Optional, throws NotFoundException if not present49 std::string hot_key() const; // Optional, throws NotFoundException if not present
50 bool invisible() const; // Optional, returns false if not present50 bool invisible() const; // Optional, returns false if not present
51 bool location_data_needed() const; // Optional, returns false if not present51 bool location_data_needed() const; // Optional, returns false if not present
52 std::string scope_runner() const; // Optional, throws NotFoundException if not present52 std::string scope_runner() const; // Optional, throws NotFoundException if not present
53 int idle_timeout() const; // Optional, returns default value if not present53 int idle_timeout() const; // Optional, returns default value if not present
54 ScopeMetadata::ResultsTtlType results_ttl_type() const; // Optional, returns none if not present54 ScopeMetadata::ResultsTtlType results_ttl_type() const; // Optional, returns none if not present
5555
56 VariantMap appearance_attributes() const; // Optional, returns empty map if no attributes are present56 VariantMap appearance_attributes() const; // Optional, returns empty map if no attributes are present
5757
=== modified file 'include/unity/scopes/internal/ScopeLoader.h'
--- include/unity/scopes/internal/ScopeLoader.h 2014-07-02 05:17:19 +0000
+++ include/unity/scopes/internal/ScopeLoader.h 2014-07-28 11:21:43 +0000
@@ -40,12 +40,8 @@
40 NONCOPYABLE(ScopeLoader);40 NONCOPYABLE(ScopeLoader);
41 UNITY_DEFINES_PTRS(ScopeLoader);41 UNITY_DEFINES_PTRS(ScopeLoader);
4242
43 // Creates a ScopeLoader for a scope with the given ID, library, and settings dir. We pass in the registry proxy43 // Creates a ScopeLoader for a scope with the given ID and library.
44 // so we can pass it to the scope's start method.44 static UPtr load(std::string const& scope_id, std::string const& libpath);
45 static UPtr load(std::string const& scope_id,
46 std::string const& libpath,
47 std::string const& data_dir,
48 RegistryProxy const& registry);
4945
50 // unload() explicitly finalizes the scope. This is called by the destructor too, but calling it explicity46 // unload() explicitly finalizes the scope. This is called by the destructor too, but calling it explicity
51 // allows the caller to receive any exceptions that may have been produced by the scope thread.47 // allows the caller to receive any exceptions that may have been produced by the scope thread.
@@ -67,14 +63,10 @@
67 ~ScopeLoader();63 ~ScopeLoader();
6864
69private:65private:
70 ScopeLoader(std::string const& scope_id,66 ScopeLoader(std::string const& scope_id, std::string const& path);
71 std::string const& libpath,
72 std::string const& data_dir,
73 RegistryProxy const& registry);
7467
75 std::string scope_id_;68 std::string scope_id_;
76 unity::scopes::internal::DynamicLoader::UPtr dyn_loader_;69 unity::scopes::internal::DynamicLoader::UPtr dyn_loader_;
77 unity::scopes::RegistryProxy registry_;
78 std::exception_ptr exception_;70 std::exception_ptr exception_;
7971
80 std::thread scope_thread_;72 std::thread scope_thread_;
8173
=== modified file 'include/unity/scopes/testing/TypedScopeFixture.h'
--- include/unity/scopes/testing/TypedScopeFixture.h 2014-06-17 09:27:49 +0000
+++ include/unity/scopes/testing/TypedScopeFixture.h 2014-07-28 11:21:43 +0000
@@ -46,9 +46,9 @@
46 return "unknown";46 return "unknown";
47 }47 }
4848
49 inline static std::shared_ptr<Scope> construct()49 inline static std::shared_ptr<Scope> construct(RegistryProxy const& r)
50 {50 {
51 return std::make_shared<Scope>();51 return std::make_shared<Scope>(r);
52 }52 }
53};53};
5454
@@ -57,14 +57,14 @@
57{57{
58public:58public:
59 TypedScopeFixture()59 TypedScopeFixture()
60 : scope(ScopeTraits<Scope>::construct()),60 : registry_proxy(&registry, [](unity::scopes::Registry*) {})
61 registry_proxy(&registry, [](unity::scopes::Registry*) {})61 , scope(ScopeTraits<Scope>::construct(registry_proxy))
62 {62 {
63 }63 }
6464
65 void SetUp()65 void SetUp()
66 {66 {
67 EXPECT_NO_THROW(scope->start(ScopeTraits<Scope>::name(), registry_proxy));67 EXPECT_NO_THROW(scope->start(ScopeTraits<Scope>::name()));
68 EXPECT_NO_THROW(scope->run());68 EXPECT_NO_THROW(scope->run());
69 }69 }
7070
@@ -74,9 +74,9 @@
74 }74 }
7575
76protected:76protected:
77 std::shared_ptr<Scope> scope;
78 unity::scopes::testing::MockRegistry registry;77 unity::scopes::testing::MockRegistry registry;
79 unity::scopes::RegistryProxy registry_proxy;78 unity::scopes::RegistryProxy registry_proxy;
79 std::shared_ptr<Scope> scope;
80};80};
8181
82/// @endcond82/// @endcond
8383
=== modified file 'scoperegistry/scoperegistry.cpp'
--- scoperegistry/scoperegistry.cpp 2014-07-22 10:48:57 +0000
+++ scoperegistry/scoperegistry.cpp 2014-07-28 11:21:43 +0000
@@ -35,7 +35,6 @@
3535
36#include <boost/algorithm/string.hpp>36#include <boost/algorithm/string.hpp>
37#include <boost/filesystem/operations.hpp>37#include <boost/filesystem/operations.hpp>
38#include <boost/filesystem/path.hpp>
3938
40#include <algorithm>39#include <algorithm>
41#include <cassert>40#include <cassert>
@@ -43,11 +42,8 @@
43#include <iostream>42#include <iostream>
44#include <map>43#include <map>
45#include <set>44#include <set>
46#include <sstream>45
4746#include <sys/stat.h> // TODO: remove this once hack for creating data root dir is removed
48#include <libgen.h>
49#include <unistd.h>
50
5147
52using namespace scoperegistry;48using namespace scoperegistry;
53using namespace std;49using namespace std;
@@ -464,11 +460,23 @@
464 SignalThreadWrapper signal_handler_wrapper;460 SignalThreadWrapper signal_handler_wrapper;
465461
466 // And finally creating our runtime.462 // And finally creating our runtime.
467 RuntimeConfig rt_config(config_file);463 string identity;
468 RuntimeImpl::UPtr runtime = RuntimeImpl::create(rt_config.registry_identity(), config_file);464 string ss_reg_id;
469465 RuntimeImpl::UPtr runtime;
470 string identity = runtime->registry_identity();466 {
471 string ss_reg_id = runtime->ss_registry_identity();467 RuntimeConfig rt_config(config_file);
468 runtime = RuntimeImpl::create(rt_config.registry_identity(), config_file);
469
470 identity = runtime->registry_identity();
471 ss_reg_id = runtime->ss_registry_identity();
472
473 // TODO: HACK: We create the root of the data directory for confined scopes,
474 // in case the scope is confined and the dir doesn't exist
475 // yet. This really should be done by the click-installation but,
476 // prior to RTM, we don't rely on that.
477 string data_root = rt_config.data_directory() + "/leaf-net";
478 ::mkdir(data_root.c_str(), 0700);
479 } // Release memory for config parser
472480
473 // Collect the registry config data.481 // Collect the registry config data.
474482
@@ -539,9 +547,8 @@
539 }547 }
540548
541 // Configure watches for scope install directories549 // Configure watches for scope install directories
542 ScopesWatcher local_scopes_watcher(registry,550 auto local_watch_lambda = [registry, &middleware, &scoperunner_path, &config_file, process_timeout]
543 [registry, &middleware, &scoperunner_path, &config_file, process_timeout]551 (pair<string, string> const& scope)
544 (pair<string, string> const& scope)
545 {552 {
546 try553 try
547 {554 {
@@ -551,13 +558,13 @@
551 {558 {
552 error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what());559 error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what());
553 }560 }
554 });561 };
562 ScopesWatcher local_scopes_watcher(registry, local_watch_lambda);
555 local_scopes_watcher.add_install_dir(scope_installdir);563 local_scopes_watcher.add_install_dir(scope_installdir);
556 local_scopes_watcher.add_install_dir(oem_installdir);564 local_scopes_watcher.add_install_dir(oem_installdir);
557565
558 ScopesWatcher click_scopes_watcher(registry,566 auto click_watch_lambda = [registry, &middleware, &scoperunner_path, &config_file, process_timeout]
559 [registry, &middleware, &scoperunner_path, &config_file, process_timeout]567 (pair<string, string> const& scope)
560 (pair<string, string> const& scope)
561 {568 {
562 try569 try
563 {570 {
@@ -567,7 +574,8 @@
567 {574 {
568 error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what());575 error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what());
569 }576 }
570 });577 };
578 ScopesWatcher click_scopes_watcher(registry, click_watch_lambda);
571 click_scopes_watcher.add_install_dir(click_installdir);579 click_scopes_watcher.add_install_dir(click_installdir);
572580
573 // Let's add the registry's state receiver to the middleware so that scopes can inform581 // Let's add the registry's state receiver to the middleware so that scopes can inform
574582
=== modified file 'scoperunner/scoperunner.cpp'
--- scoperunner/scoperunner.cpp 2014-07-21 15:37:57 +0000
+++ scoperunner/scoperunner.cpp 2014-07-28 11:21:43 +0000
@@ -38,8 +38,6 @@
38#include <unordered_map>38#include <unordered_map>
39#include <vector>39#include <vector>
4040
41#include <libgen.h>
42
43using namespace std;41using namespace std;
44using namespace unity::scopes;42using namespace unity::scopes;
45using namespace unity::scopes::internal;43using namespace unity::scopes::internal;
@@ -59,7 +57,7 @@
59// Run the scope specified by the config_file in a separate thread and wait for the thread to finish.57// Run the scope specified by the config_file in a separate thread and wait for the thread to finish.
60// Return exit status for main to use.58// Return exit status for main to use.
6159
62int run_scope(std::string const& runtime_config, std::string const& scope_configfile)60int run_scope(std::string const& runtime_config, std::string const& scope_config)
63{61{
64 auto trap = core::posix::trap_signals_for_all_subsequent_threads(62 auto trap = core::posix::trap_signals_for_all_subsequent_threads(
65 {63 {
@@ -69,16 +67,11 @@
6967
70 std::thread trap_worker([trap]() { trap->run(); });68 std::thread trap_worker([trap]() { trap->run(); });
7169
72 // Retrieve the registry middleware and create a proxy to its state receiver70 // Figure out what the scope ID is from the name of the scope config file.
73 RuntimeConfig rt_config(runtime_config);71 filesystem::path scope_config_path(scope_config);
74 RegistryConfig reg_conf(rt_config.registry_identity(), rt_config.registry_configfile());
75 auto reg_runtime = RuntimeImpl::create(rt_config.registry_identity(), runtime_config);
76 auto reg_mw = reg_runtime->factory()->find(reg_runtime->registry_identity(), reg_conf.mw_kind());
77 auto reg_state_receiver = reg_mw->create_state_receiver_proxy("StateReceiver");
78
79 filesystem::path scope_config_path(scope_configfile);
80 string lib_dir = scope_config_path.parent_path().native();72 string lib_dir = scope_config_path.parent_path().native();
81 string scope_id = scope_config_path.stem().native();73 string scope_id = scope_config_path.stem().native();
74
82 if (!lib_dir.empty())75 if (!lib_dir.empty())
83 {76 {
84 lib_dir += '/';77 lib_dir += '/';
@@ -87,11 +80,6 @@
87 int exit_status = 1;80 int exit_status = 1;
88 try81 try
89 {82 {
90 // Instantiate the run time, create the middleware, load the scope from its
91 // shared library, and call the scope's start() method.
92 auto rt = RuntimeImpl::create(scope_id, runtime_config);
93 auto mw = rt->factory()->create(scope_id, reg_conf.mw_kind(), reg_conf.mw_configfile());
94
95 // For a scope_id "Fred", we look for the library as "libFred.so", "Fred.so", and "scope.so".83 // For a scope_id "Fred", we look for the library as "libFred.so", "Fred.so", and "scope.so".
96 vector<string> libs;84 vector<string> libs;
97 libs.push_back(lib_dir + "lib" + scope_id + ".so");85 libs.push_back(lib_dir + "lib" + scope_id + ".so");
@@ -104,7 +92,7 @@
104 {92 {
105 try93 try
106 {94 {
107 loader = ScopeLoader::load(scope_id, lib, rt_config.data_directory(), rt->registry());95 loader = ScopeLoader::load(scope_id, lib);
108 }96 }
109 catch (unity::ResourceException& e)97 catch (unity::ResourceException& e)
110 {98 {
@@ -123,35 +111,24 @@
123 e.remember(ep);111 e.remember(ep);
124 throw e;112 throw e;
125 }113 }
126 loader->start();114
127115 static mutex rt_mutex;
128 // Give a thread to the scope to do with as it likes. If the scope doesn't want to use it and116 RuntimeImpl::SPtr rt;
129 // immediately returns from run(), that's fine.117
130 auto run_future = std::async(launch::async, [loader] { loader->scope_base()->run(); });118 // Signal handler to shut down the run time on receipt of a signal.
131119 trap->signal_raised().connect([rt](core::posix::Signal)
132 // Create a servant for the scope and register the servant.
133 ScopeConfig scope_config(scope_configfile);
134 auto scope = unique_ptr<ScopeObject>(new ScopeObject(rt.get(), loader->scope_base()));
135 auto proxy = mw->add_scope_object(scope_id, move(scope), scope_config.idle_timeout() * 1000);
136
137 trap->signal_raised().connect([mw](core::posix::Signal)
138 {120 {
139 mw->stop();121 lock_guard<mutex> lock(rt_mutex);
122 rt->destroy();
140 });123 });
141124
142 // Inform the registry that this scope is now ready to process requests125 // Instantiate the run time and run the scope.
143 reg_state_receiver->push_state(scope_id, StateReceiverObject::State::ScopeReady);126 {
144127 lock_guard<mutex> lock(rt_mutex);
145 mw->wait_for_shutdown();128 rt = RuntimeImpl::create(scope_id, runtime_config);
146129 }
147 // Inform the registry that this scope is shutting down130
148 reg_state_receiver->push_state(scope_id, StateReceiverObject::State::ScopeStopping);131 rt->run_scope(loader->scope_base(), runtime_config, scope_config);
149
150 loader->stop();
151
152 // Collect exit status from the run thread. If this throws, the ScopeLoader
153 // destructor will still call stop() on the scope.
154 run_future.get();
155132
156 exit_status = 0;133 exit_status = 0;
157 }134 }
158135
=== modified file 'smartscopesproxy/smartscopesproxy.cpp'
--- smartscopesproxy/smartscopesproxy.cpp 2014-06-30 07:20:30 +0000
+++ smartscopesproxy/smartscopesproxy.cpp 2014-07-28 11:21:43 +0000
@@ -27,9 +27,10 @@
27#include <core/posix/signal.h>27#include <core/posix/signal.h>
2828
29#include <cassert>29#include <cassert>
30#include <iostream>
31
32#include <libgen.h>
30#include <signal.h>33#include <signal.h>
31#include <libgen.h>
32#include <iostream>
33#include <unistd.h>34#include <unistd.h>
3435
35using namespace unity::scopes;36using namespace unity::scopes;
3637
=== modified file 'src/scopes/ScopeBase.cpp'
--- src/scopes/ScopeBase.cpp 2014-06-24 11:11:11 +0000
+++ src/scopes/ScopeBase.cpp 2014-07-28 11:21:43 +0000
@@ -18,6 +18,7 @@
1818
19#include <unity/scopes/ScopeBase.h>19#include <unity/scopes/ScopeBase.h>
20#include <unity/scopes/ActivationQueryBase.h>20#include <unity/scopes/ActivationQueryBase.h>
21#include <unity/scopes/Registry.h>
21#include <unity/scopes/internal/ScopeBaseImpl.h>22#include <unity/scopes/internal/ScopeBaseImpl.h>
2223
23namespace unity24namespace unity
@@ -39,7 +40,7 @@
3940
40//! @endcond41//! @endcond
4142
42void ScopeBase::start(std::string const&, RegistryProxy const&)43void ScopeBase::start(std::string const&)
43{44{
44 // Intentionally empty: default "do nothing" implementation.45 // Intentionally empty: default "do nothing" implementation.
45}46}
@@ -76,6 +77,16 @@
76 return p->scope_directory();77 return p->scope_directory();
77}78}
7879
80std::string ScopeBase::cache_directory() const
81{
82 return p->cache_directory();
83}
84
85RegistryProxy ScopeBase::registry() const
86{
87 return p->registry();
88}
89
79unity::scopes::VariantMap ScopeBase::settings() const90unity::scopes::VariantMap ScopeBase::settings() const
80{91{
81 return p->settings();92 return p->settings();
8293
=== modified file 'src/scopes/internal/RegistryConfig.cpp'
--- src/scopes/internal/RegistryConfig.cpp 2014-05-09 06:36:46 +0000
+++ src/scopes/internal/RegistryConfig.cpp 2014-07-28 11:21:43 +0000
@@ -78,7 +78,7 @@
78 throw_ex("Illegal value (" + to_string(process_timeout_) + ") for " + process_timeout_key + ": value must be 10-5000 ms");78 throw_ex("Illegal value (" + to_string(process_timeout_) + ") for " + process_timeout_key + ": value must be 10-5000 ms");
79 }79 }
8080
81 const KnownEntries known_entries = {81 KnownEntries const known_entries = {
82 { registry_config_group,82 { registry_config_group,
83 {83 {
84 mw_kind_key,84 mw_kind_key,
8585
=== modified file 'src/scopes/internal/RuntimeConfig.cpp'
--- src/scopes/internal/RuntimeConfig.cpp 2014-07-07 05:22:26 +0000
+++ src/scopes/internal/RuntimeConfig.cpp 2014-07-28 11:21:43 +0000
@@ -104,7 +104,7 @@
104 }104 }
105 }105 }
106106
107 const KnownEntries known_entries = {107 KnownEntries const known_entries = {
108 { runtime_config_group,108 { runtime_config_group,
109 {109 {
110 registry_identity_key,110 registry_identity_key,
111111
=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
--- src/scopes/internal/RuntimeImpl.cpp 2014-07-21 15:37:57 +0000
+++ src/scopes/internal/RuntimeImpl.cpp 2014-07-28 11:21:43 +0000
@@ -35,8 +35,7 @@
3535
36#include <boost/filesystem.hpp>36#include <boost/filesystem.hpp>
3737
38#include <signal.h>38#include <boost/filesystem.hpp>
39#include <libgen.h>
4039
41#include <cassert>40#include <cassert>
42#include <cstring>41#include <cstring>
@@ -301,27 +300,37 @@
301 auto mw = factory()->create(scope_id_, reg_conf.mw_kind(), reg_conf.mw_configfile());300 auto mw = factory()->create(scope_id_, reg_conf.mw_kind(), reg_conf.mw_configfile());
302301
303 {302 {
304 boost::filesystem::path inip(scope_ini_file);303 boost::filesystem::path dir = boost::filesystem::path(scope_ini_file).parent_path();
305 boost::filesystem::path scope_dir(inip.parent_path());304 scope_base->p->set_scope_directory(dir.native());
306 scope_base->p->set_scope_directory(inip.native());
307 }305 }
308306
309 // Try to open the scope settings database, if any.
310 string settings_dir = data_dir_ + "/" + scope_id_;
311 string scope_dir = scope_base->scope_directory();
312 string settings_db = settings_dir + "/settings.db";
313 string settings_schema = scope_dir + "/" + scope_id_ + "-settings.ini";
314 if (boost::filesystem::exists(settings_schema))
315 {307 {
316 // Make sure the settings directories exist. (No permission for group and others; data might be sensitive.)308 // Try to open the scope settings database, if any.
317 ::mkdir(data_dir_.c_str(), 0700);309 string settings_dir = data_dir_ + "/" + scope_id_;
318 ::mkdir(settings_dir.c_str(), 0700);310 string scope_dir = scope_base->scope_directory();
311 string settings_db = settings_dir + "/settings.db";
312 string settings_schema = scope_dir + "/" + scope_id_ + "-settings.ini";
313 if (boost::filesystem::exists(settings_schema))
314 {
315 // Make sure the settings directories exist. (No permission for group and others; data might be sensitive.)
316 ::mkdir(data_dir_.c_str(), 0700);
317 ::mkdir(settings_dir.c_str(), 0700);
319318
320 shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema));319 shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema));
321 scope_base->p->set_settings_db(db);320 scope_base->p->set_settings_db(db);
321 }
322 else
323 {
324 scope_base->p->set_settings_db(nullptr);
325 }
322 }326 }
323327
324 scope_base->start(scope_id_, registry());328 scope_base->p->set_registry(registry_);
329
330 scope_base->p->set_cache_directory(find_cache_dir());
331
332 scope_base->start(scope_id_);
333
325 // Ensure the scope gets stopped.334 // Ensure the scope gets stopped.
326 unique_ptr<ScopeBase, void(*)(ScopeBase*)> cleanup_scope(scope_base, [](ScopeBase *scope_base) { scope_base->stop(); });335 unique_ptr<ScopeBase, void(*)(ScopeBase*)> cleanup_scope(scope_base, [](ScopeBase *scope_base) { scope_base->stop(); });
327336
@@ -332,15 +341,13 @@
332341
333 // Create a servant for the scope and register the servant.342 // Create a servant for the scope and register the servant.
334 auto scope = unique_ptr<internal::ScopeObject>(new internal::ScopeObject(this, scope_base));343 auto scope = unique_ptr<internal::ScopeObject>(new internal::ScopeObject(this, scope_base));
344 int idle_timeout_ms = 0;
335 if (!scope_ini_file.empty())345 if (!scope_ini_file.empty())
336 {346 {
337 ScopeConfig scope_config(scope_ini_file);347 ScopeConfig scope_config(scope_ini_file);
338 mw->add_scope_object(scope_id_, move(scope), scope_config.idle_timeout() * 1000);348 idle_timeout_ms = scope_config.idle_timeout() * 1000;
339 }349 }
340 else350 mw->add_scope_object(scope_id_, move(scope), idle_timeout_ms);
341 {
342 mw->add_scope_object(scope_id_, move(scope));
343 }
344351
345 // Inform the registry that this scope is now ready to process requests352 // Inform the registry that this scope is now ready to process requests
346 reg_state_receiver->push_state(scope_id_, StateReceiverObject::State::ScopeReady);353 reg_state_receiver->push_state(scope_id_, StateReceiverObject::State::ScopeReady);
@@ -383,6 +390,42 @@
383 }390 }
384}391}
385392
393string RuntimeImpl::find_cache_dir() const
394{
395 // TODO: HACK: Until we get a fancier Apparmor query API, we try
396 // to create the scope cache dir and figure out whether
397 // whether we are confined or unconfined. We first try to
398 // create <data_dir>/unconfined and <data_dir>/unconfined/<scope_id_>,
399 // in case they don't exist. Then we try to create a file in
400 // <data_dir>unconfined/<scope_id_>. If that works, we unlink
401 // the file again and can conclude that the scope is unconfined.
402 // Otherwise, the scope must be confined, in which case
403 // we create <data_dir>/leaf-net and <data_dir>/leaf-net/<scope_id_>.
404
405 string cache_dir = data_dir_ + "/unconfined/" + scope_id_;
406
407 // The following two mkdir() calls will fail if the scope is confined or
408 // the directories exist already.
409 ::mkdir((data_dir_ + "/unconfined").c_str(), 0700);
410 ::mkdir(cache_dir.c_str(), 0700);
411 string tmp = cache_dir + "/.unconfined_scope_XXXXXX";
412 int fd = mkstemp(const_cast<char*>(tmp.c_str())); // mkstemp() modifies its argument
413 if (fd != -1)
414 {
415 // If mkstemp succeeded, the scope is unconfined.
416 assert(::unlink(tmp.c_str()) == 0);
417 ::close(fd);
418 }
419 else
420 {
421 // mkstemp() failed, the scope must be confined.
422 ::mkdir((data_dir_ + "/leaf-net").c_str(), 0700);
423 ::mkdir(cache_dir.c_str(), 0700);
424 cache_dir = data_dir_ + "/leaf-net/" + scope_id_;
425 }
426 return cache_dir;
427}
428
386} // namespace internal429} // namespace internal
387430
388} // namespace scopes431} // namespace scopes
389432
=== modified file 'src/scopes/internal/ScopeBaseImpl.cpp'
--- src/scopes/internal/ScopeBaseImpl.cpp 2014-06-24 03:05:19 +0000
+++ src/scopes/internal/ScopeBaseImpl.cpp 2014-07-28 11:21:43 +0000
@@ -17,8 +17,12 @@
17 */17 */
1818
19#include <unity/scopes/internal/ScopeBaseImpl.h>19#include <unity/scopes/internal/ScopeBaseImpl.h>
20
21#include <unity/UnityExceptions.h>
20#include <unity/scopes/internal/SettingsDB.h>22#include <unity/scopes/internal/SettingsDB.h>
23#include <unity/scopes/ScopeExceptions.h>
2124
25using namespace unity;
22using namespace unity::scopes;26using namespace unity::scopes;
23using namespace std;27using namespace std;
2428
@@ -31,21 +35,78 @@
31namespace internal35namespace internal
32{36{
3337
34void ScopeBaseImpl::set_scope_directory(std::string const &path)38ScopeBaseImpl::ScopeBaseImpl()
39 : scope_dir_initialized_(false)
40 , cache_dir_initialized_(false)
41 , registry_initialized_(false)
42 , settings_db_initialized_(false)
43{
44}
45
46void ScopeBaseImpl::set_scope_directory(std::string const& path)
35{47{
36 lock_guard<mutex> lock(mutex_);48 lock_guard<mutex> lock(mutex_);
37 scope_directory_ = path;49 scope_directory_ = path;
50 scope_dir_initialized_ = true;
38}51}
3952
40std::string ScopeBaseImpl::scope_directory() const53std::string ScopeBaseImpl::scope_directory() const
41{54{
42 lock_guard<mutex> lock(mutex_);55 lock_guard<mutex> lock(mutex_);
56 if (!scope_dir_initialized_)
57 {
58 throw LogicException("ScopeBase::scope_directory() cannot be called from constructor");
59 }
60 // scope_dir_ is never empty, except for tests, so we don't throw if it is empty here.
43 return scope_directory_;61 return scope_directory_;
44}62}
4563
64void ScopeBaseImpl::set_cache_directory(std::string const& path)
65{
66 lock_guard<mutex> lock(mutex_);
67 cache_directory_ = path;
68 cache_dir_initialized_ = true;
69}
70
71std::string ScopeBaseImpl::cache_directory() const
72{
73 lock_guard<mutex> lock(mutex_);
74 if (!cache_dir_initialized_)
75 {
76 throw LogicException("ScopeBase::cache_directory() cannot be called from constructor");
77 }
78 if (cache_directory_.empty())
79 {
80 throw ConfigException("ScopeBase::cache_directory(): no cache directory available");
81 }
82 return cache_directory_;
83}
84
85void ScopeBaseImpl::set_registry(RegistryProxy const& registry)
86{
87 lock_guard<mutex> lock(mutex_);
88 registry_ = registry;
89 registry_initialized_ = true;
90}
91
92RegistryProxy ScopeBaseImpl::registry() const
93{
94 lock_guard<mutex> lock(mutex_);
95 if (!registry_initialized_)
96 {
97 throw LogicException("ScopeBase::registry() cannot be called from constructor");
98 }
99 // registry_ can be a null proxy.
100 return registry_;
101}
102
46SettingsDB::SPtr ScopeBaseImpl::settings_db() const103SettingsDB::SPtr ScopeBaseImpl::settings_db() const
47{104{
48 lock_guard<mutex> lock(mutex_);105 lock_guard<mutex> lock(mutex_);
106 if (!settings_db_initialized_)
107 {
108 throw LogicException("ScopeBase::settings_db() cannot be called from constructor");
109 }
49 return db_;110 return db_;
50}111}
51112
@@ -53,11 +114,16 @@
53{114{
54 lock_guard<mutex> lock(mutex_);115 lock_guard<mutex> lock(mutex_);
55 db_ = db;116 db_ = db;
117 settings_db_initialized_ = true;
56}118}
57119
58VariantMap ScopeBaseImpl::settings() const120VariantMap ScopeBaseImpl::settings() const
59{121{
60 lock_guard<mutex> lock(mutex_);122 lock_guard<mutex> lock(mutex_);
123 if (!settings_db_initialized_)
124 {
125 throw LogicException("ScopeBase::settings_db() cannot be called from constructor");
126 }
61 return db_ ? db_->settings() : VariantMap();127 return db_ ? db_->settings() : VariantMap();
62}128}
63129
64130
=== modified file 'src/scopes/internal/ScopeConfig.cpp'
--- src/scopes/internal/ScopeConfig.cpp 2014-07-24 13:08:48 +0000
+++ src/scopes/internal/ScopeConfig.cpp 2014-07-28 11:21:43 +0000
@@ -54,7 +54,7 @@
54 const string location_data_needed_key = "LocationDataNeeded";54 const string location_data_needed_key = "LocationDataNeeded";
55 const string scoperunner_key = "ScopeRunner";55 const string scoperunner_key = "ScopeRunner";
56 const string idle_timeout_key = "IdleTimeout";56 const string idle_timeout_key = "IdleTimeout";
57 const string results_ttl_str = "ResultsTtlType";57 const string results_ttl_key = "ResultsTtlType";
5858
59 const string scope_appearance_group = "Appearance";59 const string scope_appearance_group = "Appearance";
60 const string fg_color_key = "ForegroundColor";60 const string fg_color_key = "ForegroundColor";
@@ -141,8 +141,8 @@
141 // custom scope runner executable is optional141 // custom scope runner executable is optional
142 try142 try
143 {143 {
144 string key = parser()->get_string(scope_config_group, scoperunner_key);144 string scope_runner = parser()->get_string(scope_config_group, scoperunner_key);
145 scope_runner_.reset(new string(key));145 scope_runner_.reset(new string(scope_runner));
146 }146 }
147 catch (LogicException const&)147 catch (LogicException const&)
148 {148 {
@@ -162,7 +162,7 @@
162 results_ttl_type_ = ScopeMetadata::ResultsTtlType::None;162 results_ttl_type_ = ScopeMetadata::ResultsTtlType::None;
163 try163 try
164 {164 {
165 string orig = parser()->get_string(scope_config_group, results_ttl_str);165 string orig = parser()->get_string(scope_config_group, results_ttl_key);
166 string ttl = orig;166 string ttl = orig;
167 to_lower(ttl);167 to_lower(ttl);
168 if (ttl.empty() || ttl == "none")168 if (ttl.empty() || ttl == "none")
@@ -182,7 +182,7 @@
182 }182 }
183 else183 else
184 {184 {
185 throw_ex("Illegal value (" + orig + ") for " + results_ttl_str);185 throw_ex("Illegal value (\"" + orig + "\") for " + results_ttl_key);
186 }186 }
187 }187 }
188 catch (LogicException const&)188 catch (LogicException const&)
@@ -201,7 +201,7 @@
201 {201 {
202 }202 }
203203
204 const KnownEntries known_entries = {204 KnownEntries const known_entries = {
205 { scope_config_group,205 { scope_config_group,
206 {206 {
207 overrideable_key,207 overrideable_key,
@@ -216,7 +216,7 @@
216 location_data_needed_key,216 location_data_needed_key,
217 scoperunner_key,217 scoperunner_key,
218 idle_timeout_key,218 idle_timeout_key,
219 results_ttl_str219 results_ttl_key
220 }220 }
221 },221 },
222 { scope_appearance_group,222 { scope_appearance_group,
223223
=== modified file 'src/scopes/internal/ScopeLoader.cpp'
--- src/scopes/internal/ScopeLoader.cpp 2014-07-02 05:17:19 +0000
+++ src/scopes/internal/ScopeLoader.cpp 2014-07-28 11:21:43 +0000
@@ -23,11 +23,7 @@
23#include <unity/scopes/Version.h>23#include <unity/scopes/Version.h>
24#include <unity/UnityExceptions.h>24#include <unity/UnityExceptions.h>
2525
26#include <boost/filesystem.hpp>
27
28#include <cassert>26#include <cassert>
29#include <libgen.h>
30#include <sys/stat.h>
3127
32using namespace std;28using namespace std;
33using namespace unity::scopes;29using namespace unity::scopes;
@@ -42,13 +38,9 @@
42namespace internal38namespace internal
43{39{
4440
45ScopeLoader::ScopeLoader(string const& scope_id,41ScopeLoader::ScopeLoader(string const& scope_id, string const& libpath) :
46 string const& libpath,
47 string const& data_dir,
48 RegistryProxy const& registry) :
49 scope_id_(scope_id),42 scope_id_(scope_id),
50 dyn_loader_(DynamicLoader::create(libpath, DynamicLoader::Binding::now, DynamicLoader::Unload::noclose)),43 dyn_loader_(DynamicLoader::create(libpath, DynamicLoader::Binding::now, DynamicLoader::Unload::noclose)),
51 registry_(registry),
52 scope_base_(nullptr, reinterpret_cast<DestroyFunction>(dyn_loader_->find_function(UNITY_SCOPE_DESTROY_SYMSTR))),44 scope_base_(nullptr, reinterpret_cast<DestroyFunction>(dyn_loader_->find_function(UNITY_SCOPE_DESTROY_SYMSTR))),
53 scope_state_(ScopeState::Stopped)45 scope_state_(ScopeState::Stopped)
54{46{
@@ -62,26 +54,6 @@
62 {54 {
63 throw unity::ResourceException("Scope " + scope_id_ + " returned nullptr from " + UNITY_SCOPE_CREATE_SYMSTR);55 throw unity::ResourceException("Scope " + scope_id_ + " returned nullptr from " + UNITY_SCOPE_CREATE_SYMSTR);
64 }56 }
65
66 {
67 boost::filesystem::path libp(libpath);
68 boost::filesystem::path scope_dir(libp.parent_path());
69 scope_base_->p->set_scope_directory(scope_dir.native());
70 }
71
72 string settings_dir = data_dir + "/" + scope_id;
73 string scope_dir = scope_base_->scope_directory();
74 string settings_db = settings_dir + "/settings.db";
75 string settings_schema = scope_dir + "/" + scope_id + "-settings.ini";
76 if (boost::filesystem::exists(settings_schema))
77 {
78 // Make sure the settings directories exist. (No permission for group and others; data might be sensitive.)
79 ::mkdir(data_dir.c_str(), 0700);
80 ::mkdir(settings_dir.c_str(), 0700);
81
82 shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema));
83 scope_base_->p->set_settings_db(db);
84 }
85}57}
8658
87ScopeLoader::~ScopeLoader()59ScopeLoader::~ScopeLoader()
@@ -95,12 +67,9 @@
95 }67 }
96}68}
9769
98ScopeLoader::UPtr ScopeLoader::load(string const& scope_id,70ScopeLoader::UPtr ScopeLoader::load(string const& scope_id, string const& libpath)
99 string const& libpath,
100 string const& data_dir,
101 RegistryProxy const& registry)
102{71{
103 return UPtr(new ScopeLoader(scope_id, libpath, data_dir, registry));72 return UPtr(new ScopeLoader(scope_id, libpath));
104}73}
10574
106void ScopeLoader::unload()75void ScopeLoader::unload()
@@ -142,7 +111,7 @@
142111
143 try112 try
144 {113 {
145 scope_base_->start(scope_id_, registry_);114 scope_base_->start(scope_id_);
146 }115 }
147 catch (...)116 catch (...)
148 {117 {
149118
=== modified file 'src/scopes/internal/zmq_middleware/ZmqConfig.cpp'
--- src/scopes/internal/zmq_middleware/ZmqConfig.cpp 2014-07-22 04:01:45 +0000
+++ src/scopes/internal/zmq_middleware/ZmqConfig.cpp 2014-07-28 11:21:43 +0000
@@ -88,7 +88,7 @@
88 registry_endpoint_dir_ = get_optional_string(zmq_config_group, registry_endpoint_dir_key);88 registry_endpoint_dir_ = get_optional_string(zmq_config_group, registry_endpoint_dir_key);
89 ss_registry_endpoint_dir_ = get_optional_string(zmq_config_group, ss_registry_endpoint_dir_key);89 ss_registry_endpoint_dir_ = get_optional_string(zmq_config_group, ss_registry_endpoint_dir_key);
9090
91 const KnownEntries known_entries = {91 KnownEntries const known_entries = {
92 { zmq_config_group,92 { zmq_config_group,
93 {93 {
94 endpoint_dir_key,94 endpoint_dir_key,
9595
=== modified file 'test/CMakeLists.txt'
--- test/CMakeLists.txt 2014-07-07 23:53:36 +0000
+++ test/CMakeLists.txt 2014-07-28 11:21:43 +0000
@@ -4,3 +4,4 @@
4endif()4endif()
5add_subdirectory(copyright)5add_subdirectory(copyright)
6add_subdirectory(whitespace)6add_subdirectory(whitespace)
7add_subdirectory(autopkg)
78
=== added directory 'test/autopkg'
=== added file 'test/autopkg/CMakeLists.txt'
--- test/autopkg/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ test/autopkg/CMakeLists.txt 2014-07-28 11:21:43 +0000
@@ -0,0 +1,4 @@
1add_executable(scopetest ${CMAKE_SOURCE_DIR}/debian/tests/scopetest.cpp)
2target_link_libraries(scopetest ${UNITY_SCOPES_LIB} ${OTHER_LIBS})
3
4add_test(autopkg-scopetest scopetest)
05
=== modified file 'test/gtest/scopes/Activation/TestScope.h'
--- test/gtest/scopes/Activation/TestScope.h 2014-06-17 11:20:48 +0000
+++ test/gtest/scopes/Activation/TestScope.h 2014-07-28 11:21:43 +0000
@@ -98,7 +98,7 @@
98class TestScope : public ScopeBase98class TestScope : public ScopeBase
99{99{
100public:100public:
101 virtual void start(std::string const&, RegistryProxy const &) override {}101 virtual void start(std::string const&) override {}
102102
103 virtual void stop() override {}103 virtual void stop() override {}
104104
105105
=== modified file 'test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp'
--- test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp 2014-06-17 11:20:48 +0000
+++ test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp 2014-07-28 11:21:43 +0000
@@ -50,7 +50,7 @@
5050
51} // namespace51} // namespace
5252
53void SlowSearchScope::start(string const&, RegistryProxy const &)53void SlowSearchScope::start(string const&)
54{54{
55}55}
5656
5757
=== modified file 'test/gtest/scopes/IdleShutdown/SlowSearchScope.h'
--- test/gtest/scopes/IdleShutdown/SlowSearchScope.h 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/IdleShutdown/SlowSearchScope.h 2014-07-28 11:21:43 +0000
@@ -27,7 +27,7 @@
27class SlowSearchScope : public ScopeBase27class SlowSearchScope : public ScopeBase
28{28{
29public:29public:
30 virtual void start(string const&, RegistryProxy const &) override;30 virtual void start(string const&) override;
3131
32 virtual void stop() override;32 virtual void stop() override;
3333
3434
=== modified file 'test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp'
--- test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp 2014-06-17 11:20:48 +0000
+++ test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp 2014-07-28 11:21:43 +0000
@@ -64,7 +64,7 @@
64class MyScope : public ScopeBase64class MyScope : public ScopeBase
65{65{
66public:66public:
67 virtual void start(string const&, RegistryProxy const&) override {}67 virtual void start(string const&) override {}
6868
69 virtual void stop() override {}69 virtual void stop() override {}
7070
7171
=== modified file 'test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp'
--- test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp 2014-06-17 11:20:48 +0000
+++ test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp 2014-07-28 11:21:43 +0000
@@ -77,7 +77,7 @@
77class MyScope : public ScopeBase77class MyScope : public ScopeBase
78{78{
79public:79public:
80 virtual void start(string const&, RegistryProxy const&) override {}80 virtual void start(string const&) override {}
8181
82 virtual void stop() override {}82 virtual void stop() override {}
8383
8484
=== modified file 'test/gtest/scopes/Runtime/PusherScope.h'
--- test/gtest/scopes/Runtime/PusherScope.h 2014-07-24 13:51:38 +0000
+++ test/gtest/scopes/Runtime/PusherScope.h 2014-07-28 11:21:43 +0000
@@ -21,14 +21,13 @@
2121
22#include <unity/scopes/ScopeBase.h>22#include <unity/scopes/ScopeBase.h>
2323
24using namespace std;24class PusherScope : public unity::scopes::ScopeBase
25using namespace unity::scopes;
26
27class PusherScope : public ScopeBase
28{25{
29public:26public:
30 virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override;27 virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
31 virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) override;28 unity::scopes::SearchMetadata const&) override;
29 virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
30 unity::scopes::ActionMetadata const&) override;
32};31};
3332
34#endif33#endif
3534
=== modified file 'test/gtest/scopes/Runtime/SlowCreateScope.h'
--- test/gtest/scopes/Runtime/SlowCreateScope.h 2014-07-24 13:51:38 +0000
+++ test/gtest/scopes/Runtime/SlowCreateScope.h 2014-07-28 11:21:43 +0000
@@ -21,14 +21,13 @@
2121
22#include <unity/scopes/ScopeBase.h>22#include <unity/scopes/ScopeBase.h>
2323
24using namespace std;24class SlowCreateScope : public unity::scopes::ScopeBase
25using namespace unity::scopes;
26
27class SlowCreateScope : public ScopeBase
28{25{
29public:26public:
30 virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override;27 virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
31 virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override;28 unity::scopes::SearchMetadata const&) override;
29 virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
30 unity::scopes::ActionMetadata const&) override;
32};31};
3332
34#endif33#endif
3534
=== modified file 'test/gtest/scopes/ScopeBase/ScopeBase_test.cpp'
--- test/gtest/scopes/ScopeBase/ScopeBase_test.cpp 2014-07-07 23:53:36 +0000
+++ test/gtest/scopes/ScopeBase/ScopeBase_test.cpp 2014-07-28 11:21:43 +0000
@@ -65,7 +65,7 @@
65 EXPECT_EQ(UNITY_SCOPES_VERSION_MINOR, vminor);65 EXPECT_EQ(UNITY_SCOPES_VERSION_MINOR, vminor);
66 EXPECT_EQ(UNITY_SCOPES_VERSION_MICRO, vmicro);66 EXPECT_EQ(UNITY_SCOPES_VERSION_MICRO, vmicro);
6767
68 b->start("some_scope", nullptr);68 b->start("some_scope");
69 b->stop();69 b->stop();
70 destroy(b);70 destroy(b);
71}71}
7272
=== modified file 'test/gtest/scopes/ScopeBase/scopelib.cpp'
--- test/gtest/scopes/ScopeBase/scopelib.cpp 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/ScopeBase/scopelib.cpp 2014-07-28 11:21:43 +0000
@@ -25,7 +25,7 @@
25public:25public:
26 MyScope() {}26 MyScope() {}
2727
28 virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override {}28 virtual void start(std::string const&) override {}
29 virtual void stop() override {}29 virtual void stop() override {}
30 virtual void run() override {}30 virtual void run() override {}
3131
3232
=== modified file 'test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp'
--- test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-06-27 02:19:43 +0000
+++ test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-07-28 11:21:43 +0000
@@ -125,7 +125,7 @@
125 }125 }
126 catch(ConfigException const& e)126 catch(ConfigException const& e)
127 {127 {
128 boost::regex r("unity::scopes::ConfigException: \".*\": Illegal value \\(blah\\) for ResultsTtlType");128 boost::regex r("unity::scopes::ConfigException: \".*\": Illegal value \\(\"blah\"\\) for ResultsTtlType");
129 EXPECT_TRUE(boost::regex_match(e.what(), r));129 EXPECT_TRUE(boost::regex_match(e.what(), r));
130 }130 }
131}131}
132132
=== modified file 'test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in'
--- test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-06-26 12:49:46 +0000
+++ test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-07-28 11:21:43 +0000
@@ -15,6 +15,7 @@
15IdleTimeout = 30015IdleTimeout = 300
16ResultsTtlType = large16ResultsTtlType = large
17LocationDataNeeded = true17LocationDataNeeded = true
18ConfinementType = unconfined
1819
19[Appearance]20[Appearance]
20arbitrary_key = true21arbitrary_key = true
2122
=== modified file 'test/gtest/scopes/internal/ScopeLoader/MyScope.h'
--- test/gtest/scopes/internal/ScopeLoader/MyScope.h 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/internal/ScopeLoader/MyScope.h 2014-07-28 11:21:43 +0000
@@ -31,7 +31,7 @@
31 MyScope() {}31 MyScope() {}
32 virtual ~MyScope() {}32 virtual ~MyScope() {}
3333
34 virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override34 virtual void start(std::string const&) override
35 {35 {
36 inc_start();36 inc_start();
37 }37 }
3838
=== modified file 'test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp'
--- test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp 2014-07-28 11:21:43 +0000
@@ -30,7 +30,7 @@
30class ScopeA : public MyScope30class ScopeA : public MyScope
31{31{
32public:32public:
33 virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override33 virtual void start(std::string const&) override
34 {34 {
35 inc_start();35 inc_start();
36 }36 }
3737
=== modified file 'test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp'
--- test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp 2014-07-28 11:21:43 +0000
@@ -30,7 +30,7 @@
30class ScopeA : public MyScope30class ScopeA : public MyScope
31{31{
32public:32public:
33 virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override33 virtual void start(std::string const&) override
34 {34 {
35 inc_start();35 inc_start();
36 }36 }
3737
=== modified file 'test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp'
--- test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp 2014-07-01 08:39:17 +0000
+++ test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp 2014-07-28 11:21:43 +0000
@@ -47,11 +47,6 @@
47char const* scopeB = TEST_DIR "/libScopeB.so";47char const* scopeB = TEST_DIR "/libScopeB.so";
48}48}
4949
50// Need to make a dummy registry proxy because, if we pass a null shared_ptr to load(),
51// load() throws an exception.
52
53RegistryProxy registry(make_shared<RegistryImpl>(nullptr, (RuntimeImpl*)0x1));
54
55// Basic test.50// Basic test.
5651
57TEST(ScopeLoader, basic)52TEST(ScopeLoader, basic)
@@ -59,13 +54,12 @@
59 reset_counters();54 reset_counters();
6055
61 {56 {
62 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);57 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
63 EXPECT_EQ(1, num_create());58 EXPECT_EQ(1, num_create());
64 EXPECT_EQ(0, num_destroy());59 EXPECT_EQ(0, num_destroy());
6560
66 EXPECT_EQ("testScope", sl->scope_id());61 EXPECT_EQ("testScope", sl->scope_id());
67 EXPECT_EQ(scope_lib, sl->libpath());62 EXPECT_EQ(scope_lib, sl->libpath());
68 EXPECT_EQ(TEST_DIR, sl->scope_base()->scope_directory());
69 }63 }
70 EXPECT_EQ(1, num_create());64 EXPECT_EQ(1, num_create());
71 EXPECT_EQ(1, num_destroy());65 EXPECT_EQ(1, num_destroy());
@@ -78,7 +72,7 @@
78 reset_counters();72 reset_counters();
7973
80 {74 {
81 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);75 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
8276
83 // Check that calling stop on a stopped thread does nothing.77 // Check that calling stop on a stopped thread does nothing.
84 sl->stop();78 sl->stop();
@@ -116,7 +110,7 @@
116 reset_counters();110 reset_counters();
117111
118 {112 {
119 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);113 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
120114
121 sl->start();115 sl->start();
122 EXPECT_EQ(1, num_start());116 EXPECT_EQ(1, num_start());
@@ -136,7 +130,7 @@
136130
137 try131 try
138 {132 {
139 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", "no_such_lib", TEST_DIR, registry);133 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", "no_such_lib");
140 FAIL();134 FAIL();
141 }135 }
142 catch (unity::Exception const& e)136 catch (unity::Exception const& e)
@@ -156,7 +150,7 @@
156150
157 try151 try
158 {152 {
159 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", no_destroy_lib, TEST_DIR, registry);153 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", no_destroy_lib);
160 FAIL();154 FAIL();
161 }155 }
162 catch (unity::Exception const& e)156 catch (unity::Exception const& e)
@@ -176,7 +170,7 @@
176170
177 try171 try
178 {172 {
179 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib, TEST_DIR, registry);173 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib);
180 FAIL();174 FAIL();
181 }175 }
182 catch (unity::Exception const& e)176 catch (unity::Exception const& e)
@@ -197,7 +191,7 @@
197191
198 try192 try
199 {193 {
200 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib, TEST_DIR, registry);194 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib);
201 sl->unload();195 sl->unload();
202 FAIL();196 FAIL();
203 }197 }
@@ -217,7 +211,7 @@
217{211{
218 reset_counters();212 reset_counters();
219 {213 {
220 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, TEST_DIR, registry);214 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib);
221 try215 try
222 {216 {
223 sl->start();217 sl->start();
@@ -242,7 +236,7 @@
242{236{
243 reset_counters();237 reset_counters();
244 {238 {
245 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, TEST_DIR, registry);239 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib);
246 try240 try
247 {241 {
248 sl->start();242 sl->start();
@@ -266,7 +260,7 @@
266{260{
267 reset_counters();261 reset_counters();
268 {262 {
269 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_start_lib, TEST_DIR, registry);263 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_start_lib);
270 try264 try
271 {265 {
272 sl->start();266 sl->start();
@@ -293,7 +287,7 @@
293 reset_counters();287 reset_counters();
294 try288 try
295 {289 {
296 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib, TEST_DIR, registry);290 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib);
297 sl->start();291 sl->start();
298 sl->stop();292 sl->stop();
299 EXPECT_EQ(1, num_start());293 EXPECT_EQ(1, num_start());
@@ -319,7 +313,7 @@
319 reset_counters();313 reset_counters();
320 try314 try
321 {315 {
322 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_std_ex_from_stop_lib, TEST_DIR, registry);316 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_std_ex_from_stop_lib);
323 sl->start();317 sl->start();
324 sl->stop();318 sl->stop();
325 EXPECT_EQ(1, num_start());319 EXPECT_EQ(1, num_start());
@@ -345,7 +339,7 @@
345 reset_counters();339 reset_counters();
346 try340 try
347 {341 {
348 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_stop_lib, TEST_DIR, registry);342 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_stop_lib);
349 sl->start();343 sl->start();
350 sl->stop();344 sl->stop();
351 EXPECT_EQ(1, num_start());345 EXPECT_EQ(1, num_start());
@@ -369,7 +363,7 @@
369{363{
370 reset_counters();364 reset_counters();
371365
372 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);366 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
373 sl->start();367 sl->start();
374 sl->stop();368 sl->stop();
375 sl->unload();369 sl->unload();
@@ -387,7 +381,7 @@
387{381{
388 reset_counters();382 reset_counters();
389383
390 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib, TEST_DIR, registry);384 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib);
391 sl->start();385 sl->start();
392 try386 try
393 {387 {
@@ -418,7 +412,7 @@
418{412{
419 reset_counters();413 reset_counters();
420414
421 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);415 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
422 sl->start();416 sl->start();
423 sl->unload();417 sl->unload();
424 try418 try
@@ -438,7 +432,7 @@
438{432{
439 reset_counters();433 reset_counters();
440434
441 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);435 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
442 sl->start();436 sl->start();
443 sl->unload();437 sl->unload();
444 try438 try
@@ -458,7 +452,7 @@
458{452{
459 reset_counters();453 reset_counters();
460454
461 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, TEST_DIR, registry);455 ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib);
462 try456 try
463 {457 {
464 sl->start();458 sl->start();
@@ -495,12 +489,12 @@
495 reset_counters();489 reset_counters();
496 clear_vars();490 clear_vars();
497491
498 ScopeLoader::UPtr slA = ScopeLoader::load("scopeA", scopeA, TEST_DIR, registry);492 ScopeLoader::UPtr slA = ScopeLoader::load("scopeA", scopeA);
499 slA->start();493 slA->start();
500 EXPECT_EQ(1, num_create());494 EXPECT_EQ(1, num_create());
501 EXPECT_EQ(1, num_start());495 EXPECT_EQ(1, num_start());
502496
503 ScopeLoader::UPtr slB = ScopeLoader::load("scopeB", scopeB, TEST_DIR, registry);497 ScopeLoader::UPtr slB = ScopeLoader::load("scopeB", scopeB);
504 slB->start();498 slB->start();
505 EXPECT_EQ(2, num_create());499 EXPECT_EQ(2, num_create());
506 EXPECT_EQ(2, num_start());500 EXPECT_EQ(2, num_start());
507501
=== modified file 'test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp'
--- test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp 2014-07-28 11:21:43 +0000
@@ -29,7 +29,7 @@
29class EXPORT MyThrowingScope : public MyScope29class EXPORT MyThrowingScope : public MyScope
30{30{
31public:31public:
32 virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override32 virtual void start(std::string const&) override
33 {33 {
34 inc_start();34 inc_start();
35 throw unity::LogicException("start failure");35 throw unity::LogicException("start failure");
3636
=== modified file 'test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp'
--- test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp 2014-07-28 11:21:43 +0000
@@ -28,7 +28,7 @@
28class EXPORT MyThrowingScope : public MyScope28class EXPORT MyThrowingScope : public MyScope
29{29{
30public:30public:
31 virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override31 virtual void start(std::string const&) override
32 {32 {
33 inc_start();33 inc_start();
34 throw 42;34 throw 42;
3535
=== modified file 'test/gtest/scopes/testing/IsolatedScope/scope.cpp'
--- test/gtest/scopes/testing/IsolatedScope/scope.cpp 2014-06-18 09:50:21 +0000
+++ test/gtest/scopes/testing/IsolatedScope/scope.cpp 2014-07-28 11:21:43 +0000
@@ -91,7 +91,8 @@
91{91{
92public:92public:
93 Query(unity::scopes::CannedQuery const& query, unity::scopes::SearchMetadata const& metadata, unity::scopes::RegistryProxy const& registry)93 Query(unity::scopes::CannedQuery const& query, unity::scopes::SearchMetadata const& metadata, unity::scopes::RegistryProxy const& registry)
94 : unity::scopes::SearchQueryBase(query, metadata), registry_(registry)94 : unity::scopes::SearchQueryBase(query, metadata)
95 , registry_(registry)
95 {96 {
96 }97 }
9798
@@ -167,9 +168,15 @@
167168
168} // namespace testing169} // namespace testing
169170
170void testing::Scope::start(std::string const&, unity::scopes::RegistryProxy const &registry)171testing::Scope::Scope(unity::scopes::RegistryProxy const& r)
171{172 : registry_(r)
172 registry_ = registry;173{
174}
175
176testing::Scope::~Scope() = default;
177
178void testing::Scope::start(std::string const&)
179{
173}180}
174181
175void testing::Scope::stop()182void testing::Scope::stop()
@@ -184,7 +191,7 @@
184 unity::scopes::CannedQuery const& query,191 unity::scopes::CannedQuery const& query,
185 unity::scopes::SearchMetadata const &metadata)192 unity::scopes::SearchMetadata const &metadata)
186{193{
187 return unity::scopes::SearchQueryBase::UPtr(new testing::Query(query, metadata, registry_));194 return unity::scopes::SearchQueryBase::UPtr(new testing::Query(query, metadata, registry()));
188}195}
189196
190unity::scopes::ActivationQueryBase::UPtr testing::Scope::activate(197unity::scopes::ActivationQueryBase::UPtr testing::Scope::activate(
@@ -209,3 +216,23 @@
209{216{
210 return unity::scopes::PreviewQueryBase::UPtr(new testing::Preview(result, metadata));217 return unity::scopes::PreviewQueryBase::UPtr(new testing::Preview(result, metadata));
211}218}
219
220std::string testing::Scope::scope_directory() const
221{
222 return "";
223}
224
225std::string testing::Scope::cache_directory() const
226{
227 return "";
228}
229
230unity::scopes::RegistryProxy testing::Scope::registry() const
231{
232 return registry_;
233}
234
235unity::scopes::VariantMap testing::Scope::settings() const
236{
237 return unity::scopes::VariantMap();
238}
212239
=== modified file 'test/gtest/scopes/testing/IsolatedScope/scope.h'
--- test/gtest/scopes/testing/IsolatedScope/scope.h 2014-06-18 09:50:21 +0000
+++ test/gtest/scopes/testing/IsolatedScope/scope.h 2014-07-28 11:21:43 +0000
@@ -17,15 +17,19 @@
17 * Thomas Voß <thomas.voss@canonical.com>17 * Thomas Voß <thomas.voss@canonical.com>
18 */18 */
1919
20#include <unity/scopes/ScopeBase.h>20#include <unity/scopes/AbstractScopeBase.h>
21#include <unity/scopes/testing/MockRegistry.h>
2122
22namespace testing23namespace testing
23{24{
2425
25class Scope : public unity::scopes::ScopeBase26class Scope : public unity::scopes::AbstractScopeBase
26{27{
27public:28public:
28 void start(std::string const&, unity::scopes::RegistryProxy const &) override;29 Scope(unity::scopes::RegistryProxy const&);
30 virtual ~Scope();
31
32 void start(std::string const&) override;
2933
30 void stop() override;34 void stop() override;
3135
@@ -49,6 +53,14 @@
49 unity::scopes::Result const&,53 unity::scopes::Result const&,
50 unity::scopes::ActionMetadata const &) override;54 unity::scopes::ActionMetadata const &) override;
5155
56 std::string scope_directory() const override;
57
58 std::string cache_directory() const override;
59
60 unity::scopes::RegistryProxy registry() const override;
61
62 unity::scopes::VariantMap settings() const override;
63
52 unity::scopes::RegistryProxy registry_;64 unity::scopes::RegistryProxy registry_;
53};65};
5466
5567
=== modified file 'test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp'
--- test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp 2014-04-03 12:57:25 +0000
+++ test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp 2014-07-28 11:21:43 +0000
@@ -55,7 +55,7 @@
55 return "BenchmarkingScope";55 return "BenchmarkingScope";
56 }56 }
5757
58 inline static std::shared_ptr<::testing::Scope> construct()58 inline static std::shared_ptr<::testing::Scope> construct(unity::scopes::RegistryProxy const&)
59 {59 {
60 return std::make_shared<::testing::Scope>(mean, variance);60 return std::make_shared<::testing::Scope>(mean, variance);
61 }61 }
6262
=== modified file 'test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp'
--- test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp 2014-06-17 11:20:48 +0000
+++ test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp 2014-07-28 11:21:43 +0000
@@ -155,7 +155,7 @@
155{155{
156}156}
157157
158void testing::Scope::start(std::string const&, unity::scopes::RegistryProxy const &)158void testing::Scope::start(std::string const&)
159{159{
160}160}
161161
162162
=== modified file 'test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h'
--- test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h 2014-06-17 09:27:49 +0000
+++ test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h 2014-07-28 11:21:43 +0000
@@ -30,7 +30,7 @@
30public:30public:
31 Scope(const std::chrono::milliseconds& mean, const std::chrono::milliseconds& variance);31 Scope(const std::chrono::milliseconds& mean, const std::chrono::milliseconds& variance);
3232
33 void start(std::string const&, unity::scopes::RegistryProxy const &) override;33 void start(std::string const&) override;
3434
35 void stop() override;35 void stop() override;
3636
3737
=== modified file 'test/headers/CMakeLists.txt'
--- test/headers/CMakeLists.txt 2014-01-24 09:55:09 +0000
+++ test/headers/CMakeLists.txt 2014-07-28 11:21:43 +0000
@@ -6,6 +6,7 @@
66
7set(subdirs7set(subdirs
8 unity/scopes8 unity/scopes
9 unity/scopes/testing
9)10)
10foreach(dir ${OTHER_INCLUDE_DIRS})11foreach(dir ${OTHER_INCLUDE_DIRS})
11 set(other_inc_dirs "${other_inc_dirs} -I${dir}")12 set(other_inc_dirs "${other_inc_dirs} -I${dir}")
@@ -26,9 +27,11 @@
26 ${public_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${public_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}")27 ${public_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${public_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}")
2728
28 # Test that each internal header compiles stand-alone.29 # Test that each internal header compiles stand-alone.
29 add_test(stand-alone-${location}-internal-headers30 if (IS_DIRECTORY ${internal_inc_dir})
30 ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py31 add_test(stand-alone-${location}-internal-headers
31 ${internal_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${internal_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}")32 ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py
33 ${internal_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${internal_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}")
34 endif()
3235
33 # Test that no public header includes an internal header36 # Test that no public header includes an internal header
34 add_test(clean-public-${location}-headers ${CMAKE_CURRENT_SOURCE_DIR}/check_public_headers.py ${public_inc_dir})37 add_test(clean-public-${location}-headers ${CMAKE_CURRENT_SOURCE_DIR}/check_public_headers.py ${public_inc_dir})
3538
=== modified file 'test/headers/check_public_headers.py'
--- test/headers/check_public_headers.py 2013-06-27 08:38:02 +0000
+++ test/headers/check_public_headers.py 2014-07-28 11:21:43 +0000
@@ -53,7 +53,7 @@
53 for hdr in hdrs:53 for hdr in hdrs:
54 try:54 try:
55 hdr_name = os.path.join(hdr_dir, hdr)55 hdr_name = os.path.join(hdr_dir, hdr)
56 file = open(hdr_name, "r")56 file = open(hdr_name, 'r', encoding = 'utf=8')
57 except OSError as e:57 except OSError as e:
58 error("cannot open \"" + hdr_name + "\": " + e.strerror)58 error("cannot open \"" + hdr_name + "\": " + e.strerror)
59 sys.exit(1)59 sys.exit(1)

Subscribers

People subscribed via source and target branches

to all changes: