Add support for creating and parsing URLs (issue #181).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@177 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
83dd15925f
commit
64d9d8294c
1
cef.gyp
1
cef.gyp
|
@ -183,6 +183,7 @@
|
|||
'tests/unittests/string_unittest.cc',
|
||||
'tests/unittests/test_handler.h',
|
||||
'tests/unittests/test_suite.h',
|
||||
'tests/unittests/url_unittest.cc',
|
||||
'tests/unittests/v8_unittest.cc',
|
||||
'tests/unittests/xml_reader_unittest.cc',
|
||||
'tests/unittests/zip_reader_unittest.cc',
|
||||
|
|
|
@ -59,6 +59,7 @@ class CefSettings;
|
|||
class CefStreamReader;
|
||||
class CefStreamWriter;
|
||||
class CefTask;
|
||||
class CefURLParts;
|
||||
class CefV8Handler;
|
||||
class CefV8Value;
|
||||
|
||||
|
@ -179,6 +180,18 @@ bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task);
|
|||
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
|
||||
long delay_ms);
|
||||
|
||||
// Parse the specified |url| into its component parts.
|
||||
// Returns false if the URL is empty or invalid.
|
||||
/*--cef()--*/
|
||||
bool CefParseURL(const CefString& url,
|
||||
CefURLParts& parts);
|
||||
|
||||
// Creates a URL from the specified |parts|, which must contain a non-empty
|
||||
// spec or a non-empty host and path (at a minimum), but not both.
|
||||
// Returns false if |parts| isn't initialized as described.
|
||||
/*--cef()--*/
|
||||
bool CefCreateURL(const CefURLParts& parts,
|
||||
CefString& url);
|
||||
|
||||
// Interface defining the the reference count implementation methods. All
|
||||
// framework classes must implement the CefBase class.
|
||||
|
@ -1886,4 +1899,77 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
// Class used to represent a URL's component parts.
|
||||
class CefURLParts : public cef_urlparts_t
|
||||
{
|
||||
public:
|
||||
CefURLParts()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
virtual ~CefURLParts()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
CefURLParts(const CefURLParts& r)
|
||||
{
|
||||
Init();
|
||||
*this = r;
|
||||
}
|
||||
CefURLParts(const cef_urlparts_t& r)
|
||||
{
|
||||
Init();
|
||||
*this = r;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
cef_string_clear(&spec);
|
||||
cef_string_clear(&scheme);
|
||||
cef_string_clear(&username);
|
||||
cef_string_clear(&password);
|
||||
cef_string_clear(&host);
|
||||
cef_string_clear(&port);
|
||||
cef_string_clear(&path);
|
||||
cef_string_clear(&query);
|
||||
Init();
|
||||
}
|
||||
|
||||
void Attach(const cef_urlparts_t& r)
|
||||
{
|
||||
Reset();
|
||||
*static_cast<cef_urlparts_t*>(this) = r;
|
||||
}
|
||||
|
||||
void Detach()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CefURLParts& operator=(const CefURLParts& r)
|
||||
{
|
||||
return operator=(static_cast<const cef_urlparts_t&>(r));
|
||||
}
|
||||
|
||||
CefURLParts& operator=(const cef_urlparts_t& r)
|
||||
{
|
||||
cef_string_copy(r.spec.str, r.spec.length, &spec);
|
||||
cef_string_copy(r.scheme.str, r.scheme.length, &scheme);
|
||||
cef_string_copy(r.username.str, r.username.length, &username);
|
||||
cef_string_copy(r.password.str, r.password.length, &password);
|
||||
cef_string_copy(r.host.str, r.host.length, &host);
|
||||
cef_string_copy(r.port.str, r.port.length, &port);
|
||||
cef_string_copy(r.path.str, r.path.length, &path);
|
||||
cef_string_copy(r.query.str, r.query.length, &query);
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void Init()
|
||||
{
|
||||
memset(static_cast<cef_urlparts_t*>(this), 0, sizeof(cef_urlparts_t));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _CEF_H
|
||||
|
|
|
@ -152,6 +152,17 @@ CEF_EXPORT int cef_post_task(cef_thread_id_t threadId,
|
|||
CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
|
||||
struct _cef_task_t* task, long delay_ms);
|
||||
|
||||
// Parse the specified |url| into its component parts. Returns false (0) if the
|
||||
// URL is NULL or invalid.
|
||||
CEF_EXPORT int cef_parse_url(const cef_string_t* url,
|
||||
struct _cef_urlparts_t* parts);
|
||||
|
||||
// Creates a URL from the specified |parts|, which must contain a non-NULL spec
|
||||
// or a non-NULL host and path (at a minimum), but not both. Returns false (0)
|
||||
// if |parts| isn't initialized as described.
|
||||
CEF_EXPORT int cef_create_url(const struct _cef_urlparts_t* parts,
|
||||
cef_string_t* url);
|
||||
|
||||
typedef struct _cef_base_t
|
||||
{
|
||||
// Size of the data structure.
|
||||
|
|
|
@ -238,6 +238,35 @@ typedef struct _cef_browser_settings_t
|
|||
bool developer_tools_disabled;
|
||||
} cef_browser_settings_t;
|
||||
|
||||
// URL component parts.
|
||||
typedef struct _cef_urlparts_t
|
||||
{
|
||||
// The complete URL specification.
|
||||
cef_string_t spec;
|
||||
|
||||
// Scheme component not including the colon (e.g., "http").
|
||||
cef_string_t scheme;
|
||||
|
||||
// User name component.
|
||||
cef_string_t username;
|
||||
|
||||
// Password component.
|
||||
cef_string_t password;
|
||||
|
||||
// Host component. This may be a hostname, an IPv4 address or an IPv6 literal
|
||||
// surrounded by square brackets (e.g., "[2001:db8::1]").
|
||||
cef_string_t host;
|
||||
|
||||
// Port number component.
|
||||
cef_string_t port;
|
||||
|
||||
// Path component including the first slash following the host.
|
||||
cef_string_t path;
|
||||
|
||||
// Query string component (i.e., everything following the '?').
|
||||
cef_string_t query;
|
||||
} cef_urlparts_t;
|
||||
|
||||
// Define handler return value types. Returning RV_HANDLED indicates
|
||||
// that the implementation completely handled the method and that no further
|
||||
// processing is required. Returning RV_CONTINUE indicates that the
|
||||
|
|
|
@ -187,6 +187,69 @@ bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
|
|||
new CefTaskHelper(task, threadId), delay_ms);
|
||||
}
|
||||
|
||||
bool CefParseURL(const CefString& url,
|
||||
CefURLParts& parts)
|
||||
{
|
||||
GURL gurl(url.ToString());
|
||||
if (!gurl.is_valid())
|
||||
return false;
|
||||
|
||||
CefString(&parts.spec).FromString(gurl.spec());
|
||||
CefString(&parts.scheme).FromString(gurl.scheme());
|
||||
CefString(&parts.username).FromString(gurl.username());
|
||||
CefString(&parts.password).FromString(gurl.password());
|
||||
CefString(&parts.host).FromString(gurl.host());
|
||||
CefString(&parts.port).FromString(gurl.port());
|
||||
CefString(&parts.path).FromString(gurl.path());
|
||||
CefString(&parts.query).FromString(gurl.query());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CefCreateURL(const CefURLParts& parts,
|
||||
CefString& url)
|
||||
{
|
||||
std::string spec = CefString(parts.spec.str, parts.spec.length, false);
|
||||
std::string scheme = CefString(parts.scheme.str, parts.scheme.length, false);
|
||||
std::string username =
|
||||
CefString(parts.username.str, parts.username.length, false);
|
||||
std::string password =
|
||||
CefString(parts.password.str, parts.password.length, false);
|
||||
std::string host = CefString(parts.host.str, parts.host.length, false);
|
||||
std::string port = CefString(parts.port.str, parts.port.length, false);
|
||||
std::string path = CefString(parts.path.str, parts.path.length, false);
|
||||
std::string query = CefString(parts.query.str, parts.query.length, false);
|
||||
|
||||
GURL gurl;
|
||||
if (!spec.empty()) {
|
||||
gurl = GURL(spec);
|
||||
} else if (!scheme.empty() && !host.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << scheme << "://";
|
||||
if (!username.empty()) {
|
||||
ss << username;
|
||||
if (!password.empty())
|
||||
ss << ":" << password;
|
||||
ss << "@";
|
||||
}
|
||||
ss << host;
|
||||
if (!port.empty())
|
||||
ss << ":" << port;
|
||||
if (!path.empty())
|
||||
ss << path;
|
||||
if (!query.empty())
|
||||
ss << "?" << query;
|
||||
gurl = GURL(ss.str());
|
||||
}
|
||||
|
||||
if (gurl.is_valid()) {
|
||||
url = gurl.spec();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// CefContext
|
||||
|
||||
|
|
|
@ -186,3 +186,57 @@ CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
|
|||
|
||||
return CefPostDelayedTask(threadId, CefTaskCToCpp::Wrap(task), delay_ms);
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_parse_url(const cef_string_t* url,
|
||||
struct _cef_urlparts_t* parts)
|
||||
{
|
||||
DCHECK(url && parts);
|
||||
if(!url || !parts)
|
||||
return 0;
|
||||
|
||||
CefURLParts urlParts;
|
||||
bool ret = CefParseURL(CefString(url), urlParts);
|
||||
|
||||
// Clear the current structure values, if any.
|
||||
cef_string_clear(&parts->spec);
|
||||
cef_string_clear(&parts->scheme);
|
||||
cef_string_clear(&parts->username);
|
||||
cef_string_clear(&parts->password);
|
||||
cef_string_clear(&parts->host);
|
||||
cef_string_clear(&parts->port);
|
||||
cef_string_clear(&parts->path);
|
||||
cef_string_clear(&parts->query);
|
||||
|
||||
// Transfer ownership of the values from |urlParts| to the structure.
|
||||
memcpy(parts, static_cast<cef_urlparts_t*>(&urlParts),
|
||||
sizeof(cef_urlparts_t));
|
||||
urlParts.Detach();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_create_url(const struct _cef_urlparts_t* parts,
|
||||
cef_string_t* url)
|
||||
{
|
||||
DCHECK(parts && url);
|
||||
if(!parts || !url)
|
||||
return 0;
|
||||
|
||||
CefURLParts urlParts;
|
||||
|
||||
// Reference the existing structure values without copying.
|
||||
cef_string_set(parts->spec.str, parts->spec.length, &urlParts.spec, false);
|
||||
cef_string_set(parts->scheme.str, parts->scheme.length, &urlParts.scheme,
|
||||
false);
|
||||
cef_string_set(parts->username.str, parts->username.length,
|
||||
&urlParts.username, false);
|
||||
cef_string_set(parts->password.str, parts->password.length,
|
||||
&urlParts.password, false);
|
||||
cef_string_set(parts->host.str, parts->host.length, &urlParts.host, false);
|
||||
cef_string_set(parts->port.str, parts->port.length, &urlParts.port, false);
|
||||
cef_string_set(parts->path.str, parts->path.length, &urlParts.path, false);
|
||||
cef_string_set(parts->query.str, parts->query.length, &urlParts.query, false);
|
||||
|
||||
CefString urlStr(url);
|
||||
return CefCreateURL(urlParts, urlStr);
|
||||
}
|
||||
|
|
|
@ -159,3 +159,15 @@ bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
|
|||
return cef_post_delayed_task(threadId, CefTaskCppToC::Wrap(task), delay_ms)?
|
||||
true:false;
|
||||
}
|
||||
|
||||
bool CefParseURL(const CefString& url,
|
||||
CefURLParts& parts)
|
||||
{
|
||||
return cef_parse_url(url.GetStruct(), &parts) ? true : false;
|
||||
}
|
||||
|
||||
bool CefCreateURL(const CefURLParts& parts,
|
||||
CefString& url)
|
||||
{
|
||||
return cef_create_url(&parts, url.GetWritableStruct()) ? true : false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
TEST(URLTest, CreateURL)
|
||||
{
|
||||
// Create the URL using the spec.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
CefString(&parts.spec).FromASCII(
|
||||
"http://user:pass@www.example.com:88/path/to.html?foo=test&bar=test2");
|
||||
ASSERT_TRUE(CefCreateURL(parts, url));
|
||||
ASSERT_EQ(url,
|
||||
"http://user:pass@www.example.com:88/path/to.html?foo=test&bar=test2");
|
||||
}
|
||||
|
||||
// Test that scheme and host are required.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
CefString(&parts.scheme).FromASCII("http");
|
||||
ASSERT_FALSE(CefCreateURL(parts, url));
|
||||
}
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
CefString(&parts.host).FromASCII("www.example.com");
|
||||
ASSERT_FALSE(CefCreateURL(parts, url));
|
||||
}
|
||||
|
||||
// Create the URL using scheme and host.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
CefString(&parts.scheme).FromASCII("http");
|
||||
CefString(&parts.host).FromASCII("www.example.com");
|
||||
ASSERT_TRUE(CefCreateURL(parts, url));
|
||||
ASSERT_EQ(url, "http://www.example.com/");
|
||||
}
|
||||
|
||||
// Create the URL using scheme, host and path.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
CefString(&parts.scheme).FromASCII("http");
|
||||
CefString(&parts.host).FromASCII("www.example.com");
|
||||
CefString(&parts.path).FromASCII("/path/to.html");
|
||||
ASSERT_TRUE(CefCreateURL(parts, url));
|
||||
ASSERT_EQ(url, "http://www.example.com/path/to.html");
|
||||
}
|
||||
|
||||
// Create the URL using scheme, host, path and query.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
CefString(&parts.scheme).FromASCII("http");
|
||||
CefString(&parts.host).FromASCII("www.example.com");
|
||||
CefString(&parts.path).FromASCII("/path/to.html");
|
||||
CefString(&parts.query).FromASCII("foo=test&bar=test2");
|
||||
ASSERT_TRUE(CefCreateURL(parts, url));
|
||||
ASSERT_EQ(url, "http://www.example.com/path/to.html?foo=test&bar=test2");
|
||||
}
|
||||
|
||||
// Create the URL using all the various components.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
CefString(&parts.scheme).FromASCII("http");
|
||||
CefString(&parts.username).FromASCII("user");
|
||||
CefString(&parts.password).FromASCII("pass");
|
||||
CefString(&parts.host).FromASCII("www.example.com");
|
||||
CefString(&parts.port).FromASCII("88");
|
||||
CefString(&parts.path).FromASCII("/path/to.html");
|
||||
CefString(&parts.query).FromASCII("foo=test&bar=test2");
|
||||
ASSERT_TRUE(CefCreateURL(parts, url));
|
||||
ASSERT_EQ(url,
|
||||
"http://user:pass@www.example.com:88/path/to.html?foo=test&bar=test2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(URLTest, ParseURL)
|
||||
{
|
||||
// Parse the URL using scheme and host.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
url.FromASCII("http://www.example.com");
|
||||
ASSERT_TRUE(CefParseURL(url, parts));
|
||||
|
||||
CefString spec(&parts.spec);
|
||||
ASSERT_EQ(spec, "http://www.example.com/");
|
||||
ASSERT_EQ(parts.username.length, 0);
|
||||
ASSERT_EQ(parts.password.length, 0);
|
||||
CefString scheme(&parts.scheme);
|
||||
ASSERT_EQ(scheme, "http");
|
||||
CefString host(&parts.host);
|
||||
ASSERT_EQ(host, "www.example.com");
|
||||
ASSERT_EQ(parts.port.length, 0);
|
||||
CefString path(&parts.path);
|
||||
ASSERT_EQ(path, "/");
|
||||
ASSERT_EQ(parts.query.length, 0);
|
||||
}
|
||||
|
||||
// Parse the URL using scheme, host and path.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
url.FromASCII("http://www.example.com/path/to.html");
|
||||
ASSERT_TRUE(CefParseURL(url, parts));
|
||||
|
||||
CefString spec(&parts.spec);
|
||||
ASSERT_EQ(spec, "http://www.example.com/path/to.html");
|
||||
ASSERT_EQ(parts.username.length, 0);
|
||||
ASSERT_EQ(parts.password.length, 0);
|
||||
CefString scheme(&parts.scheme);
|
||||
ASSERT_EQ(scheme, "http");
|
||||
CefString host(&parts.host);
|
||||
ASSERT_EQ(host, "www.example.com");
|
||||
ASSERT_EQ(parts.port.length, 0);
|
||||
CefString path(&parts.path);
|
||||
ASSERT_EQ(path, "/path/to.html");
|
||||
ASSERT_EQ(parts.query.length, 0);
|
||||
}
|
||||
|
||||
// Parse the URL using scheme, host, path and query.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
url.FromASCII("http://www.example.com/path/to.html?foo=test&bar=test2");
|
||||
ASSERT_TRUE(CefParseURL(url, parts));
|
||||
|
||||
CefString spec(&parts.spec);
|
||||
ASSERT_EQ(spec, "http://www.example.com/path/to.html?foo=test&bar=test2");
|
||||
ASSERT_EQ(parts.username.length, 0);
|
||||
ASSERT_EQ(parts.password.length, 0);
|
||||
CefString scheme(&parts.scheme);
|
||||
ASSERT_EQ(scheme, "http");
|
||||
CefString host(&parts.host);
|
||||
ASSERT_EQ(host, "www.example.com");
|
||||
ASSERT_EQ(parts.port.length, 0);
|
||||
CefString path(&parts.path);
|
||||
ASSERT_EQ(path, "/path/to.html");
|
||||
CefString query(&parts.query);
|
||||
ASSERT_EQ(query, "foo=test&bar=test2");
|
||||
}
|
||||
|
||||
// Parse the URL using all the various components.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
url.FromASCII(
|
||||
"http://user:pass@www.example.com:88/path/to.html?foo=test&bar=test2");
|
||||
ASSERT_TRUE(CefParseURL(url, parts));
|
||||
|
||||
CefString spec(&parts.spec);
|
||||
ASSERT_EQ(spec,
|
||||
"http://user:pass@www.example.com:88/path/to.html?foo=test&bar=test2");
|
||||
CefString scheme(&parts.scheme);
|
||||
ASSERT_EQ(scheme, "http");
|
||||
CefString username(&parts.username);
|
||||
ASSERT_EQ(username, "user");
|
||||
CefString password(&parts.password);
|
||||
ASSERT_EQ(password, "pass");
|
||||
CefString host(&parts.host);
|
||||
ASSERT_EQ(host, "www.example.com");
|
||||
CefString port(&parts.port);
|
||||
ASSERT_EQ(port, "88");
|
||||
CefString path(&parts.path);
|
||||
ASSERT_EQ(path, "/path/to.html");
|
||||
CefString query(&parts.query);
|
||||
ASSERT_EQ(query, "foo=test&bar=test2");
|
||||
}
|
||||
|
||||
// Parse an invalid URL.
|
||||
{
|
||||
CefURLParts parts;
|
||||
CefString url;
|
||||
url.FromASCII("www.example.com");
|
||||
ASSERT_FALSE(CefParseURL(url, parts));
|
||||
}
|
||||
}
|
|
@ -1060,6 +1060,7 @@ class obj_analysis:
|
|||
'CefPopupFeatures' : 'cef_popup_features_t',
|
||||
'CefSettings' : 'cef_settings_t',
|
||||
'CefBrowserSettings' : 'cef_browser_settings_t',
|
||||
'CefURLParts' : 'cef_urlparts_t',
|
||||
}
|
||||
if value in structuretypes.keys():
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue