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);