1 // Copyright 2005, Google Inc.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
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
)
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 //-----------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
68 //------------------------------------------------------------------------------
69 NS_IMETHODIMP
GearsManagedResourceStore::GetName(nsAString
&name
) {
70 name
.Assign(store_
.GetName());
74 //------------------------------------------------------------------------------
76 //------------------------------------------------------------------------------
78 GearsManagedResourceStore::GetRequiredCookie(nsAString
&cookie
) {
79 cookie
.Assign(store_
.GetRequiredCookie());
83 //------------------------------------------------------------------------------
85 //------------------------------------------------------------------------------
86 NS_IMETHODIMP
GearsManagedResourceStore::GetEnabled(PRBool
*enabled
) {
87 *enabled
= store_
.IsEnabled() ? PR_TRUE
: PR_FALSE
;
91 //------------------------------------------------------------------------------
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."));
101 //------------------------------------------------------------------------------
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());
109 RETURN_EXCEPTION(STRING16(L
"Failed to get manifest url."));
114 //------------------------------------------------------------------------------
116 //------------------------------------------------------------------------------
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."));
127 nsString
url(url_abstract
); // nsAString doesn't have get()
128 std::string16 full_url
;
129 if (!ResolveAndNormalize(EnvPageLocationUrl().c_str(), url
.get(),
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."));
143 //------------------------------------------------------------------------------
144 // GetLastUpdateCheckTime
145 //------------------------------------------------------------------------------
147 GearsManagedResourceStore::GetLastUpdateCheckTime(PRInt32
*time
) {
149 RETURN_EXCEPTION(STRING16(L
"Invalid parameter."));
153 WebCacheDB::UpdateStatus status
;
154 if (store_
.GetUpdateInfo(&status
, &time64
, NULL
, NULL
)) {
155 *time
= static_cast<long>(time64
/1000); // convert to seconds
157 RETURN_EXCEPTION(STRING16(L
"Failed to get update info."));
162 //------------------------------------------------------------------------------
164 //------------------------------------------------------------------------------
165 NS_IMETHODIMP
GearsManagedResourceStore::GetUpdateStatus(PRInt32
*status
) {
167 RETURN_EXCEPTION(STRING16(L
"Invalid parameter."));
169 *status
= WebCacheDB::UPDATE_OK
;
170 WebCacheDB::UpdateStatus update_status
;
172 if (store_
.GetUpdateInfo(&update_status
, &time64
, NULL
, NULL
)) {
173 *status
= update_status
;
175 RETURN_EXCEPTION(STRING16(L
"Failed to get update info."));
180 //------------------------------------------------------------------------------
181 // GetLastErrorMessage
182 //------------------------------------------------------------------------------
183 NS_IMETHODIMP
GearsManagedResourceStore::GetLastErrorMessage(
184 nsAString
&error_message_out
) {
185 std::string16 error_message
;
186 WebCacheDB::UpdateStatus update_status
;
188 if (store_
.GetUpdateInfo(&update_status
,
192 error_message_out
.Assign(error_message
.c_str());
194 RETURN_EXCEPTION(STRING16(L
"Failed to get last error message."));
199 //------------------------------------------------------------------------------
201 //------------------------------------------------------------------------------
202 NS_IMETHODIMP
GearsManagedResourceStore::SetOnerror(nsIVariant
*in_value
) {
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
);
218 observer_topic_
= UpdateTask::GetNotificationTopic(&store_
);
219 MessageService::GetInstance()->AddObserver(this, observer_topic_
.c_str());
224 //------------------------------------------------------------------------------
226 //------------------------------------------------------------------------------
227 NS_IMETHODIMP
GearsManagedResourceStore::GetOnerror(nsIVariant
**out_value
) {
229 RETURN_EXCEPTION(STRING16(L
"This property is write only."));
232 //------------------------------------------------------------------------------
234 //------------------------------------------------------------------------------
235 NS_IMETHODIMP
GearsManagedResourceStore::SetOnprogress(nsIVariant
*in_value
) {
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
);
251 observer_topic_
= UpdateTask::GetNotificationTopic(&store_
);
252 MessageService::GetInstance()->AddObserver(this, observer_topic_
.c_str());
257 //------------------------------------------------------------------------------
259 //------------------------------------------------------------------------------
260 NS_IMETHODIMP
GearsManagedResourceStore::GetOnprogress(nsIVariant
**out_value
) {
262 RETURN_EXCEPTION(STRING16(L
"This property is write only."));
265 //------------------------------------------------------------------------------
267 //------------------------------------------------------------------------------
268 NS_IMETHODIMP
GearsManagedResourceStore::SetOncomplete(nsIVariant
*in_value
) {
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
);
284 observer_topic_
= UpdateTask::GetNotificationTopic(&store_
);
285 MessageService::GetInstance()->AddObserver(this, observer_topic_
.c_str());
290 //------------------------------------------------------------------------------
292 //------------------------------------------------------------------------------
293 NS_IMETHODIMP
GearsManagedResourceStore::GetOncomplete(nsIVariant
**out_value
) {
295 RETURN_EXCEPTION(STRING16(L
"This property is write only."));
298 //------------------------------------------------------------------------------
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
,
307 // Add the callbacks to handle deserializing messages.
308 UpdateTask::RegisterEventClasses();
312 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
328 //------------------------------------------------------------------------------
329 void GearsManagedResourceStore::OnNotify(MessageService
*service
,
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());
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());
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());
386 JsParamToSend argv
[argc
] = {
387 { JSPARAM_OBJECT
, param
.get() }
389 GetJsRunner()->InvokeCallback(handler
, argc
, argv
, NULL
);
392 //------------------------------------------------------------------------------
394 //------------------------------------------------------------------------------
395 NS_IMETHODIMP
GearsManagedResourceStore::CheckForUpdate() {
396 if (update_task_
.get()) {
397 // We're already running an update task, just return
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
415 update_task_
->AwaitStartup();
420 //------------------------------------------------------------------------------
422 //------------------------------------------------------------------------------
423 NS_IMETHODIMP
GearsManagedResourceStore::GetCurrentVersion(nsAString
&ver
) {
424 GetAppVersionString(WebCacheDB::VERSION_CURRENT
, ver
);
428 //------------------------------------------------------------------------------
429 // GetAppVersionString
430 //------------------------------------------------------------------------------
431 void GearsManagedResourceStore::GetAppVersionString(
432 WebCacheDB::VersionReadyState state
,
433 nsAString
&ver_out
) {
435 if (store_
.GetVersionString(state
, &ver
)) {
436 ver_out
.Assign(ver
.c_str());
438 ver_out
.SetLength(0);
442 //------------------------------------------------------------------------------
444 //------------------------------------------------------------------------------
445 void GearsManagedResourceStore::HandleEvent(int code
, int param
,
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();