1 // Copyright 2013 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 "base/lazy_instance.h"
6 #include "chrome/browser/browser_process.h"
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.h"
9 #include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
10 #include "chrome/browser/extensions/api/image_writer_private/operation.h"
11 #include "chrome/browser/extensions/api/image_writer_private/operation_manager.h"
12 #include "chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h"
13 #include "chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h"
14 #include "chrome/browser/extensions/event_router_forwarder.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_service.h"
19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_host.h"
22 namespace image_writer_api = extensions::api::image_writer_private;
24 namespace extensions {
25 namespace image_writer {
27 using content::BrowserThread;
29 OperationManager::OperationManager(content::BrowserContext* context)
30 : profile_(Profile::FromBrowserContext(context)), weak_factory_(this) {
31 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
32 content::Source<Profile>(profile_));
33 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
34 content::Source<Profile>(profile_));
35 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
36 content::Source<Profile>(profile_));
37 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
38 content::Source<Profile>(profile_));
39 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
40 content::Source<Profile>(profile_));
43 OperationManager::~OperationManager() {
46 void OperationManager::Shutdown() {
47 for (OperationMap::iterator iter = operations_.begin();
48 iter != operations_.end();
50 BrowserThread::PostTask(BrowserThread::FILE,
52 base::Bind(&Operation::Abort,
57 void OperationManager::StartWriteFromUrl(
58 const ExtensionId& extension_id,
60 const std::string& hash,
61 const std::string& device_path,
62 const Operation::StartWriteCallback& callback) {
63 OperationMap::iterator existing_operation = operations_.find(extension_id);
65 if (existing_operation != operations_.end()) {
66 return callback.Run(false, error::kOperationAlreadyInProgress);
69 scoped_refptr<Operation> operation(
70 new WriteFromUrlOperation(weak_factory_.GetWeakPtr(),
72 profile_->GetRequestContext(),
76 operations_[extension_id] = operation;
77 BrowserThread::PostTask(BrowserThread::FILE,
79 base::Bind(&Operation::Start, operation));
80 callback.Run(true, "");
83 void OperationManager::StartWriteFromFile(
84 const ExtensionId& extension_id,
85 const base::FilePath& path,
86 const std::string& device_path,
87 const Operation::StartWriteCallback& callback) {
88 OperationMap::iterator existing_operation = operations_.find(extension_id);
90 if (existing_operation != operations_.end()) {
91 return callback.Run(false, error::kOperationAlreadyInProgress);
94 scoped_refptr<Operation> operation(new WriteFromFileOperation(
95 weak_factory_.GetWeakPtr(), extension_id, path, device_path));
96 operations_[extension_id] = operation;
97 BrowserThread::PostTask(BrowserThread::FILE,
99 base::Bind(&Operation::Start, operation));
100 callback.Run(true, "");
103 void OperationManager::CancelWrite(
104 const ExtensionId& extension_id,
105 const Operation::CancelWriteCallback& callback) {
106 Operation* existing_operation = GetOperation(extension_id);
108 if (existing_operation == NULL) {
109 callback.Run(false, error::kNoOperationInProgress);
111 BrowserThread::PostTask(BrowserThread::FILE,
113 base::Bind(&Operation::Cancel, existing_operation));
114 DeleteOperation(extension_id);
115 callback.Run(true, "");
119 void OperationManager::DestroyPartitions(
120 const ExtensionId& extension_id,
121 const std::string& device_path,
122 const Operation::StartWriteCallback& callback) {
123 OperationMap::iterator existing_operation = operations_.find(extension_id);
125 if (existing_operation != operations_.end()) {
126 return callback.Run(false, error::kOperationAlreadyInProgress);
129 scoped_refptr<Operation> operation(new DestroyPartitionsOperation(
130 weak_factory_.GetWeakPtr(), extension_id, device_path));
131 operations_[extension_id] = operation;
132 BrowserThread::PostTask(BrowserThread::FILE,
134 base::Bind(&Operation::Start, operation));
135 callback.Run(true, "");
138 void OperationManager::OnProgress(const ExtensionId& extension_id,
139 image_writer_api::Stage stage,
141 DCHECK_CURRENTLY_ON(BrowserThread::UI);
143 image_writer_api::ProgressInfo info;
145 info.percent_complete = progress;
147 scoped_ptr<base::ListValue> args(
148 image_writer_api::OnWriteProgress::Create(info));
149 scoped_ptr<Event> event(new Event(
150 image_writer_api::OnWriteProgress::kEventName, args.Pass()));
152 EventRouter::Get(profile_)
153 ->DispatchEventToExtension(extension_id, event.Pass());
156 void OperationManager::OnComplete(const ExtensionId& extension_id) {
157 DCHECK_CURRENTLY_ON(BrowserThread::UI);
159 scoped_ptr<base::ListValue> args(image_writer_api::OnWriteComplete::Create());
160 scoped_ptr<Event> event(new Event(
161 image_writer_api::OnWriteComplete::kEventName, args.Pass()));
163 EventRouter::Get(profile_)
164 ->DispatchEventToExtension(extension_id, event.Pass());
166 DeleteOperation(extension_id);
169 void OperationManager::OnError(const ExtensionId& extension_id,
170 image_writer_api::Stage stage,
172 const std::string& error_message) {
173 DCHECK_CURRENTLY_ON(BrowserThread::UI);
174 image_writer_api::ProgressInfo info;
176 DLOG(ERROR) << "ImageWriter error: " << error_message;
179 info.percent_complete = progress;
181 scoped_ptr<base::ListValue> args(
182 image_writer_api::OnWriteError::Create(info, error_message));
183 scoped_ptr<Event> event(new Event(
184 image_writer_api::OnWriteError::kEventName, args.Pass()));
186 EventRouter::Get(profile_)
187 ->DispatchEventToExtension(extension_id, event.Pass());
189 DeleteOperation(extension_id);
192 Operation* OperationManager::GetOperation(const ExtensionId& extension_id) {
193 OperationMap::iterator existing_operation = operations_.find(extension_id);
195 if (existing_operation == operations_.end())
197 return existing_operation->second.get();
200 void OperationManager::DeleteOperation(const ExtensionId& extension_id) {
201 OperationMap::iterator existing_operation = operations_.find(extension_id);
202 if (existing_operation != operations_.end()) {
203 operations_.erase(existing_operation);
207 void OperationManager::Observe(int type,
208 const content::NotificationSource& source,
209 const content::NotificationDetails& details) {
211 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
212 DeleteOperation(content::Details<const Extension>(details).ptr()->id());
215 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
216 DeleteOperation(content::Details<const Extension>(details).ptr()->id());
219 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: {
220 DeleteOperation(content::Details<const Extension>(details).ptr()->id());
223 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: {
225 content::Details<ExtensionHost>(details)->extension()->id());
228 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
230 content::Details<ExtensionHost>(details)->extension()->id());
240 OperationManager* OperationManager::Get(content::BrowserContext* context) {
241 return BrowserContextKeyedAPIFactory<OperationManager>::Get(context);
244 static base::LazyInstance<BrowserContextKeyedAPIFactory<OperationManager> >
245 g_factory = LAZY_INSTANCE_INITIALIZER;
247 BrowserContextKeyedAPIFactory<OperationManager>*
248 OperationManager::GetFactoryInstance() {
249 return g_factory.Pointer();
253 } // namespace image_writer
254 } // namespace extensions