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.
17 #include <glib/gstdio.h>
19 #include <sys/types.h>
25 #include "application.h"
27 #include "deployment.h"
32 Application::Application ()
34 SetObjectType (Type::APPLICATION
);
38 apply_default_style_cb
= NULL
;
39 get_default_template_root_cb
= NULL
;
40 apply_style_cb
= NULL
;
41 convert_keyframe_callback
= NULL
;
42 get_resource_cb
= NULL
;
45 Application::~Application ()
48 RemoveDir (resource_root
);
49 g_free (resource_root
);
54 Application::GetCurrent ()
56 return Deployment::GetCurrent()->GetCurrentApplication();
60 Application::SetCurrent (Application
*application
)
62 Deployment::GetCurrent()->SetCurrentApplication (application
);
66 Application::RegisterCallbacks (ApplyDefaultStyleCallback apply_default_style_cb
,
67 ApplyStyleCallback apply_style_cb
,
68 GetResourceCallback get_resource_cb
,
69 ConvertKeyframeValueCallback convert_keyframe_callback
,
70 GetDefaultTemplateRootCallback get_default_template_root_cb
)
72 this->apply_default_style_cb
= apply_default_style_cb
;
73 this->get_default_template_root_cb
= get_default_template_root_cb
;
74 this->apply_style_cb
= apply_style_cb
;
75 this->convert_keyframe_callback
= convert_keyframe_callback
;
76 this->get_resource_cb
= get_resource_cb
;
80 Application::ApplyDefaultStyle (FrameworkElement
*fwe
, ManagedTypeInfo
*key
)
82 if (apply_default_style_cb
)
83 apply_default_style_cb (fwe
, key
);
87 Application::GetDefaultTemplateRoot (ContentControl
*ctrl
)
89 if (get_default_template_root_cb
)
90 return get_default_template_root_cb (ctrl
);
95 Application::ApplyStyle (FrameworkElement
*fwe
, Style
*style
)
98 apply_style_cb (fwe
, style
);
102 Application::ConvertKeyframeValue (Type::Kind kind
, DependencyProperty
*property
, Value
*original
, Value
*converted
)
104 if (convert_keyframe_callback
) {
105 convert_keyframe_callback (kind
, property
, original
, converted
);
107 converted
= new Value (*original
);
113 NotifyFunc notify_cb
;
117 static void downloader_abort (gpointer data
, void *ctx
);
118 static void downloader_progress_changed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
);
119 static void downloader_complete (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
);
120 static void downloader_failed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
);
121 static void downloader_write (void *data
, gint32 offset
, gint32 n
, void *closure
);
122 static void downloader_notify_size (gint64 size
, gpointer closure
);
125 Application::GetResource (const char *resourceBase
, const Uri
*uri
,
126 NotifyFunc notify_cb
, WriteFunc write_cb
,
127 DownloaderAccessPolicy policy
,
128 Cancellable
*cancellable
, gpointer user_data
)
131 g_warning ("Passing a null uri to Application::GetResource");
135 if (get_resource_cb
&& uri
&& !uri
->isAbsolute
) {
136 char *url
= uri
->ToString ();
137 ManagedStreamCallbacks stream
= get_resource_cb (resourceBase
, url
);
142 notify_cb (NotifyStarted
, NULL
, user_data
);
143 notify_cb (NotifySize
, stream
.Length (stream
.handle
), user_data
);
151 if (stream
.CanSeek (stream
.handle
))
152 stream
.Seek (stream
.handle
, 0, 0);
155 if ((nread
= stream
.Read (stream
.handle
, buf
, 0, sizeof (buf
))) <= 0)
158 write_cb (buf
, offset
, nread
, user_data
);
164 notify_cb (NotifyCompleted
, NULL
, user_data
);
166 stream
.Close (stream
.handle
);
172 //no get_resource_cb or empty stream
173 Downloader
*downloader
;
174 Surface
*surface
= Deployment::GetCurrent ()->GetSurface ();
175 if (!(downloader
= surface
->CreateDownloader ()))
178 NotifyCtx
*ctx
= g_new (NotifyCtx
, 1);
179 ctx
->user_data
= user_data
;
180 ctx
->notify_cb
= notify_cb
;
181 ctx
->write_cb
= write_cb
;
184 downloader
->AddHandler (Downloader::DownloadProgressChangedEvent
, downloader_progress_changed
, ctx
);
185 downloader
->AddHandler (Downloader::DownloadFailedEvent
, downloader_failed
, ctx
);
186 downloader
->AddHandler (Downloader::CompletedEvent
, downloader_complete
, ctx
);
190 cancellable
->SetCancelFuncAndData (downloader_abort
, downloader
, ctx
);
193 if (downloader
->Completed ()) {
195 notify_cb (NotifyCompleted
, NULL
, user_data
);
197 if (!downloader
->Started ()) {
198 downloader
->Open ("GET", (Uri
*)uri
, policy
);
199 downloader
->SetStreamFunctions (downloader_write
, downloader_notify_size
, ctx
);
206 downloader_notify_size (gint64 size
, gpointer closure
)
208 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
209 ctx
->notify_cb (NotifySize
, size
, ctx
->user_data
);
213 downloader_write (void *data
, gint32 offset
, gint32 n
, void *closure
)
215 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
216 ctx
->write_cb (data
, offset
, n
, ctx
->user_data
);
220 downloader_abort (gpointer data
, void *ctx
)
222 Downloader
*dl
= (Downloader
*) data
;
223 NotifyCtx
*nc
= (NotifyCtx
*)ctx
;
224 dl
->RemoveHandler (Downloader::DownloadProgressChangedEvent
, downloader_progress_changed
, nc
);
225 dl
->RemoveHandler (Downloader::DownloadFailedEvent
, downloader_failed
, nc
);
226 dl
->RemoveHandler (Downloader::CompletedEvent
, downloader_complete
, nc
);
231 downloader_progress_changed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
)
233 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
234 Downloader
*dl
= (Downloader
*) sender
;
235 ctx
->notify_cb (NotifyProgressChanged
, (gint64
) (100 * dl
->GetDownloadProgress ()), ctx
->user_data
);
239 downloader_complete (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
)
241 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
242 ctx
->notify_cb (NotifyCompleted
, NULL
, ctx
->user_data
);
244 ((Downloader
*) sender
)->unref_delayed ();
248 downloader_failed (EventObject
*sender
, EventArgs
*calldata
, gpointer closure
)
250 NotifyCtx
*ctx
= (NotifyCtx
*) closure
;
251 ctx
->notify_cb (NotifyFailed
, NULL
, ctx
->user_data
);
253 ((Downloader
*) sender
)->unref_delayed ();
258 Application::GetResourceAsPath (const char *resourceBase
, const Uri
*uri
)
260 char *dirname
, *path
, *filename
, *url
;
261 ManagedStreamCallbacks stream
;
268 if (!get_resource_cb
|| !uri
|| uri
->isAbsolute
)
271 if (!resource_root
) {
272 // create a root temp directory for our resource files
273 if (!(resource_root
= CreateTempDir ("moonlight-app")))
277 // construct the path name for this resource
278 filename
= uri
->ToString ();
279 CanonicalizeFilename (filename
, -1, true);
280 if (uri
->GetQuery () != NULL
) {
281 char *sc
= strchr (filename
, ';');
286 path
= g_build_filename (resource_root
, filename
, NULL
);
289 if (stat (path
, &st
) != -1) {
290 // path exists, we're done
294 // create the directory for our resource (keeping the relative path intact)
295 dirname
= g_path_get_dirname (path
);
296 if (g_mkdir_with_parents (dirname
, 0700) == -1 && errno
!= EEXIST
) {
304 url
= uri
->ToString ();
305 stream
= get_resource_cb (resourceBase
, url
);
308 if (!stream
.handle
) {
313 // reset the stream to 0
314 if (stream
.CanSeek (stream
.handle
))
315 stream
.Seek (stream
.handle
, 0, SEEK_SET
);
317 // create and save the buffer to disk
318 if ((fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600)) == -1) {
319 stream
.Close (stream
.handle
);
324 // write the stream to disk
326 if ((nread
= stream
.Read (stream
.handle
, buf
, 0, sizeof (buf
))) <= 0)
329 if (write_all (fd
, buf
, (size_t) nread
) == -1) {
330 stream
.Close (stream
.handle
);
339 stream
.Close (stream
.handle
);
342 // check to see if the resource is zipped
343 if (!(zipfile
= unzOpen (path
))) {
344 // nope, not zipped...
348 // create a directory to contain our unzipped content
349 dirname
= g_strdup_printf ("%s.XXXXXX", path
);
350 if (!MakeTempDir (dirname
)) {
358 // unzip the contents
359 if (!ExtractAll (zipfile
, dirname
, true)) {
371 if (rename (dirname
, path
) == -1) {