1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
16 #include <glib/gstdio.h>
20 #include "application.h"
22 #include "deployment.h"
27 Application::Application ()
29 SetObjectType (Type::APPLICATION
);
33 apply_default_style_cb
= NULL
;
34 get_default_template_root_cb
= NULL
;
35 apply_style_cb
= NULL
;
36 convert_keyframe_callback
= NULL
;
37 get_resource_cb
= NULL
;
40 Application::~Application ()
43 Deployment::GetCurrent()->UntrackPath (resource_root
);
44 RemoveDir (resource_root
);
45 g_free (resource_root
);
50 Application::GetCurrent ()
52 return Deployment::GetCurrent()->GetCurrentApplication();
56 Application::SetCurrent (Application
*application
)
58 Deployment::GetCurrent()->SetCurrentApplication (application
);
62 Application::RegisterCallbacks (ApplyDefaultStyleCallback apply_default_style_cb
,
63 ApplyStyleCallback apply_style_cb
,
64 GetResourceCallback get_resource_cb
,
65 ConvertKeyframeValueCallback convert_keyframe_callback
,
66 GetDefaultTemplateRootCallback get_default_template_root_cb
)
68 this->apply_default_style_cb
= apply_default_style_cb
;
69 this->get_default_template_root_cb
= get_default_template_root_cb
;
70 this->apply_style_cb
= apply_style_cb
;
71 this->convert_keyframe_callback
= convert_keyframe_callback
;
72 this->get_resource_cb
= get_resource_cb
;
76 Application::ApplyDefaultStyle (FrameworkElement
*fwe
, ManagedTypeInfo
*key
)
78 if (apply_default_style_cb
)
79 apply_default_style_cb (fwe
, key
);
83 Application::GetDefaultTemplateRoot (ContentControl
*ctrl
)
85 if (get_default_template_root_cb
)
86 return get_default_template_root_cb (ctrl
);
91 Application::ApplyStyle (FrameworkElement
*fwe
, Style
*style
)
94 apply_style_cb (fwe
, style
);
98 Application::ConvertKeyframeValue (Type::Kind kind
, DependencyProperty
*property
, Value
*original
, Value
*converted
)
100 if (convert_keyframe_callback
) {
101 convert_keyframe_callback (kind
, property
, original
, converted
);
103 converted
= new Value (*original
);
109 NotifyFunc notify_cb
;
113 static void downloader_abort (gpointer data
, void *ctx
);
114 static void downloader_progress_changed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
);
115 static void downloader_complete (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
);
116 static void downloader_failed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
);
117 static void downloader_write (void *data
, gint32 offset
, gint32 n
, void *closure
);
118 static void downloader_notify_size (gint64 size
, gpointer closure
);
121 Application::GetResource (const char *resourceBase
, const Uri
*uri
,
122 NotifyFunc notify_cb
, WriteFunc write_cb
,
123 DownloaderAccessPolicy policy
,
124 Cancellable
*cancellable
, gpointer user_data
)
127 g_warning ("Passing a null uri to Application::GetResource");
131 if (get_resource_cb
&& uri
&& !uri
->isAbsolute
) {
132 char *url
= uri
->ToString ();
133 ManagedStreamCallbacks stream
= get_resource_cb (resourceBase
, url
);
138 notify_cb (NotifyStarted
, NULL
, user_data
);
139 notify_cb (NotifySize
, stream
.Length (stream
.handle
), user_data
);
147 if (stream
.CanSeek (stream
.handle
))
148 stream
.Seek (stream
.handle
, 0, 0);
151 if ((nread
= stream
.Read (stream
.handle
, buf
, 0, sizeof (buf
))) <= 0)
154 write_cb (buf
, offset
, nread
, user_data
);
160 notify_cb (NotifyCompleted
, NULL
, user_data
);
162 stream
.Close (stream
.handle
);
168 //no get_resource_cb or empty stream
169 Downloader
*downloader
;
170 Surface
*surface
= Deployment::GetCurrent ()->GetSurface ();
171 if (!(downloader
= surface
->CreateDownloader ()))
174 NotifyCtx
*ctx
= g_new (NotifyCtx
, 1);
175 ctx
->user_data
= user_data
;
176 ctx
->notify_cb
= notify_cb
;
177 ctx
->write_cb
= write_cb
;
180 downloader
->AddHandler (Downloader::DownloadProgressChangedEvent
, downloader_progress_changed
, ctx
);
181 downloader
->AddHandler (Downloader::DownloadFailedEvent
, downloader_failed
, ctx
);
182 downloader
->AddHandler (Downloader::CompletedEvent
, downloader_complete
, ctx
);
186 cancellable
->SetCancelFuncAndData (downloader_abort
, downloader
, ctx
);
189 if (downloader
->Completed ()) {
191 notify_cb (NotifyCompleted
, NULL
, user_data
);
193 if (!downloader
->Started ()) {
194 downloader
->Open ("GET", (Uri
*)uri
, policy
);
195 downloader
->SetStreamFunctions (downloader_write
, downloader_notify_size
, ctx
);
202 downloader_notify_size (gint64 size
, gpointer closure
)
204 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
205 ctx
->notify_cb (NotifySize
, size
, ctx
->user_data
);
209 downloader_write (void *data
, gint32 offset
, gint32 n
, void *closure
)
211 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
212 ctx
->write_cb (data
, offset
, n
, ctx
->user_data
);
216 downloader_abort (gpointer data
, void *ctx
)
218 Downloader
*dl
= (Downloader
*) data
;
219 NotifyCtx
*nc
= (NotifyCtx
*)ctx
;
220 dl
->RemoveHandler (Downloader::DownloadProgressChangedEvent
, downloader_progress_changed
, nc
);
221 dl
->RemoveHandler (Downloader::DownloadFailedEvent
, downloader_failed
, nc
);
222 dl
->RemoveHandler (Downloader::CompletedEvent
, downloader_complete
, nc
);
227 downloader_progress_changed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
)
229 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
230 Downloader
*dl
= (Downloader
*) sender
;
231 ctx
->notify_cb (NotifyProgressChanged
, (gint64
) (100 * dl
->GetDownloadProgress ()), ctx
->user_data
);
235 downloader_complete (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
)
237 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
238 ctx
->notify_cb (NotifyCompleted
, NULL
, ctx
->user_data
);
240 ((Downloader
*) sender
)->unref_delayed ();
244 downloader_failed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
)
246 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
247 ctx
->notify_cb (NotifyFailed
, NULL
, ctx
->user_data
);
249 ((Downloader
*) sender
)->unref_delayed ();
254 Application::GetResourceAsPath (const char *resourceBase
, const Uri
*uri
)
256 char *dirname
, *path
, *filename
, *url
;
257 ManagedStreamCallbacks stream
;
264 if (!get_resource_cb
|| !uri
|| uri
->isAbsolute
)
267 // construct the path name for this resource
268 filename
= uri
->ToString ();
269 CanonicalizeFilename (filename
, -1, CanonModeResource
);
270 if (uri
->GetQuery () != NULL
) {
271 char *sc
= strchr (filename
, ';');
276 path
= g_build_filename (GetResourceRoot(), filename
, NULL
);
279 if (g_stat (path
, &st
) != -1) {
280 // path exists, we're done
284 // create the directory for our resource (keeping the relative path intact)
285 dirname
= g_path_get_dirname (path
);
286 if (g_mkdir_with_parents (dirname
, 0700) == -1 && errno
!= EEXIST
) {
294 url
= uri
->ToString ();
295 stream
= get_resource_cb (resourceBase
, url
);
298 if (!stream
.handle
) {
303 // reset the stream to 0
304 if (stream
.CanSeek (stream
.handle
))
305 stream
.Seek (stream
.handle
, 0, SEEK_SET
);
307 // create and save the buffer to disk
308 if ((fd
= g_open (path
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600)) == -1) {
309 stream
.Close (stream
.handle
);
314 // write the stream to disk
316 if ((nread
= stream
.Read (stream
.handle
, buf
, 0, sizeof (buf
))) <= 0)
319 if (write_all (fd
, buf
, (size_t) nread
) == -1) {
320 stream
.Close (stream
.handle
);
329 stream
.Close (stream
.handle
);
332 // check to see if the resource is zipped
333 if (!(zipfile
= unzOpen (path
))) {
334 // nope, not zipped...
338 // create a directory to contain our unzipped content
339 if (!(dirname
= CreateTempDir (path
))) {
347 // unzip the contents
348 if (!ExtractAll (zipfile
, dirname
, CanonModeResource
)) {
360 if (g_rename (dirname
, path
) == -1) {
373 Application::GetResourceRoot ()
375 if (!resource_root
) {
376 char *buf
= g_build_filename (g_get_tmp_dir (), "moonlight-app.XXXXXX", NULL
);
377 // create a root temp directory for all files
378 if (!(resource_root
= MakeTempDir (buf
)))
380 Deployment::GetCurrent()->TrackPath (resource_root
);
382 return resource_root
;