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_host.h"
16 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/extensions/extension_system.h"
18 #include "chrome/browser/extensions/extension_system_factory.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/notification_service.h"
21 #include "extensions/browser/event_router.h"
23 namespace image_writer_api = extensions::api::image_writer_private;
25 namespace extensions {
26 namespace image_writer {
28 using content::BrowserThread;
30 OperationManager::OperationManager(Profile* profile)
33 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
34 content::Source<Profile>(profile_));
35 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
36 content::Source<Profile>(profile_));
37 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
38 content::Source<Profile>(profile_));
39 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
40 content::Source<Profile>(profile_));
41 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
42 content::Source<Profile>(profile_));
45 OperationManager::~OperationManager() {
48 void OperationManager::Shutdown() {
49 for (OperationMap::iterator iter = operations_.begin();
50 iter != operations_.end();
52 BrowserThread::PostTask(BrowserThread::FILE,
54 base::Bind(&Operation::Abort,
59 void OperationManager::StartWriteFromUrl(
60 const ExtensionId& extension_id,
62 content::RenderViewHost* rvh,
63 const std::string& hash,
64 bool saveImageAsDownload,
65 const std::string& storage_unit_id,
66 const Operation::StartWriteCallback& callback) {
67 OperationMap::iterator existing_operation = operations_.find(extension_id);
69 if (existing_operation != operations_.end()) {
70 return callback.Run(false, error::kOperationAlreadyInProgress);
73 scoped_refptr<Operation> operation(
74 new WriteFromUrlOperation(weak_factory_.GetWeakPtr(),
81 operations_[extension_id] = operation;
82 BrowserThread::PostTask(BrowserThread::FILE,
84 base::Bind(&Operation::Start, operation));
85 callback.Run(true, "");
88 void OperationManager::StartWriteFromFile(
89 const ExtensionId& extension_id,
90 const base::FilePath& path,
91 const std::string& storage_unit_id,
92 const Operation::StartWriteCallback& callback) {
93 OperationMap::iterator existing_operation = operations_.find(extension_id);
95 if (existing_operation != operations_.end()) {
96 return callback.Run(false, error::kOperationAlreadyInProgress);
99 scoped_refptr<Operation> operation(
100 new WriteFromFileOperation(weak_factory_.GetWeakPtr(),
104 operations_[extension_id] = operation;
105 BrowserThread::PostTask(BrowserThread::FILE,
107 base::Bind(&Operation::Start, operation));
108 callback.Run(true, "");
111 void OperationManager::CancelWrite(
112 const ExtensionId& extension_id,
113 const Operation::CancelWriteCallback& callback) {
114 Operation* existing_operation = GetOperation(extension_id);
116 if (existing_operation == NULL) {
117 callback.Run(false, error::kNoOperationInProgress);
119 BrowserThread::PostTask(BrowserThread::FILE,
121 base::Bind(&Operation::Cancel, existing_operation));
122 DeleteOperation(extension_id);
123 callback.Run(true, "");
127 void OperationManager::DestroyPartitions(
128 const ExtensionId& extension_id,
129 const std::string& storage_unit_id,
130 const Operation::StartWriteCallback& callback) {
131 OperationMap::iterator existing_operation = operations_.find(extension_id);
133 if (existing_operation != operations_.end()) {
134 return callback.Run(false, error::kOperationAlreadyInProgress);
137 scoped_refptr<Operation> operation(
138 new DestroyPartitionsOperation(weak_factory_.GetWeakPtr(),
141 operations_[extension_id] = operation;
142 BrowserThread::PostTask(BrowserThread::FILE,
144 base::Bind(&Operation::Start, operation));
145 callback.Run(true, "");
148 void OperationManager::OnProgress(const ExtensionId& extension_id,
149 image_writer_api::Stage stage,
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
152 DVLOG(2) << "progress - " << stage << " at " << progress << "%";
154 image_writer_api::ProgressInfo info;
156 info.percent_complete = progress;
158 scoped_ptr<base::ListValue> args(
159 image_writer_api::OnWriteProgress::Create(info));
160 scoped_ptr<Event> event(new Event(
161 image_writer_api::OnWriteProgress::kEventName, args.Pass()));
163 ExtensionSystem::Get(profile_)->event_router()->
164 DispatchEventToExtension(extension_id, event.Pass());
167 void OperationManager::OnComplete(const ExtensionId& extension_id) {
168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
170 scoped_ptr<base::ListValue> args(image_writer_api::OnWriteComplete::Create());
171 scoped_ptr<Event> event(new Event(
172 image_writer_api::OnWriteComplete::kEventName, args.Pass()));
174 ExtensionSystem::Get(profile_)->event_router()->
175 DispatchEventToExtension(extension_id, event.Pass());
177 DeleteOperation(extension_id);
180 void OperationManager::OnError(const ExtensionId& extension_id,
181 image_writer_api::Stage stage,
183 const std::string& error_message) {
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
185 image_writer_api::ProgressInfo info;
187 DLOG(ERROR) << "ImageWriter error: " << error_message;
190 info.percent_complete = progress;
192 scoped_ptr<base::ListValue> args(
193 image_writer_api::OnWriteError::Create(info, error_message));
194 scoped_ptr<Event> event(new Event(
195 image_writer_api::OnWriteError::kEventName, args.Pass()));
197 ExtensionSystem::Get(profile_)->event_router()->
198 DispatchEventToExtension(extension_id, event.Pass());
200 DeleteOperation(extension_id);
203 Operation* OperationManager::GetOperation(const ExtensionId& extension_id) {
204 OperationMap::iterator existing_operation = operations_.find(extension_id);
206 if (existing_operation == operations_.end())
208 return existing_operation->second.get();
211 void OperationManager::DeleteOperation(const ExtensionId& extension_id) {
212 OperationMap::iterator existing_operation = operations_.find(extension_id);
213 if (existing_operation != operations_.end()) {
214 operations_.erase(existing_operation);
218 void OperationManager::Observe(int type,
219 const content::NotificationSource& source,
220 const content::NotificationDetails& details) {
222 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
223 DeleteOperation(content::Details<const Extension>(details).ptr()->id());
226 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
227 DeleteOperation(content::Details<const Extension>(details).ptr()->id());
230 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: {
231 DeleteOperation(content::Details<const Extension>(details).ptr()->id());
234 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: {
236 content::Details<ExtensionHost>(details)->extension()->id());
239 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
241 content::Details<ExtensionHost>(details)->extension()->id());
251 OperationManager* OperationManager::Get(Profile* profile) {
252 return ProfileKeyedAPIFactory<OperationManager>::
253 GetForProfile(profile);
256 static base::LazyInstance<ProfileKeyedAPIFactory<OperationManager> >
257 g_factory = LAZY_INSTANCE_INITIALIZER;
259 ProfileKeyedAPIFactory<OperationManager>*
260 OperationManager::GetFactoryInstance() {
261 return g_factory.Pointer();
265 } // namespace image_writer
266 } // namespace extensions