add ability to search in web from search view

It use OpenSearch to define the search engines.
https://bugzilla.gnome.org/show_bug.cgi?id=623708
This commit is contained in:
Maxim Ermilov
2011-01-18 00:38:47 +03:00
parent 883f51be93
commit b0c6cf3fc5
12 changed files with 517 additions and 30 deletions

View File

@ -27,6 +27,9 @@
#include <X11/extensions/Xfixes.h>
#include <gjs/gjs-module.h>
#include <canberra.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
@ -1070,6 +1073,136 @@ shell_global_breakpoint (ShellGlobal *global)
G_BREAKPOINT ();
}
/**
* shell_global_parse_search_provider:
* @global: A #ShellGlobal
* @data: description of provider
* @name: (out): location to store a display name
* @url: (out): location to store template of url
* @langs: (out) (transfer full) (element-type utf8): list of supported languages
* @icon_data_uri: (out): location to store uri
* @error: location to store GError
*
* Returns: %TRUE on success
*/
gboolean
shell_global_parse_search_provider (ShellGlobal *global,
const char *data,
char **name,
char **url,
GList **langs,
char **icon_data_uri,
GError **error)
{
xmlDocPtr doc = xmlParseMemory (data, strlen(data));
xmlNode *root;
*name = NULL;
*url = NULL;
*icon_data_uri = NULL;
*langs = NULL;
if (!doc)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Malformed xml");
return FALSE;
}
root = xmlDocGetRootElement (doc);
if (root && root->name && xmlStrcmp (root->name, (const xmlChar *)"OpenSearchDescription") == 0)
{
xmlNode *child;
for (child = root->children; child; child = child->next)
{
if (!child->name)
continue;
if (xmlStrcmp (child->name, (const xmlChar *)"Language") == 0)
{
xmlChar *val = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
if (!val)
continue;
*langs = g_list_append (*langs, g_strdup ((char *)val));
xmlFree (val);
}
if (!*name && xmlStrcmp (child->name, (const xmlChar *)"ShortName") == 0)
{
xmlChar *val = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
*name = g_strdup ((char *)val);
xmlFree (val);
}
if (!*icon_data_uri && xmlStrcmp (child->name, (const xmlChar *)"Image") == 0)
{
xmlChar *val = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
if (val)
*icon_data_uri = g_strdup ((char *)val);
xmlFree (val);
}
if (!*url && xmlStrcmp (child->name, (const xmlChar *)"Url") == 0)
{
xmlChar *template;
xmlChar *type;
type = xmlGetProp(child, (const xmlChar *)"type");
if (!type)
continue;
if (xmlStrcmp (type, (const xmlChar *)"text/html") != 0)
{
xmlFree (type);
continue;
}
xmlFree (type);
template = xmlGetProp(child, (const xmlChar *)"template");
if (!template)
continue;
*url = g_strdup ((char *)template);
xmlFree (template);
}
}
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid OpenSearch document");
xmlFreeDoc (doc);
return FALSE;
}
xmlFreeDoc (doc);
if (*icon_data_uri && *name && *url)
return TRUE;
if (*icon_data_uri)
g_free (*icon_data_uri);
else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"search provider doesn't have icon");
if (*name)
g_free (*name);
else if (error && !*error)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"search provider doesn't have ShortName");
if (*url)
g_free (*url);
else if (error && !*error)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"search provider doesn't have template for url");
if (*langs)
{
g_list_foreach (*langs, (GFunc)g_free, NULL);
g_list_free (*langs);
}
*url = NULL;
*name = NULL;
*icon_data_uri = NULL;
*langs = NULL;
return FALSE;
}
/**
* shell_global_gc:
* @global: A #ShellGlobal

View File

@ -84,6 +84,14 @@ void shell_global_reexec_self (ShellGlobal *global);
void shell_global_breakpoint (ShellGlobal *global);
gboolean shell_global_parse_search_provider (ShellGlobal *global,
const char *data,
char **name,
char **url,
GList **langs,
char **icon_data_uri,
GError **error);
void shell_global_gc (ShellGlobal *global);
void shell_global_maybe_gc (ShellGlobal *global);

View File

@ -437,6 +437,67 @@ out:
return rotated_pixbuf;
}
static GdkPixbuf*
decode_image (const char *val)
{
int i;
GError *error = NULL;
GdkPixbuf *res = NULL;
struct {
const char *prefix;
const char *mime_type;
} formats[] = {
{ "data:image/x-icon;base64,", "image/x-icon" },
{ "data:image/png;base64,", "image/png" }
};
g_return_val_if_fail (val, NULL);
for (i = 0; i < G_N_ELEMENTS (formats); i++)
{
if (g_str_has_prefix (val, formats[i].prefix))
{
gsize len;
guchar *data = NULL;
char *unescaped;
unescaped = g_uri_unescape_string (val + strlen (formats[i].prefix), NULL);
if (unescaped)
{
data = g_base64_decode (unescaped, &len);
g_free (unescaped);
}
if (data)
{
GdkPixbufLoader *loader;
loader = gdk_pixbuf_loader_new_with_mime_type (formats[i].mime_type, &error);
if (loader &&
gdk_pixbuf_loader_write (loader, data, len, &error) &&
gdk_pixbuf_loader_close (loader, &error))
{
res = gdk_pixbuf_loader_get_pixbuf (loader);
g_object_ref (res);
}
g_object_unref (loader);
g_free (data);
}
}
}
if (!res)
{
if (error)
{
g_warning (error->message);
g_error_free (error);
}
else
g_warning ("incorrect data uri");
}
return res;
}
static GdkPixbuf *
impl_load_pixbuf_file (const char *uri,
int available_width,
@ -448,6 +509,9 @@ impl_load_pixbuf_file (const char *uri,
char *contents = NULL;
gsize size;
if (g_str_has_prefix (uri, "data:"))
return decode_image (uri);
file = g_file_new_for_uri (uri);
if (g_file_load_contents (file, NULL, &contents, &size, NULL, error))
{