Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / application_manager / background_shell_application_loader.cc
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.
4
5 #include "mojo/application_manager/background_shell_application_loader.h"
6
7 #include "base/bind.h"
8 #include "base/run_loop.h"
9 #include "mojo/application_manager/application_manager.h"
10
11 namespace mojo {
12
13 class BackgroundShellApplicationLoader::BackgroundLoader {
14  public:
15   explicit BackgroundLoader(ApplicationLoader* loader) : loader_(loader) {}
16   ~BackgroundLoader() {}
17
18   void Load(ApplicationManager* manager,
19             const GURL& url,
20             ScopedMessagePipeHandle shell_handle) {
21     scoped_refptr<LoadCallbacks> callbacks(
22         new ApplicationLoader::SimpleLoadCallbacks(shell_handle.Pass()));
23     loader_->Load(manager, url, callbacks);
24   }
25
26   void OnServiceError(ApplicationManager* manager, const GURL& url) {
27     loader_->OnServiceError(manager, url);
28   }
29
30  private:
31   ApplicationLoader* loader_;  // Owned by BackgroundShellApplicationLoader
32
33   DISALLOW_COPY_AND_ASSIGN(BackgroundLoader);
34 };
35
36 BackgroundShellApplicationLoader::BackgroundShellApplicationLoader(
37     scoped_ptr<ApplicationLoader> real_loader,
38     const std::string& thread_name,
39     base::MessageLoop::Type message_loop_type)
40     : loader_(real_loader.Pass()),
41       message_loop_type_(message_loop_type),
42       thread_name_(thread_name),
43       message_loop_created_(true, false),
44       background_loader_(NULL) {
45 }
46
47 BackgroundShellApplicationLoader::~BackgroundShellApplicationLoader() {
48   if (thread_)
49     thread_->Join();
50 }
51
52 void BackgroundShellApplicationLoader::Load(
53     ApplicationManager* manager,
54     const GURL& url,
55     scoped_refptr<LoadCallbacks> callbacks) {
56   ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
57   if (!shell_handle.is_valid())
58     return;
59
60   if (!thread_) {
61     // TODO(tim): It'd be nice if we could just have each Load call
62     // result in a new thread like DynamicService{Loader, Runner}. But some
63     // loaders are creating multiple ApplicationImpls (NetworkApplicationLoader)
64     // sharing a delegate (etc). So we have to keep it single threaded, wait
65     // for the thread to initialize, and post to the TaskRunner for subsequent
66     // Load calls for now.
67     thread_.reset(new base::DelegateSimpleThread(this, thread_name_));
68     thread_->Start();
69     message_loop_created_.Wait();
70     DCHECK(task_runner_);
71   }
72
73   task_runner_->PostTask(
74       FROM_HERE,
75       base::Bind(
76           &BackgroundShellApplicationLoader::LoadOnBackgroundThread,
77           base::Unretained(this),
78           manager,
79           url,
80           base::Owned(new ScopedMessagePipeHandle(shell_handle.Pass()))));
81 }
82
83 void BackgroundShellApplicationLoader::OnServiceError(
84     ApplicationManager* manager,
85     const GURL& url) {
86   task_runner_->PostTask(
87       FROM_HERE,
88       base::Bind(
89           &BackgroundShellApplicationLoader::OnServiceErrorOnBackgroundThread,
90           base::Unretained(this),
91           manager,
92           url));
93 }
94
95 void BackgroundShellApplicationLoader::Run() {
96   base::MessageLoop message_loop(message_loop_type_);
97   base::RunLoop loop;
98   task_runner_ = message_loop.task_runner();
99   quit_closure_ = loop.QuitClosure();
100   message_loop_created_.Signal();
101   loop.Run();
102
103   delete background_loader_;
104   background_loader_ = NULL;
105   // Destroy |loader_| on the thread it's actually used on.
106   loader_.reset();
107 }
108
109 void BackgroundShellApplicationLoader::LoadOnBackgroundThread(
110     ApplicationManager* manager,
111     const GURL& url,
112     ScopedMessagePipeHandle* shell_handle) {
113   DCHECK(task_runner_->RunsTasksOnCurrentThread());
114   if (!background_loader_)
115     background_loader_ = new BackgroundLoader(loader_.get());
116   background_loader_->Load(manager, url, shell_handle->Pass());
117 }
118
119 void BackgroundShellApplicationLoader::OnServiceErrorOnBackgroundThread(
120     ApplicationManager* manager,
121     const GURL& url) {
122   DCHECK(task_runner_->RunsTasksOnCurrentThread());
123   if (!background_loader_)
124     background_loader_ = new BackgroundLoader(loader_.get());
125   background_loader_->OnServiceError(manager, url);
126 }
127
128 }  // namespace mojo