[gnome-boxes] Download logos on demand



commit 872e9bffd949406a65c6827f5e07c5088a1ebca5
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Thu Aug 23 23:30:34 2012 +0300

    Download logos on demand
    
    This patch is very similar to the one I originally proposed in
    bug#670003. The understanding I got from Fedora legal was that
    distribution of the logos is not an issue but rather the use so I started
    to ship logos in Boxes itself. While it was really not an issue for
    Fedora legal, it became an issue for other distros and upstream
    (bug#671251).
    
    I then put this under a new package called gnome-boxes-nonfree but soon
    realized that most distros would not like to ship it in their main
    repositories as it clearly says 'nonfree' in the name. So I would like
    to retire that package and download these logos on demand and keep them
    cached.
    
    Major differences against the original patch in bug#670003:
    
    1. Now we ourselves maintain a very tiny libosinfo database adds logo
    logo URLs to some OSs. The reason for that is that Fedora legal asked us
    to ensure that these logos are not used outside of Boxes' context.
    
    2. I've put all the downloading and caching code in a separate new
    singleton class: Downloader. Later I intend to use this to also download
    ISOs.
    
    3. Ensure same file is not downloaded more than once.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=682573

 README.logos                  |  203 +++++++++++++++++++++++++++++++++++++++++
 configure.ac                  |    2 +-
 data/Makefile.am              |    4 +
 data/gnome-boxes-logos-db.xml |   21 ++++
 src/Makefile.am               |    1 +
 src/downloader.vala           |  116 +++++++++++++++++++++++
 src/os-database.vala          |    1 +
 src/util-app.vala             |   24 -----
 src/util.vala                 |   12 +++
 src/wizard-source.vala        |    6 +-
 src/wizard.vala               |   16 +++-
 11 files changed, 377 insertions(+), 29 deletions(-)
---
diff --git a/README.logos b/README.logos
new file mode 100644
index 0000000..57c54ea
--- /dev/null
+++ b/README.logos
@@ -0,0 +1,203 @@
+Boxes has acquired explicit permission from trademark owners for the usage and
+shipment (though we don't ship them but rather download them on demand) of their
+logos[1][3]. Please note that this permission does not extend to any derivate
+work but only applies to Boxes for the very specific purpose of identifying the
+products in question.
+
+Following are the owners for each logo:
+
+Fedora: Red Hat, Inc.
+Ubuntu: Canonical Ltd.
+openSUSE: Novell, Inc. [2]
+Debian: SPI (Software in the Public Interest).
+
+The Fedora board/legal required we keep a special note in this file:
+
+   FedoraÂ, the Fedora word design, and the Infinity design logo, either
+   separately or in combination, are hereinafter referred to as "Fedora
+   Trademarks" and are trademarks of Red Hat, Inc., registered in the
+   United States and other countries. The Boxes software contains images
+   that are or include the Fedora Trademarks. You are granted a a
+   license to copy and redistribute unmodified image files containing
+   the Fedora Trademarks only for the purpose of indicating Fedora VM
+   instances in the Graphical Interface for the Boxes software, as
+   described to the Fedora Board on 2012-02-21. No other permission is
+   granted.
+
+   All such rights are granted to you provided that the above trademark
+   legend and this license are included with each copy you make, and
+   they remain intact and are not altered, deleted, or modified in any
+   way.
+-----------------------------------------------------------------------
+
+[1] with the exception of Debian logo due to its very liberal licensing:
+
+http://www.debian.org/logos/
+
+[2] For use in other projects, please read:
+
+http://en.opensuse.org/openSUSE:Trademark_guidelines
+
+[3] Following are the e-mails I recieved from vendors granting us explicit
+    permissions to use their logos in Boxes:
+
+Fedora
+======
+
+http://lists.fedoraproject.org/pipermail/advisory-board/2012-February/011367.html
+
+openSUSE
+========
+
+From: awafaa opensuse org Andrew Wafaa
+Date: Wed, 22 Feb 2012 12:16:08 +0200
+Subject: Re: Permission to use openSUSE Logo for gnome-boxes
+
+Hi Manu,
+
+On 21 February 2012 17:48, Manu Gupta <manugupt1 gmail com> wrote:
+> Hi,
+>  As you may or may not know, we have been working on a new GNOME
+> application, Boxes[1] that (among other things) enables users to easily
+> manage virtual-machines. This also includes ability to detect
+> operating-systems given an installation media and presenting an
+> intuitive and *impressive* UI to user to easily install different
+> operating systems with minimum or no interaction. Boxes makes use of a
+> new library, libosinfo[2] that provides information about operating
+> systems (which it internally keeps in an XML database).
+>
+> We really want (more like need) to show logos of different operating
+> systems to the user[3]. Can we please get the permission to use openSUSE logo in
+> this manner and distribute it along with Boxes or libosinfo?
+>
+> [1] http://live.gnome.org/Boxes
+> [2] https://fedorahosted.org/libosinfo/
+> [3] http://static.fi/~zeenix/tmp/boxes-small-iso-icons+logos.png
+>
+>
+> --
+> Regards
+> Manu Gupta
+>
+
+openSUSE would like to have our logo show up as one of the installable
+OSes within Boxes. Please ensure that you follow the Trademark
+Guidlines[0]. If you would like to modify the logo to work better with
+the application, please submit your proposal of a modified logo for
+approval. This is *ONLY* for openSUSE and _NOT_ for SUSE Enterprise
+Linux.
+
+Many thanks and regards,
+
+Andy
+
+0= http://en.opensuse.org/openSUSE:Trademark_guidelines
+
+--
+Andrew Wafaa
+IRC: FunkyPenguin
+GPG: 0x3A36312F
+=================
+
+From: mrdocs opensuse org Peter Linnell
+Date: Wed, 22 Feb 2012 20:23:31 +0200
+Subject: Re: Permission to use openSUSE Logo for gnome-boxes
+
+On 02/22/2012 02:16 AM, Andrew Wafaa wrote:
+> Hi Manu,
+>
+> On 21 February 2012 17:48, Manu Gupta<manugupt1 gmail com>  wrote:
+>> Hi,
+>>   As you may or may not know, we have been working on a new GNOME
+>> application, Boxes[1] that (among other things) enables users to easily
+>> manage virtual-machines. This also includes ability to detect
+>> operating-systems given an installation media and presenting an
+>> intuitive and *impressive* UI to user to easily install different
+>> operating systems with minimum or no interaction. Boxes makes use of a
+>> new library, libosinfo[2] that provides information about operating
+>> systems (which it internally keeps in an XML database).
+>>
+>> We really want (more like need) to show logos of different operating
+>> systems to the user[3]. Can we please get the permission to use openSUSE logo in
+>> this manner and distribute it along with Boxes or libosinfo?
+>>
+>> [1] http://live.gnome.org/Boxes
+>> [2] https://fedorahosted.org/libosinfo/
+>> [3] http://static.fi/~zeenix/tmp/boxes-small-iso-icons+logos.png
+>>
+>>
+>> --
+>> Regards
+>> Manu Gupta
+>>
+>
+> openSUSE would like to have our logo show up as one of the installable
+> OSes within Boxes. Please ensure that you follow the Trademark
+> Guidlines[0]. If you would like to modify the logo to work better with
+> the application, please submit your proposal of a modified logo for
+> approval. This is *ONLY* for openSUSE and _NOT_ for SUSE Enterprise
+> Linux.
+>
+> Many thanks and regards,
+>
+> Andy
+>
+> 0= http://en.opensuse.org/openSUSE:Trademark_guidelines
+>
+
+Hi Manu,
+
+I am with Andy. Good luck.
+
+Cheers,
+Peter
+=====
+
+Ubuntu
+======
+
+From: michelle canonical com michelle canonical com
+Date: Tue, 21 Feb 2012 17:46:02 +0200
+Subject: Your application to Ubuntu to Trademarks
+
+Hi Zeeshan,
+
+Thank you for contacting us and for your interest in and support of Ubuntu.
+
+============
+
+We have been working on a new GNOME
+application, Boxes[1] that (among other things) enables users to easily
+manage virtuat-machines. This also includes ability to detect
+operating-systems given an installation media and presenting an
+intuitive and impressive UI to user to easily install different
+operating systems with minimum or no interaction. Boxes makes use of a
+new library, libosinfo[2] that provides information about operating
+systems (which it internally keeps in an XML database).
+
+Can we get explicit permission to use the Ubuntu logo (as shown in the screen[3]) and distribut it as part of libosinfo or Boxes itself?
+
+[1] https://live.gnome.org/Boxes
+[2] https://fedorahosted.org/libosinfo/
+[3] http://static.fi/~zeenix/tmp/boxes-small-iso-icons+logos.png
+
+============
+
+Canonical is the official sponsor of the Ubuntu project and owns the trademarks, both in the word and logo form, relating to the project.
+
+To keep the balance between the integrity of our trademarks and the ability to customise Ubuntu, weâve tried to define a reasonable trademark policy that allows our Community to use Ubuntu and to promote the project. You can read the full policy at http://www.ubuntu.com/aboutus/trademarkpolicy.
+
+As your intent is to promote the Ubuntu brand and show your support of the software, we have no issue with you producing the product as you have requested.
+
+You can find our brand guidelines and downloadable images at http://design.ubuntu.com/.
+
+Thanks again for your support.
+
+Kind regards,
+
+
+Michelle,
+Trademarks Team
+
+Michelle Surtees-Myers
+Ubuntu - Linux for Human Beings
diff --git a/configure.ac b/configure.ac
index 82056cb..2bd57bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,7 +52,7 @@ LIBVIRT_GCONFIG_MIN_VERSION=0.1.0
 LIBXML2_MIN_VERSION=2.7.8
 SPICE_GTK_MIN_VERSION=0.12.101
 GUDEV_MIN_VERSION=165
-OSINFO_MIN_VERSION=0.1.1
+OSINFO_MIN_VERSION=0.2.0
 TRACKER_SPARQL=0.13.1
 UUID_REQUIRED=1.41.3
 
diff --git a/data/Makefile.am b/data/Makefile.am
index 9304257..15ff1f6 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -38,6 +38,9 @@ unattended_DATA = fedora.ks			\
 		  disk.img			\
 		  $(NULL)
 
+logosdbdir= $(datadir)/gnome-boxes
+logosdb_DATA= gnome-boxes-logos-db.xml
+
 disk.img:
 	rm -f disk.img && qemu-img create -f raw disk.img 1440k && mkfs.msdos -s 1 disk.img
 
@@ -50,6 +53,7 @@ EXTRA_DIST =					\
 	$(style_DATA)				\
 	$(unattended_DATA)			\
 	$(searchprovider_DATA)			\
+	$(logosdb_DATA)				\
 	$(service_in_files)			\
 	$(NULL)
 
diff --git a/data/gnome-boxes-logos-db.xml b/data/gnome-boxes-logos-db.xml
new file mode 100644
index 0000000..429004e
--- /dev/null
+++ b/data/gnome-boxes-logos-db.xml
@@ -0,0 +1,21 @@
+<libosinfo version="0.0.1">
+
+  <!-- Please read README.logos for any questions about usage of product logos in Boxes. !-->
+
+  <os id="http://debian.org/debian/1.0";>
+    <logo>http://www.debian.org/logos/openlogo-nd.svg</logo>
+  </os>
+
+  <os id="http://fedoraproject.org/fedora/1";>
+    <logo>http://upload.wikimedia.org/wikipedia/commons/3/3f/Fedora_logo.svg</logo>
+  </os>
+
+  <os id="http://opensuse.org/opensuse/10.2";>
+    <logo>http://gitorious.org/opensuse/art/blobs/raw/master/00assets/logo/official-logo-color.svg</logo>
+  </os>
+
+  <os id="http://ubuntu.com/ubuntu/4.10";>
+    <logo>http://design.ubuntu.com/wp-content/uploads/logo-ubuntu_cof-orange-hex.svg</logo>
+  </os>
+
+</libosinfo>
diff --git a/src/Makefile.am b/src/Makefile.am
index f8b8cce..4f87589 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -113,6 +113,7 @@ gnome_boxes_SOURCES =				\
 	winxp-installer.vala 			\
 	wizard-source.vala			\
 	wizard.vala				\
+	downloader.vala				\
 	$(NULL)
 
 gnome_boxes_LDADD =				\
diff --git a/src/downloader.vala b/src/downloader.vala
new file mode 100644
index 0000000..f5d96e4
--- /dev/null
+++ b/src/downloader.vala
@@ -0,0 +1,116 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+private class Boxes.Downloader : GLib.Object {
+    private static Downloader downloader;
+
+    private GLib.HashTable<string,File> downloads;
+
+    public signal void downloaded (string uri, File cached_file);
+    public signal void download_failed (string uri, File cached_file, GLib.Error error);
+
+    public static Downloader get_instance () {
+        if (downloader == null)
+            downloader = new Downloader ();
+
+        return downloader;
+    }
+
+    private Downloader () {
+        downloads = new GLib.HashTable <string,File> (str_hash, str_equal);
+    }
+
+    public async File download (File remote_file, string cached_path) throws GLib.Error {
+        var uri = remote_file.get_uri ();
+
+        if (downloads.contains (uri))
+            // Already being downloaded
+            return yield await_download (uri, cached_path);
+
+        var cached_file = File.new_for_path (cached_path);
+        if (cached_file.query_exists ()) {
+            debug ("'%s' already available locally at '%s'. Not downloading.", uri, cached_path);
+            return cached_file;
+        }
+
+        debug ("Downloading '%s'...", uri);
+        downloads.set (uri, cached_file);
+
+        try {
+            yield remote_file.copy_async (cached_file, FileCopyFlags.NONE);
+        } catch (GLib.Error error) {
+            download_failed (uri, cached_file, error);
+
+            throw error;
+        } finally {
+            downloads.remove (uri);
+        }
+
+        debug ("Downloaded '%s' and its now locally available at '%s'.", uri, cached_path);
+        downloaded (uri, cached_file);
+
+        return cached_file;
+    }
+
+    public static async void fetch_os_logo (Gtk.Image image, Osinfo.Os os, int size) {
+        if (os.logo != null) {
+            debug ("%s has logo '%s'.", os.name, os.logo);
+
+            var remote_file = File.new_for_uri (os.logo);
+            var cached_path = get_logo_cache (remote_file.get_basename ());
+            try {
+                var cached_file = yield get_instance ().download (remote_file, cached_path);
+                var pixbuf = new Gdk.Pixbuf.from_file_at_size (cached_file.get_path (), size, size);
+                image.set_from_pixbuf (pixbuf);
+            } catch (GLib.Error error) {
+                warning ("Error loading logo file '%s': %s", os.logo, error.message);
+            }
+        } else {
+            var derived = os.get_related (Osinfo.ProductRelationship.DERIVES_FROM);
+            if (derived.get_length () > 0) {
+                // FIXME: Does Osinfo allows deriving from multiple OSs?
+                var parent = derived.get_nth (0) as Osinfo.Os;
+
+                yield fetch_os_logo (image, parent, size);
+            }
+        }
+    }
+
+    private async File? await_download (string uri, string cached_path) throws GLib.Error {
+        File downloaded_file = null;
+        GLib.Error download_error = null;
+
+        SourceFunc callback = await_download.callback;
+        var downloaded_id = downloaded.connect ((downloader, downloaded_uri, file) => {
+            if (downloaded_uri != uri)
+                return;
+
+            downloaded_file = file;
+            callback ();
+        });
+        var downloaded_failed_id = download_failed.connect ((downloader, downloaded_uri, file, error) => {
+            if (downloaded_uri != uri)
+                return;
+
+            download_error = error;
+            callback ();
+        });
+
+        debug ("'%s' already being downloaded. Waiting for download to complete..", uri);
+        yield; // Wait for it
+        debug ("Finished waiting for '%s' to download.", uri);
+        disconnect (downloaded_id);
+        disconnect (downloaded_failed_id);
+
+        if (download_error != null)
+            throw download_error;
+
+        File cached_file;
+        if (downloaded_file.get_path () != cached_path) {
+            cached_file = File.new_for_path (cached_path);
+            yield downloaded_file.copy_async (cached_file, FileCopyFlags.OVERWRITE);
+        } else
+            cached_file = downloaded_file;
+
+        return cached_file;
+    }
+}
diff --git a/src/os-database.vala b/src/os-database.vala
index 430f6ea..3fd6215 100644
--- a/src/os-database.vala
+++ b/src/os-database.vala
@@ -31,6 +31,7 @@ private class Boxes.OSDatabase {
     public OSDatabase () throws GLib.Error {
         var loader = new Loader ();
         loader.process_default_path ();
+        loader.process_path (get_logos_db ()); // Load our custom database
         db = loader.get_db ();
     }
 
diff --git a/src/util-app.vala b/src/util-app.vala
index adea140..6882504 100644
--- a/src/util-app.vala
+++ b/src/util-app.vala
@@ -142,30 +142,6 @@ namespace Boxes {
         return (devices.get_length () > 0) ? devices.get_nth (0) as Osinfo.Device : null;
     }
 
-    public Gtk.Image get_os_logo (Osinfo.Os? os, int size) {
-        var image = new Gtk.Image.from_icon_name ("media-optical", 0);
-        image.pixel_size = size;
-
-        if (os != null)
-            fetch_os_logo (image, os, size);
-
-        return image;
-    }
-
-    public void fetch_os_logo (Gtk.Image image, Osinfo.Os os, int size) {
-        var path = get_logo_path (os);
-
-        if (path == null)
-            return;
-
-        try {
-            var pixbuf = new Gdk.Pixbuf.from_file_at_size (path, size, -1);
-            image.set_from_pixbuf (pixbuf);
-        } catch (GLib.Error error) {
-            warning ("Error loading logo file '%s': %s", path, error.message);
-        }
-    }
-
     public GVir.StorageVol? get_storage_volume (GVir.Connection connection,
                                                 GVir.Domain domain,
                                                 out GVir.StoragePool pool) {
diff --git a/src/util.vala b/src/util.vala
index 45ba441..c0f13af 100644
--- a/src/util.vala
+++ b/src/util.vala
@@ -30,6 +30,10 @@ namespace Boxes {
         return Path.build_filename (get_pkgdata (), "sources", file_name);
     }
 
+    public string get_logos_db () {
+        return get_pkgdata ("gnome-boxes-logos-db.xml");
+    }
+
     public string get_user_unattended (string? file_name = null) {
         var dir = Path.build_filename (get_user_pkgconfig (), "unattended");
 
@@ -74,6 +78,14 @@ namespace Boxes {
         return Path.build_filename (dir, file_name);
     }
 
+    public string get_logo_cache (string? file_name = null) {
+        var dir = Path.build_filename (get_user_pkgcache (), "logos");
+
+        ensure_directory (dir);
+
+        return Path.build_filename (dir, file_name);
+    }
+
     public string get_screenshot_filename (string prefix) {
         return get_user_pkgcache (prefix + "-screenshot.png");
     }
diff --git a/src/wizard-source.vala b/src/wizard-source.vala
index 88e0fd0..57d140d 100644
--- a/src/wizard-source.vala
+++ b/src/wizard-source.vala
@@ -217,9 +217,13 @@ private class Boxes.WizardSource: GLib.Object {
             url_entry.activate ();
         }, 15, 5, media.device_file);
 
-        var image = get_os_logo (media.os, 64);
+        var image = new Gtk.Image.from_icon_name ("media-optical", 0);
+        image.pixel_size = 64;
         hbox.pack_start (image, false, false);
 
+        if (media.os != null)
+            Downloader.fetch_os_logo.begin (image, media.os, 64);
+
         var vbox = new Gtk.VBox (true, 5);
         hbox.pack_start (vbox, true, true);
 
diff --git a/src/wizard.vala b/src/wizard.vala
index d640195..def56a6 100644
--- a/src/wizard.vala
+++ b/src/wizard.vala
@@ -255,9 +255,19 @@ private class Boxes.Wizard: Boxes.UI {
         try {
             var install_media = media_manager.create_installer_media_for_path.end (result);
             vm_creator = new VMCreator (install_media);
-            fetch_os_logo (installer_image, install_media.os, 128);
-            prep_progress.fraction = 1.0;
-            page = WizardPage.SETUP;
+            if (install_media.os == null) {
+                 prep_progress.fraction = 1.0;
+                 page = WizardPage.SETUP;
+
+                return;
+            }
+
+            Downloader.fetch_os_logo.begin (installer_image, install_media.os, 128, (object, result) => {
+                Downloader.fetch_os_logo.end (result);
+
+                prep_progress.fraction = 1.0;
+                page = WizardPage.SETUP;
+            });
         } catch (IOError.CANCELLED cancel_error) { // We did this, so no warning!
         } catch (GLib.Error error) {
             App.app.notificationbar.display_error (error.message);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]