1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "mojo/shell/dynamic_service_loader.h"
7 #include "base/command_line.h"
8 #include "base/location.h"
9 #include "mojo/shell/context.h"
10 #include "mojo/shell/keep_alive.h"
11 #include "mojo/shell/switches.h"
18 std::string
MakeSharedLibraryName(const std::string
& file_name
) {
20 return file_name
+ ".dll";
21 #elif defined(OS_LINUX)
22 return "lib" + file_name
+ ".so";
23 #elif defined(OS_MACOSX)
24 return "lib" + file_name
+ ".dylib";
26 NOTREACHED() << "dynamic loading of services not supported";
33 class DynamicServiceLoader::LoadContext
: public mojo::shell::Loader::Delegate
{
35 LoadContext(DynamicServiceLoader
* loader
,
37 ScopedMessagePipeHandle service_handle
,
38 scoped_ptr
<DynamicServiceRunner
> runner
)
41 service_handle_(service_handle
.Pass()),
42 runner_(runner
.Pass()),
43 keep_alive_(loader
->context_
) {
46 if (url
.SchemeIs("mojo")) {
48 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
50 std::string lib
= MakeSharedLibraryName(url
.ExtractFileName());
51 url_to_load
= GURL(origin
+ "/" + lib
);
56 request_
= loader_
->context_
->loader()->Load(url_to_load
, this);
59 virtual ~LoadContext() {
63 // |Loader::Delegate| method:
64 virtual void DidCompleteLoad(const GURL
& app_url
,
65 const base::FilePath
& app_path
,
66 const std::string
* mime_type
) OVERRIDE
{
67 DVLOG(2) << "Completed load of " << app_url
<< " (" << url_
<< ") to "
69 DCHECK(loader_
->context_
->task_runners()->ui_runner()->
70 BelongsToCurrentThread());
74 service_handle_
.Pass(),
75 base::Bind(&DynamicServiceLoader::AppCompleted
,
76 base::Unretained(loader_
), url_
));
79 DynamicServiceLoader
* const loader_
;
81 scoped_ptr
<mojo::shell::Loader::Job
> request_
;
82 ScopedMessagePipeHandle service_handle_
;
83 scoped_ptr
<DynamicServiceRunner
> runner_
;
84 KeepAlive keep_alive_
;
86 DISALLOW_COPY_AND_ASSIGN(LoadContext
);
89 DynamicServiceLoader::DynamicServiceLoader(
91 scoped_ptr
<DynamicServiceRunnerFactory
> runner_factory
)
93 runner_factory_(runner_factory
.Pass()) {
96 DynamicServiceLoader::~DynamicServiceLoader() {
97 DCHECK(url_to_load_context_
.empty());
100 void DynamicServiceLoader::LoadService(ServiceManager
* manager
,
102 ScopedMessagePipeHandle service_handle
) {
103 DCHECK(url_to_load_context_
.find(url
) == url_to_load_context_
.end());
104 url_to_load_context_
[url
] = new LoadContext(
105 this, url
, service_handle
.Pass(), runner_factory_
->Create(context_
));
108 void DynamicServiceLoader::OnServiceError(ServiceManager
* manager
,
112 void DynamicServiceLoader::AppCompleted(const GURL
& url
) {
113 DCHECK(context_
->task_runners()->ui_runner()->BelongsToCurrentThread());
114 DVLOG(2) << "App completed (url: " << url
<< ")";
116 LoadContextMap::iterator it
= url_to_load_context_
.find(url
);
117 DCHECK(it
!= url_to_load_context_
.end()) << url
;
119 LoadContext
* doomed
= it
->second
;
120 url_to_load_context_
.erase(it
);