Mozilla Headless Screenshot

Build

  • .bashrc
    export MOZILLA_PATH="/path/to/mozilla/dist"
    export MOZILLA_SDK_PATH="$MOZILLA_PATH/sdk"
    export MOZILLA_FIVE_HOME="$MOZILLA_PATH/bin"
    export LD_LIBRARY_PATH="$MOZILLA_PATH/lib:$LD_LIBRARY_PATH"
    
  • Makefile
    MOZ_PATH        = `echo $$MOZILLA_PATH`
    MOZ_SDK_PATH    = `echo $$MOZILLA_SDK_PATH`
    
    CFLAGS  = -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include \
              -I$(MOZ_SDK_PATH)/include -I$(MOZ_PATH)/include/mozheadless \
              -I$(MOZ_PATH)/include/cairo
    LDLIBS  = -lcairo -lglib-2.0 -lxul -lsqlite3 -lmozjs -lsoftokn3 \
              -lnssutil3 -lnss3 -lnspr4
    LDFLAGS = -L$(MOZ_SDK_PATH)/lib -L$(MOZ_PATH)/lib -L$(MOZ_PATH)/bin
    
    all: headless
    
    clean:
        rm headless
    
    headless: moz-headless-screenshot.c
        $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LDLIBS)
    
  • moz-headless-screenshot.c
    #include <glib.h>
    #include <cairo.h>
    #include <moz-headless.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <signal.h>
    
    static MozHeadless *headless;
    static GMainLoop *mainloop;
    static gboolean resized = FALSE;
    static cairo_surface_t *surface;
    
    static void
    net_stop_cb (MozHeadless *headless)
    {
      gint width, height;
      moz_headless_get_document_size (headless, &width, &height);
      surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
      moz_headless_set_surface (headless, cairo_image_surface_get_data (surface),
                                width, height, width * 4); 
      moz_headless_set_size (headless, width, height);
      resized = TRUE;
    }
    
    static void
    updated_cb (MozHeadless *headless, gint x, gint y, gint width, gint height)
    {
      if (resized) g_main_loop_quit (mainloop);
    }
    
    static void
    leave (int sig)
    {
      net_stop_cb (headless);
    }
    
    int
    main (int argc, char **argv)
    {
      gint width, height;
    
      if (argc < 4) {
        printf ("Usage: %s <url> <width> <height> <output.png>", argv[0]);
        return 1;
      }
    
      width = atoi (argv[2]);
      height = atoi (argv[3]);
    
      g_type_init ();
      mainloop = g_main_loop_new (NULL, FALSE);
      headless = moz_headless_new ();
      moz_headless_set_size (headless, width, height);
    
      g_signal_connect (headless, "net-stop",
                        G_CALLBACK (net_stop_cb), NULL);
      g_signal_connect (headless, "updated",
                        G_CALLBACK (updated_cb), NULL);
    
      moz_headless_load_url (headless, argv[1]);
      signal (SIGINT, leave);
      g_main_loop_run (mainloop);
    
      cairo_surface_write_to_png (surface, argv[4]);
      return 0;
    }