Index: components/arc/arc_service_manager.h |
diff --git a/components/arc/arc_service_manager.h b/components/arc/arc_service_manager.h |
index 81a4ea9e98b2e715e289b112d3cae2660d72cbd6..129e17b857f393c8275862c95b46bebebf2cd4e0 100644 |
--- a/components/arc/arc_service_manager.h |
+++ b/components/arc/arc_service_manager.h |
@@ -6,6 +6,10 @@ |
#define COMPONENTS_ARC_ARC_SERVICE_MANAGER_H_ |
#include <memory> |
+#include <string> |
+#include <type_traits> |
+#include <unordered_map> |
+#include <utility> |
#include <vector> |
#include "base/macros.h" |
@@ -22,6 +26,38 @@ class ArcBridgeService; |
class ArcIntentHelperObserver; |
class ArcService; |
+namespace internal { |
+ |
+// If an ArcService is declared with a Name, e.g.: |
+// |
+// class MyArcService : public ArcService { |
+// public: |
+// static const char Name[]; |
Yusuke Sato
2017/01/10 07:11:11
The variable name 'Name' doesn't seem to follow th
Luis Héctor Chávez
2017/01/10 18:41:55
Done.
|
+// ... |
+// }; |
+// |
+// it can then be retrieved from ArcServiceManager in a type-safe way using |
+// Get<T>(). This struct allows the use of std::enable_if<...> to choose the |
+// correct implementation of the AddService() functions to enable this |
+// functionality. |
+template <typename T> |
hidehiko
2017/01/10 08:03:12
Optional: How about minimizing template magic? E.g
Luis Héctor Chávez
2017/01/10 18:41:56
Simplified the first function a bit, but done.
|
+struct NamedServiceTraits { |
+ private: |
+ typedef char No[1]; |
Yusuke Sato
2017/01/10 07:11:11
nit: do we have a reason to skip 0? No can be [0]
hidehiko
2017/01/10 08:03:12
FYI: 0 length is illegal, IIUC.
http://stackoverfl
Luis Héctor Chávez
2017/01/10 18:41:56
This is a commonly-used Method Detector idiom: htt
hidehiko
2017/01/11 05:17:45
Yes, I know, but it was developed in C++03 era, an
|
+ typedef char Yes[2]; |
+ |
+ template <typename U> |
+ static Yes& test(decltype(U::Name) *); |
Yusuke Sato
2017/01/10 07:11:11
nit: no space before *, maybe?
hidehiko
2017/01/10 08:03:12
Optional: Even in this way, trailing return type c
Luis Héctor Chávez
2017/01/10 18:41:56
Acknowledged.
|
+ |
+ template <typename U> |
+ static No& test(...); |
+ |
+ public: |
+ enum : bool { HasName = sizeof(test<T>(nullptr)) == sizeof(Yes) }; |
hidehiko
2017/01/10 08:03:12
With std::{true,false}_type,
constexpr bool kValu
Luis Héctor Chávez
2017/01/10 18:41:56
Acknowledged.
|
+}; |
+ |
+} // namespace internal |
+ |
// Manages creation and destruction of services that communicate with the ARC |
// instance via the ArcBridgeService. |
class ArcServiceManager { |
@@ -49,7 +85,26 @@ class ArcServiceManager { |
ArcBridgeService* arc_bridge_service(); |
// Adds a service to the managed services list. |
- void AddService(std::unique_ptr<ArcService> service); |
+ template <typename T, |
+ typename std::enable_if<!internal::NamedServiceTraits<T>::HasName, |
+ int>::type = 0> |
+ void AddService(std::unique_ptr<T> service) { |
+ AddServiceInternal(std::move(service)); |
+ } |
+ |
+ // Adds a named service to the managed services list. |
+ template <typename T, |
+ typename std::enable_if<internal::NamedServiceTraits<T>::HasName, |
+ int>::type = 0> |
+ void AddService(std::unique_ptr<T> service) { |
+ AddNamedServiceInternal(std::string(T::Name), std::move(service)); |
Yusuke Sato
2017/01/10 07:11:11
nit: the cast (to string) seems unnecessary
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
+ } |
+ |
+ // Gets the named service from the managed services list. |
Yusuke Sato
2017/01/10 07:11:11
For developers who don't want to read the template
hidehiko
2017/01/10 08:03:12
Also, could you explicitly comment that, this will
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
+ template <typename T> |
+ T* GetService() { |
Yusuke Sato
2017/01/10 07:11:11
I think GetService<T>() is easy to test. How about
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
+ return static_cast<T*>(GetNamedServiceInternal(T::Name)); |
+ } |
// Gets the global instance of the ARC Service Manager. This can only be |
// called on the thread that this class was created on. |
@@ -81,6 +136,12 @@ class ArcServiceManager { |
private: |
class IntentHelperObserverImpl; // implemented in arc_service_manager.cc. |
+ // Helper methods for AddService and GetService. |
+ void AddServiceInternal(std::unique_ptr<ArcService> service); |
+ void AddNamedServiceInternal(const std::string& name, |
+ std::unique_ptr<ArcService> service); |
+ ArcService* GetNamedServiceInternal(const std::string& name); |
+ |
base::ThreadChecker thread_checker_; |
scoped_refptr<base::TaskRunner> blocking_task_runner_; |
@@ -89,6 +150,7 @@ class ArcServiceManager { |
std::unique_ptr<ArcBridgeService> arc_bridge_service_; |
std::vector<std::unique_ptr<ArcService>> services_; |
+ std::unordered_map<std::string, std::unique_ptr<ArcService>> named_services_; |
hidehiko
2017/01/10 08:03:12
Optional: how about mergine services_ and named_se
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
scoped_refptr<ActivityIconLoader> icon_loader_; |
scoped_refptr<LocalActivityResolver> activity_resolver_; |