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..2ad9662f0f7bd208e213d7067dba2da1d78becfe 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,36 @@ 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 kArcServiceName[]; |
+// ... |
+// }; |
+// |
+// it can then be retrieved from ArcServiceManager in a type-safe way using |
+// GetService<T>(). This two functions allow AddService() to get the name only |
+// if it was provided, or use an empty string otherwise. |
+// |
+// In order to avoid collisions, kArcServiceName should be the fully-qualified |
hidehiko
2017/01/11 05:17:45
So, as you explicitly specify the template typenam
Luis Héctor Chávez
2017/01/11 16:01:36
Done.
|
+// name of the class. |
+template <typename T> |
+decltype(T::kArcServiceName, std::string()) GetArcServiceName(T* unused) { |
+ if (strlen(T::kArcServiceName) == 0) |
hidehiko
2017/01/11 05:17:45
Optional: or, static_assert for compile time check
Luis Héctor Chávez
2017/01/11 16:01:36
Tried that before, compiler didn't like it since T
|
+ LOG(ERROR) << "kArcServiceName[] should be a fully-qualified class name."; |
+ return T::kArcServiceName; |
+} |
+ |
+template <typename T> |
+std::string GetArcServiceName(...) { |
+ return std::string(); |
+} |
+ |
+} // namespace internal |
+ |
// Manages creation and destruction of services that communicate with the ARC |
// instance via the ArcBridgeService. |
class ArcServiceManager { |
@@ -48,8 +82,22 @@ class ArcServiceManager { |
// class was created on. |
ArcBridgeService* arc_bridge_service(); |
- // Adds a service to the managed services list. |
- void AddService(std::unique_ptr<ArcService> service); |
+ // Adds a service to the managed services list. Returns false if another |
+ // named service with that name had already been added. |
+ template <typename T> |
+ bool AddService(std::unique_ptr<T> service) { |
+ return AddServiceInternal(internal::GetArcServiceName<T>(nullptr), |
+ std::move(service)); |
+ } |
+ |
+ // Gets the named service from the managed services list. This uses SFINAE, so |
+ // you can only call this function if the service specified by T provides a |
+ // static member variable called kArcServiceName[] (otherwise this will not |
+ // compile). |
+ template <typename T> |
+ T* GetService() { |
+ return static_cast<T*>(GetNamedServiceInternal(T::kArcServiceName)); |
+ } |
// 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 +129,11 @@ class ArcServiceManager { |
private: |
class IntentHelperObserverImpl; // implemented in arc_service_manager.cc. |
+ // Helper methods for AddService and GetService. |
+ bool AddServiceInternal(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_; |
@@ -88,7 +141,7 @@ class ArcServiceManager { |
std::unique_ptr<ArcIntentHelperObserver> intent_helper_observer_; |
std::unique_ptr<ArcBridgeService> arc_bridge_service_; |
- std::vector<std::unique_ptr<ArcService>> services_; |
+ std::unordered_multimap<std::string, std::unique_ptr<ArcService>> services_; |
scoped_refptr<ActivityIconLoader> icon_loader_; |
scoped_refptr<LocalActivityResolver> activity_resolver_; |