[Author: steveblock]
[google-gears.git] / gears / localserver / firefox / managed_resource_store_ff.cc
blob971c0369c789e3d57bbc814c18f76a083afcb87c
1 // Copyright 2005, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <gecko_internal/nsIDOMClassInfo.h>
27 #include <gecko_internal/nsIVariant.h>
29 #include "gears/localserver/firefox/managed_resource_store_ff.h"
31 #include "gears/base/common/serialization.h"
32 #include "gears/base/common/url_utils.h"
33 #include "gears/base/firefox/dom_utils.h"
36 // Boilerplate. == NS_IMPL_ISUPPORTS + ..._MAP_ENTRY_EXTERNAL_DOM_CLASSINFO
37 NS_IMPL_THREADSAFE_ADDREF(GearsManagedResourceStore)
38 NS_IMPL_THREADSAFE_RELEASE(GearsManagedResourceStore)
39 NS_INTERFACE_MAP_BEGIN(GearsManagedResourceStore)
40 NS_INTERFACE_MAP_ENTRY(GearsBaseClassInterface)
41 NS_INTERFACE_MAP_ENTRY(GearsManagedResourceStoreInterface)
42 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, GearsManagedResourceStoreInterface)
43 NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(GearsManagedResourceStore)
44 NS_INTERFACE_MAP_END
46 // Object identifiers
47 const char *kGearsManagedResourceStoreClassName = "GearsManagedResourceStore";
48 const nsCID kGearsManagedResourceStoreClassId = {0x924e3de8, 0xa842, 0x4982, {0xb7, 0x5b,
49 0x96, 0xfa, 0x77, 0x9f, 0xa9, 0x37}};
50 // {924E3DE8-A842-4982-B75B-96FA779FA937}
52 //-----------------------------------------------------------------------------
53 // Destructor
54 //-----------------------------------------------------------------------------
55 GearsManagedResourceStore::~GearsManagedResourceStore() {
56 if (update_task_.get()) {
57 update_task_->SetListener(NULL);
58 update_task_->Abort();
59 update_task_.release()->DeleteWhenDone();
62 MessageService::GetInstance()->RemoveObserver(this,
63 observer_topic_.c_str());
66 //------------------------------------------------------------------------------
67 // GetName
68 //------------------------------------------------------------------------------
69 NS_IMETHODIMP GearsManagedResourceStore::GetName(nsAString &name) {
70 name.Assign(store_.GetName());
71 RETURN_NORMAL();
74 //------------------------------------------------------------------------------
75 // GetRequiredCookie
76 //------------------------------------------------------------------------------
77 NS_IMETHODIMP
78 GearsManagedResourceStore::GetRequiredCookie(nsAString &cookie) {
79 cookie.Assign(store_.GetRequiredCookie());
80 RETURN_NORMAL();
83 //------------------------------------------------------------------------------
84 // GetEnabled
85 //------------------------------------------------------------------------------
86 NS_IMETHODIMP GearsManagedResourceStore::GetEnabled(PRBool *enabled) {
87 *enabled = store_.IsEnabled() ? PR_TRUE : PR_FALSE;
88 RETURN_NORMAL();
91 //------------------------------------------------------------------------------
92 // SetEnabled
93 //------------------------------------------------------------------------------
94 NS_IMETHODIMP GearsManagedResourceStore::SetEnabled(PRBool enabled) {
95 if (!store_.SetEnabled(enabled ? true : false)) {
96 RETURN_EXCEPTION(STRING16(L"Failed to set the enabled property."));
98 RETURN_NORMAL();
101 //------------------------------------------------------------------------------
102 // GetManifestUrl
103 //------------------------------------------------------------------------------
104 NS_IMETHODIMP GearsManagedResourceStore::GetManifestUrl(nsAString &url_out) {
105 std::string16 manifest_url;
106 if (store_.GetManifestUrl(&manifest_url)) {
107 url_out.Assign(manifest_url.c_str());
108 } else {
109 RETURN_EXCEPTION(STRING16(L"Failed to get manifest url."));
111 RETURN_NORMAL();
114 //------------------------------------------------------------------------------
115 // SetManifestUrl
116 //------------------------------------------------------------------------------
117 NS_IMETHODIMP
118 GearsManagedResourceStore::SetManifestUrl(const nsAString &url_abstract) {
119 // Resetting the manifest url to an empty string is ok.
120 if (url_abstract.Length() == 0) {
121 if (!store_.SetManifestUrl(STRING16(L""))) {
122 RETURN_EXCEPTION(STRING16(L"Failed to reset manifest url."));
124 RETURN_NORMAL();
127 nsString url(url_abstract); // nsAString doesn't have get()
128 std::string16 full_url;
129 if (!ResolveAndNormalize(EnvPageLocationUrl().c_str(), url.get(),
130 &full_url)) {
131 RETURN_EXCEPTION(STRING16(L"Failed to resolve url."));
133 if (!EnvPageSecurityOrigin().IsSameOriginAsUrl(full_url.c_str())) {
134 RETURN_EXCEPTION(STRING16(L"Url is not from the same origin"));
137 if (!store_.SetManifestUrl(full_url.c_str())) {
138 RETURN_EXCEPTION(STRING16(L"Failed to set manifest url."));
140 RETURN_NORMAL();
143 //------------------------------------------------------------------------------
144 // GetLastUpdateCheckTime
145 //------------------------------------------------------------------------------
146 NS_IMETHODIMP
147 GearsManagedResourceStore::GetLastUpdateCheckTime(PRInt32 *time) {
148 if (!time) {
149 RETURN_EXCEPTION(STRING16(L"Invalid parameter."));
151 *time = 0;
152 int64 time64 = 0;
153 WebCacheDB::UpdateStatus status;
154 if (store_.GetUpdateInfo(&status, &time64, NULL, NULL)) {
155 *time = static_cast<long>(time64/1000); // convert to seconds
156 } else {
157 RETURN_EXCEPTION(STRING16(L"Failed to get update info."));
159 RETURN_NORMAL();
162 //------------------------------------------------------------------------------
163 // GetUpdateStatus
164 //------------------------------------------------------------------------------
165 NS_IMETHODIMP GearsManagedResourceStore::GetUpdateStatus(PRInt32 *status) {
166 if (!status) {
167 RETURN_EXCEPTION(STRING16(L"Invalid parameter."));
169 *status = WebCacheDB::UPDATE_OK;
170 WebCacheDB::UpdateStatus update_status;
171 int64 time64 = 0;
172 if (store_.GetUpdateInfo(&update_status, &time64, NULL, NULL)) {
173 *status = update_status;
174 } else {
175 RETURN_EXCEPTION(STRING16(L"Failed to get update info."));
177 RETURN_NORMAL();
180 //------------------------------------------------------------------------------
181 // GetLastErrorMessage
182 //------------------------------------------------------------------------------
183 NS_IMETHODIMP GearsManagedResourceStore::GetLastErrorMessage(
184 nsAString &error_message_out) {
185 std::string16 error_message;
186 WebCacheDB::UpdateStatus update_status;
187 int64 time64 = 0;
188 if (store_.GetUpdateInfo(&update_status,
189 &time64,
190 NULL,
191 &error_message)) {
192 error_message_out.Assign(error_message.c_str());
193 } else {
194 RETURN_EXCEPTION(STRING16(L"Failed to get last error message."));
196 RETURN_NORMAL();
199 //------------------------------------------------------------------------------
200 // SetOnerror
201 //------------------------------------------------------------------------------
202 NS_IMETHODIMP GearsManagedResourceStore::SetOnerror(nsIVariant *in_value) {
203 InitUnloadMonitor();
205 JsParamFetcher js_params(this);
207 if (js_params.GetCount(false) < 1) {
208 RETURN_EXCEPTION(STRING16(L"Value is required."));
211 JsRootedCallback *callback = 0;
212 if (!js_params.GetAsNewRootedCallback(0, &callback)) {
213 RETURN_EXCEPTION(STRING16(L"Invalid value for onerror property."));
215 onerror_handler_.reset(callback);
217 if (callback) {
218 observer_topic_ = UpdateTask::GetNotificationTopic(&store_);
219 MessageService::GetInstance()->AddObserver(this, observer_topic_.c_str());
221 RETURN_NORMAL();
224 //------------------------------------------------------------------------------
225 // GetOnerror
226 //------------------------------------------------------------------------------
227 NS_IMETHODIMP GearsManagedResourceStore::GetOnerror(nsIVariant **out_value) {
228 *out_value = NULL;
229 RETURN_EXCEPTION(STRING16(L"This property is write only."));
232 //------------------------------------------------------------------------------
233 // SetOnprogress
234 //------------------------------------------------------------------------------
235 NS_IMETHODIMP GearsManagedResourceStore::SetOnprogress(nsIVariant *in_value) {
236 InitUnloadMonitor();
238 JsParamFetcher js_params(this);
240 if (js_params.GetCount(false) < 1) {
241 RETURN_EXCEPTION(STRING16(L"Value is required."));
244 JsRootedCallback *callback = 0;
245 if (!js_params.GetAsNewRootedCallback(0, &callback)) {
246 RETURN_EXCEPTION(STRING16(L"Invalid value for onprogress property."));
248 onprogress_handler_.reset(callback);
250 if (callback) {
251 observer_topic_ = UpdateTask::GetNotificationTopic(&store_);
252 MessageService::GetInstance()->AddObserver(this, observer_topic_.c_str());
254 RETURN_NORMAL();
257 //------------------------------------------------------------------------------
258 // GetOnprogress
259 //------------------------------------------------------------------------------
260 NS_IMETHODIMP GearsManagedResourceStore::GetOnprogress(nsIVariant **out_value) {
261 *out_value = NULL;
262 RETURN_EXCEPTION(STRING16(L"This property is write only."));
265 //------------------------------------------------------------------------------
266 // SetOncomplete
267 //------------------------------------------------------------------------------
268 NS_IMETHODIMP GearsManagedResourceStore::SetOncomplete(nsIVariant *in_value) {
269 InitUnloadMonitor();
271 JsParamFetcher js_params(this);
273 if (js_params.GetCount(false) < 1) {
274 RETURN_EXCEPTION(STRING16(L"Value is required."));
277 JsRootedCallback *callback = 0;
278 if (!js_params.GetAsNewRootedCallback(0, &callback)) {
279 RETURN_EXCEPTION(STRING16(L"Invalid value for oncomplete property."));
281 oncomplete_handler_.reset(callback);
283 if (callback) {
284 observer_topic_ = UpdateTask::GetNotificationTopic(&store_);
285 MessageService::GetInstance()->AddObserver(this, observer_topic_.c_str());
287 RETURN_NORMAL();
290 //------------------------------------------------------------------------------
291 // GetOncomplete
292 //------------------------------------------------------------------------------
293 NS_IMETHODIMP GearsManagedResourceStore::GetOncomplete(nsIVariant **out_value) {
294 *out_value = NULL;
295 RETURN_EXCEPTION(STRING16(L"This property is write only."));
298 //------------------------------------------------------------------------------
299 // InitUnloadMonitor
300 //------------------------------------------------------------------------------
301 void GearsManagedResourceStore::InitUnloadMonitor() {
302 // Create an event monitor to alert us when the page unloads.
303 if (unload_monitor_ == NULL) {
304 unload_monitor_.reset(new JsEventMonitor(GetJsRunner(), JSEVENT_UNLOAD,
305 this));
307 // Add the callbacks to handle deserializing messages.
308 UpdateTask::RegisterEventClasses();
312 //------------------------------------------------------------------------------
313 // HandleEvent
314 //------------------------------------------------------------------------------
315 void GearsManagedResourceStore::HandleEvent(JsEventType event_type) {
316 assert(event_type == JSEVENT_UNLOAD);
318 // Drop references, js context is going away.
319 onerror_handler_.reset();
320 onprogress_handler_.reset();
321 oncomplete_handler_.reset();
322 MessageService::GetInstance()->RemoveObserver(this,
323 observer_topic_.c_str());
326 //------------------------------------------------------------------------------
327 // OnNotify
328 //------------------------------------------------------------------------------
329 void GearsManagedResourceStore::OnNotify(MessageService *service,
330 const char16 *topic,
331 const NotificationData *data) {
332 scoped_ptr<JsObject> param;
333 JsRootedCallback *handler = 0;
335 const UpdateTask::Event *event = static_cast<const UpdateTask::Event *>(data);
336 switch(event->event_type()) {
337 case UpdateTask::ERROR_EVENT: {
338 if (!onerror_handler_.get()) return;
339 handler = onerror_handler_.get();
341 param.reset(GetJsRunner()->NewObject(STRING16(L"Error")));
342 if (!param.get()) return;
344 const UpdateTask::ErrorEvent *error_event =
345 static_cast<const UpdateTask::ErrorEvent *>(data);
346 param->SetPropertyString(STRING16(L"message"),
347 error_event->error_message());
349 break;
351 case UpdateTask::PROGRESS_EVENT: {
352 if (!onprogress_handler_.get()) return;
353 handler = onprogress_handler_.get();
355 param.reset(GetJsRunner()->NewObject(NULL));
356 if (!param.get()) return;
358 const UpdateTask::ProgressEvent *progress_event =
359 static_cast<const UpdateTask::ProgressEvent *>(data);
360 param->SetPropertyInt(STRING16(L"filesTotal"),
361 progress_event->files_total());
362 param->SetPropertyInt(STRING16(L"filesComplete"),
363 progress_event->files_complete());
365 break;
367 case UpdateTask::COMPLETION_EVENT: {
368 if (!oncomplete_handler_.get()) return;
369 handler = oncomplete_handler_.get();
371 param.reset(GetJsRunner()->NewObject(NULL));
372 if (!param.get()) return;
374 const UpdateTask::CompletionEvent *completion_event =
375 static_cast<const UpdateTask::CompletionEvent *>(data);
376 param->SetPropertyString(STRING16(L"newVersion"),
377 completion_event->new_version_string());
379 break;
381 default:
382 return;
385 const int argc = 1;
386 JsParamToSend argv[argc] = {
387 { JSPARAM_OBJECT, param.get() }
389 GetJsRunner()->InvokeCallback(handler, argc, argv, NULL);
392 //------------------------------------------------------------------------------
393 // CheckForUpdate
394 //------------------------------------------------------------------------------
395 NS_IMETHODIMP GearsManagedResourceStore::CheckForUpdate() {
396 if (update_task_.get()) {
397 // We're already running an update task, just return
398 RETURN_NORMAL();
401 update_task_.reset(new FFUpdateTask());
402 if (!update_task_->Init(&store_)) {
403 update_task_.reset(NULL);
404 RETURN_EXCEPTION(STRING16(L"Failed to initialize update task."));
407 update_task_->SetListener(this);
408 if (!update_task_->Start()) {
409 update_task_.reset(NULL);
410 RETURN_EXCEPTION(STRING16(L"Failed to start update task."));
413 // We wait here so the updateStatus property reflects a running task
414 // upon return
415 update_task_->AwaitStartup();
417 RETURN_NORMAL();
420 //------------------------------------------------------------------------------
421 // GetCurrentVersion
422 //------------------------------------------------------------------------------
423 NS_IMETHODIMP GearsManagedResourceStore::GetCurrentVersion(nsAString &ver) {
424 GetAppVersionString(WebCacheDB::VERSION_CURRENT, ver);
425 return NS_OK;
428 //------------------------------------------------------------------------------
429 // GetAppVersionString
430 //------------------------------------------------------------------------------
431 void GearsManagedResourceStore::GetAppVersionString(
432 WebCacheDB::VersionReadyState state,
433 nsAString &ver_out) {
434 std::string16 ver;
435 if (store_.GetVersionString(state, &ver)) {
436 ver_out.Assign(ver.c_str());
437 } else {
438 ver_out.SetLength(0);
442 //------------------------------------------------------------------------------
443 // HandleEvent
444 //------------------------------------------------------------------------------
445 void GearsManagedResourceStore::HandleEvent(int code, int param,
446 AsyncTask *source) {
447 FFUpdateTask* task = reinterpret_cast<FFUpdateTask*>(source);
448 if (task && (task == update_task_.get())) {
449 if (code == FFUpdateTask::UPDATE_TASK_COMPLETE) {
450 update_task_->SetListener(NULL);
451 update_task_.release()->DeleteWhenDone();