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:
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
{
|
||||
|
Reference in New Issue
Block a user