Merge "Add default code reviewers into OWNERS"
diff --git a/Android.bp b/Android.bp
index 8c38aaa..bf5c328 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3,6 +3,7 @@
srcs: [
"src/proxy_resolver_v8.cc",
+ "src/proxy_resolver_v8_wrapper.cc",
"src/proxy_resolver_js_bindings.cc",
"src/net_util.cc",
],
@@ -15,14 +16,24 @@
"-Werror",
],
- export_include_dirs: ["src"],
+ export_include_dirs: ["includes"],
+ local_include_dirs: ["src"],
- static_libs: ["libv8"],
+ static_libs: [
+ "libv8",
+ // libpac lives in Runtime APEX. It can't use the shared liblog in /system/.
+ "liblog",
+ ],
shared_libs: [
- "libutils",
- "liblog",
"libicuuc",
"libicui18n",
],
+
+ stubs: {
+ symbol_file: "libpac.map.txt",
+ versions: [
+ "1",
+ ],
+ },
}
diff --git a/includes/proxy_resolver_v8_wrapper.h b/includes/proxy_resolver_v8_wrapper.h
new file mode 100644
index 0000000..776a45d
--- /dev/null
+++ b/includes/proxy_resolver_v8_wrapper.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NET_PROXY_PROXY_RESOLVER_V8_WRAPPER_H_
+#define NET_PROXY_PROXY_RESOLVER_V8_WRAPPER_H_
+
+// This header should be compatible with C or C++ compiler
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OK 0
+#define ERR_PAC_SCRIPT_FAILED -1
+#define ERR_FAILED -2
+
+/**
+* Declare an incomplete type ProxyResolverV8Handle. A pointer of this should always be
+* either null or pointing to a C++ ProxyResolverV8 object.
+*/
+typedef void* ProxyResolverV8Handle;
+
+/**
+ * Create a ProxyResolverV8Handle. The caller must call ProxyResolverV8Handle_delete to release
+ * the memory.
+ */
+ProxyResolverV8Handle* ProxyResolverV8Handle_new();
+
+/**
+ * @return the result in char16_t array if the run is successful. The result contains a list of
+ * proxies according to the PAC specification. Otherwise, return NULL if the run fails.
+ * The memory is allocated with malloc() and the caller should use free() to release it
+ * after use.
+ */
+char16_t* ProxyResolverV8Handle_GetProxyForURL(ProxyResolverV8Handle* handle,
+ const char16_t* spec, const char16_t* host);
+/**
+ * @return OK if setting the pac script successfully.
+ */
+int ProxyResolverV8Handle_SetPacScript(ProxyResolverV8Handle* handle,
+ const char16_t* script_data);
+
+void ProxyResolverV8Handle_delete(ProxyResolverV8Handle* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NET_PROXY_PROXY_RESOLVER_V8_WRAPPER_H_
\ No newline at end of file
diff --git a/libpac.map.txt b/libpac.map.txt
new file mode 100644
index 0000000..1936fa9
--- /dev/null
+++ b/libpac.map.txt
@@ -0,0 +1,23 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LIBPAC_EXTERNAL_1 {
+ global:
+ ProxyResolverV8Handle_new;
+ ProxyResolverV8Handle_GetProxyForURL;
+ ProxyResolverV8Handle_SetPacScript;
+ ProxyResolverV8Handle_delete;
+ local:
+ *;
+};
\ No newline at end of file
diff --git a/src/proxy_resolver_js_bindings.h b/src/proxy_resolver_js_bindings.h
index 9559492..ebdacfe 100644
--- a/src/proxy_resolver_js_bindings.h
+++ b/src/proxy_resolver_js_bindings.h
@@ -6,13 +6,10 @@
#define NET_PROXY_PROXY_RESOLVER_JS_BINDINGS_H_
#pragma once
-#include <utils/String16.h>
#include <string>
namespace net {
-class ProxyErrorListener;
-
// Interface for the javascript bindings.
class ProxyResolverJSBindings {
public:
diff --git a/src/proxy_resolver_v8.cc b/src/proxy_resolver_v8.cc
index e37334c..f26ff9d 100644
--- a/src/proxy_resolver_v8.cc
+++ b/src/proxy_resolver_v8.cc
@@ -2,13 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifdef ANDROID
+#define LOG_TAG "libpac"
+#include <utils/Log.h>
+#endif
+
#include "proxy_resolver_v8.h"
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string>
-#include <utils/String8.h>
#include <v8.h>
#include <libplatform/libplatform.h>
#include <vector>
@@ -65,50 +69,49 @@
// isInNetEx() | N/A | IPv4/IPv6 | IPv4/IPv6
// -----------------+-------------+-------------------+--------------
-static bool DoIsStringASCII(const android::String16& str) {
- for (size_t i = 0; i < str.size(); i++) {
- unsigned short c = str.string()[i];
+static bool DoIsStringASCII(const std::u16string& str) {
+ for (size_t i = 0; i < str.length(); i++) {
+ unsigned short c = str.data()[i];
if (c > 0x7F)
return false;
}
return true;
}
-bool IsStringASCII(const android::String16& str) {
+bool IsStringASCII(const std::u16string& str) {
return DoIsStringASCII(str);
}
+#ifdef ANDROID
+#define LOG_ALERT(...) ALOGD(__VA_ARGS__)
+#define LOG_ERROR(...) ALOGE(__VA_ARGS__)
+#else
+#define LOG_ALERT(...) vprintf(__VA_ARGS__)
+#define LOG_ERROR(...) vfprintf(stderr, __VA_ARGS__)
+#endif
+
namespace net {
namespace {
+class DefaultProxyErrorListener : public ProxyErrorListener {
+public:
+ ~DefaultProxyErrorListener() {}
+ void AlertMessage(const std::string& message) {
+ LOG_ALERT("Alert: %s", message.data());
+ }
+ void ErrorMessage(const std::string& message) {
+ LOG_ERROR("Error: %s", message.data());
+ }
+};
+
+ProxyErrorListener* const defaultProxyErrorListener = new DefaultProxyErrorListener();
+
// Pseudo-name for the PAC script.
const char kPacResourceName[] = "proxy-pac-script.js";
// Pseudo-name for the PAC utility script.
const char kPacUtilityResourceName[] = "proxy-pac-utility-script.js";
-// External string wrapper so V8 can access the UTF16 string wrapped by
-// ProxyResolverScriptData.
-class V8ExternalStringFromScriptData
- : public v8::String::ExternalStringResource {
- public:
- explicit V8ExternalStringFromScriptData(
- const android::String16& script_data)
- : script_data_(script_data) {}
-
- virtual const uint16_t* data() const {
- return reinterpret_cast<const uint16_t*>(script_data_.string());
- }
-
- virtual size_t length() const {
- return script_data_.size();
- }
-
- private:
- const android::String16& script_data_;
-// DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData);
-};
-
// External string wrapper so V8 can access a string literal.
class V8ExternalASCIILiteral
: public v8::String::ExternalOneByteStringResource {
@@ -155,28 +158,23 @@
}
// Converts a V8 String to a UTF16 string.
-android::String16 V8StringToUTF16(v8::Handle<v8::String> s) {
+std::u16string V8StringToUTF16(v8::Handle<v8::String> s) {
int len = s->Length();
char16_t* buf = new char16_t[len + 1];
s->Write(reinterpret_cast<uint16_t*>(buf), 0, len);
- android::String16 ret(buf, len);
+ std::u16string ret(buf, len);
delete[] buf;
return ret;
}
-std::string UTF16ToASCII(const android::String16& str) {
- android::String8 rstr(str);
- return std::string(rstr.string());
-}
-
// Converts an ASCII std::string to a V8 string.
v8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate, const std::string& s) {
return v8::String::NewFromUtf8(isolate, s.data(), v8::String::kNormalString, s.size());
}
-v8::Local<v8::String> UTF16StringToV8String(v8::Isolate* isolate, const android::String16& s) {
+v8::Local<v8::String> UTF16StringToV8String(v8::Isolate* isolate, const std::u16string& s) {
return v8::String::NewFromTwoByte(
- isolate, reinterpret_cast<const uint16_t*>(s.string()),
+ isolate, reinterpret_cast<const uint16_t*>(s.data()),
v8::String::kNormalString, s.size());
}
@@ -191,8 +189,8 @@
// Stringizes a V8 object by calling its toString() method. Returns true
// on success. This may fail if the toString() throws an exception.
-bool V8ObjectToUTF16String(v8::Handle<v8::Value> object,
- android::String16* utf16_result,
+bool V8ObjectToUTF8String(v8::Handle<v8::Value> object,
+ std::string* utf8_result,
v8::Isolate* isolate) {
if (object.IsEmpty())
return false;
@@ -201,7 +199,7 @@
v8::Local<v8::String> str_object = object->ToString();
if (str_object.IsEmpty())
return false;
- *utf16_result = V8StringToUTF16(str_object);
+ *utf8_result = V8StringToUTF8(str_object);
return true;
}
@@ -212,11 +210,11 @@
if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString())
return false;
- const android::String16 hostname_utf16 = V8StringToUTF16(args[0]->ToString());
+ const std::u16string hostname_utf16 = V8StringToUTF16(args[0]->ToString());
// If the hostname is already in ASCII, simply return it as is.
if (IsStringASCII(hostname_utf16)) {
- *hostname = UTF16ToASCII(hostname_utf16);
+ *hostname = V8StringToUTF8(args[0]->ToString());
return true;
}
return false;
@@ -371,8 +369,8 @@
v8_context_.Reset();
}
- int ResolveProxy(const android::String16 url, const android::String16 host,
- android::String16* results) {
+ int ResolveProxy(const std::u16string url, const std::u16string host,
+ std::u16string* results) {
v8::Locker locked(isolate_);
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope scope(isolate_);
@@ -383,8 +381,7 @@
v8::Local<v8::Value> function;
if (!GetFindProxyForURL(&function)) {
- error_listener_->ErrorMessage(
- android::String16("FindProxyForURL() is undefined"));
+ error_listener_->ErrorMessage("FindProxyForURL() is undefined");
return ERR_PAC_SCRIPT_FAILED;
}
@@ -397,14 +394,12 @@
context->Global(), 2, argv);
if (try_catch.HasCaught()) {
- error_listener_->ErrorMessage(
- V8StringToUTF16(try_catch.Message()->Get()));
+ error_listener_->ErrorMessage(V8StringToUTF8(try_catch.Message()->Get()));
return ERR_PAC_SCRIPT_FAILED;
}
if (!ret->IsString()) {
- error_listener_->ErrorMessage(
- android::String16("FindProxyForURL() did not return a string."));
+ error_listener_->ErrorMessage("FindProxyForURL() did not return a string.");
return ERR_PAC_SCRIPT_FAILED;
}
@@ -415,15 +410,14 @@
// could extend the parsing to handle IDNA hostnames by
// converting them to ASCII punycode.
// crbug.com/47234
- error_listener_->ErrorMessage(
- android::String16("FindProxyForURL() returned a non-ASCII string"));
+ error_listener_->ErrorMessage("FindProxyForURL() returned a non-ASCII string");
return ERR_PAC_SCRIPT_FAILED;
}
return OK;
}
- int InitV8(const android::String16& pac_script) {
+ int InitV8(const std::u16string& pac_script) {
v8::Locker locked(isolate_);
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope scope(isolate_);
@@ -523,7 +517,7 @@
void HandleError(v8::Handle<v8::Message> message) {
if (message.IsEmpty())
return;
- error_listener_->ErrorMessage(V8StringToUTF16(message->Get()));
+ error_listener_->ErrorMessage(V8StringToUTF8(message->Get()));
}
// Compiles and runs |script| in the current V8 context.
@@ -556,14 +550,11 @@
// Like firefox we assume "undefined" if no argument was specified, and
// disregard any arguments beyond the first.
- android::String16 message;
+ std::string message;
if (args.Length() == 0) {
- std::string undef = "undefined";
- android::String8 undef8(undef.c_str());
- android::String16 wundef(undef8);
- message = wundef;
+ message = "undefined";
} else {
- if (!V8ObjectToUTF16String(args[0], &message, args.GetIsolate()))
+ if (!V8ObjectToUTF8String(args[0], &message, args.GetIsolate()))
return; // toString() threw an exception.
}
@@ -714,6 +705,10 @@
bool ProxyResolverV8::initialized_for_this_process_ = false;
+ProxyResolverV8::ProxyResolverV8(ProxyResolverJSBindings* custom_js_bindings)
+ : ProxyResolverV8(custom_js_bindings, defaultProxyErrorListener) {
+}
+
ProxyResolverV8::ProxyResolverV8(
ProxyResolverJSBindings* custom_js_bindings,
ProxyErrorListener* error_listener)
@@ -737,13 +732,14 @@
}
}
-int ProxyResolverV8::GetProxyForURL(const android::String16 spec, const android::String16 host,
- android::String16* results) {
+int ProxyResolverV8::GetProxyForURL(const std::u16string& spec, const std::u16string& host,
+ std::u16string* results) {
// If the V8 instance has not been initialized (either because
// SetPacScript() wasn't called yet, or because it failed.
- if (context_ == NULL)
+ if (context_ == NULL) {
+ error_listener_->ErrorMessage(std::string("Context is null."));
return ERR_FAILED;
-
+ }
// Otherwise call into V8.
int rv = context_->ResolveProxy(spec, host, results);
@@ -754,12 +750,12 @@
context_->PurgeMemory();
}
-int ProxyResolverV8::SetPacScript(const android::String16& script_data) {
+int ProxyResolverV8::SetPacScript(const std::u16string& script_data) {
if (context_ != NULL) {
delete context_;
context_ = NULL;
}
- if (script_data.size() == 0)
+ if (script_data.length() == 0)
return ERR_PAC_SCRIPT_FAILED;
// Use the built-in locale-aware definitions instead of the ones provided by
diff --git a/src/proxy_resolver_v8.h b/src/proxy_resolver_v8.h
index 9b74e29..36a3214 100644
--- a/src/proxy_resolver_v8.h
+++ b/src/proxy_resolver_v8.h
@@ -6,25 +6,19 @@
#define NET_PROXY_PROXY_RESOLVER_V8_H_
#pragma once
-#include <utils/String16.h>
+#include <string>
#include "proxy_resolver_js_bindings.h"
+#include "proxy_resolver_v8_wrapper.h"
namespace net {
-typedef void* RequestHandle;
-typedef void* CompletionCallback;
-
-#define OK 0
-#define ERR_PAC_SCRIPT_FAILED -1
-#define ERR_FAILED -2
-
class ProxyErrorListener {
protected:
virtual ~ProxyErrorListener() {}
public:
- virtual void AlertMessage(android::String16 message) = 0;
- virtual void ErrorMessage(android::String16 error) = 0;
+ virtual void AlertMessage(const std::string& message) = 0;
+ virtual void ErrorMessage(const std::string& error) = 0;
};
// Implementation of ProxyResolver that uses V8 to evaluate PAC scripts.
@@ -50,6 +44,8 @@
// Constructs a ProxyResolverV8 with custom bindings. ProxyResolverV8 takes
// ownership of |custom_js_bindings| and deletes it when ProxyResolverV8
// is destroyed.
+ explicit ProxyResolverV8(ProxyResolverJSBindings* custom_js_bindings);
+ // This constructor should only be used for test.
explicit ProxyResolverV8(ProxyResolverJSBindings* custom_js_bindings,
ProxyErrorListener* error_listener);
@@ -57,10 +53,10 @@
ProxyResolverJSBindings* js_bindings() { return js_bindings_; }
- virtual int GetProxyForURL(const android::String16 spec, const android::String16 host,
- android::String16* results);
+ virtual int GetProxyForURL(const std::u16string& spec, const std::u16string& host,
+ std::u16string* results);
virtual void PurgeMemory();
- virtual int SetPacScript(const android::String16& script_data);
+ virtual int SetPacScript(const std::u16string& script_data);
private:
// Context holds the Javascript state for the most recently loaded PAC
diff --git a/src/proxy_resolver_v8_wrapper.cc b/src/proxy_resolver_v8_wrapper.cc
new file mode 100644
index 0000000..ae56d9a
--- /dev/null
+++ b/src/proxy_resolver_v8_wrapper.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "proxy_resolver_v8_wrapper.h"
+#include "proxy_resolver_v8.h"
+
+using namespace net;
+
+// Implement C interface of ProxyResolverV8
+extern "C" {
+
+ProxyResolverV8Handle* ProxyResolverV8Handle_new() {
+ ProxyResolverV8* proxyResolver = new ProxyResolverV8(ProxyResolverJSBindings::CreateDefault());
+ return reinterpret_cast<ProxyResolverV8Handle*>(proxyResolver);
+}
+
+char16_t* ProxyResolverV8Handle_GetProxyForURL(ProxyResolverV8Handle* handle,
+ const char16_t* spec,
+ const char16_t* host) {
+ ProxyResolverV8* proxyResolver = reinterpret_cast<ProxyResolverV8*>(handle);
+ std::u16string specStr(spec);
+ std::u16string hostStr(host);
+ std::u16string proxies;
+ int code = proxyResolver->GetProxyForURL(specStr, hostStr, &proxies);
+ if (code != OK) {
+ return NULL;
+ }
+ auto len = proxies.length();
+ char16_t* result = (char16_t*) malloc(sizeof(char16_t) * (len + 1));
+ if (result == 0) { // Failed to allocate
+ return NULL;
+ }
+ proxies.copy(result, len);
+ result[len] = u'\0';
+ return result;
+}
+
+int ProxyResolverV8Handle_SetPacScript(ProxyResolverV8Handle* handle,
+ const char16_t* script_data) {
+ ProxyResolverV8* proxyResolver = reinterpret_cast<ProxyResolverV8*>(handle);
+ std::u16string script(script_data);
+ return proxyResolver->SetPacScript(script);
+}
+
+void ProxyResolverV8Handle_delete(ProxyResolverV8Handle* handle) {
+ ProxyResolverV8* proxyResolver = reinterpret_cast<ProxyResolverV8*>(handle);
+ delete proxyResolver;
+}
+
+} // extern "C"
\ No newline at end of file
diff --git a/test/Android.bp b/test/Android.bp
index 24f2ddc..656dfaa 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -3,6 +3,8 @@
srcs: ["proxy_resolver_v8_unittest.cc"],
+ include_dirs: ["external/chromium-libpac/src"],
+
cflags: [
"-Wno-endif-labels",
"-Wno-import",
diff --git a/test/jstocstring.pl b/test/jstocstring.pl
index 7b50772..eade2b8 100755
--- a/test/jstocstring.pl
+++ b/test/jstocstring.pl
@@ -15,6 +15,7 @@
if (s/\.js/_JS/) {
$upper = uc();
print FILE "#define $upper \\\n";
+ print FILE " u\"\"\\\n";
while (<FH>) {
s/\"/\\\"/g;
chomp();
diff --git a/test/proxy_resolver_v8_unittest.cc b/test/proxy_resolver_v8_unittest.cc
index a13f5e5..b549cda 100644
--- a/test/proxy_resolver_v8_unittest.cc
+++ b/test/proxy_resolver_v8_unittest.cc
@@ -11,9 +11,9 @@
#include "android_runtime/AndroidRuntime.h"
#include "proxy_test_script.h"
+#include "proxy_resolver_v8_wrapper.h"
#include "proxy_resolver_v8.h"
-using namespace android;
namespace net {
namespace {
@@ -49,20 +49,14 @@
return !dns_resolve_ex_result.empty();
}
- virtual void AlertMessage(String16 message) {
- String8 m8(message);
- std::string mstd(m8.string());
-
- ALOGD("PAC-alert: %s\n", mstd.c_str()); // Helpful when debugging.
- alerts.push_back(mstd);
+ virtual void AlertMessage(const std::string& message) {
+ ALOGD("PAC-alert: %s\n", message.c_str()); // Helpful when debugging.
+ alerts.push_back(message);
}
- virtual void ErrorMessage(const String16 message) {
- String8 m8(message);
- std::string mstd(m8.string());
-
- ALOGD("PAC-error: %s\n", mstd.c_str()); // Helpful when debugging.
- errors.push_back(mstd);
+ virtual void ErrorMessage(const std::string& message) {
+ ALOGD("PAC-error: %s\n", message.c_str()); // Helpful when debugging.
+ errors.push_back(message);
}
virtual void Shutdown() {}
@@ -100,12 +94,12 @@
};
// Doesn't really matter what these values are for many of the tests.
-const String16 kQueryUrl("http://www.google.com");
-const String16 kQueryHost("www.google.com");
-String16 kResults;
+const std::u16string kQueryUrl(u"http://www.google.com");
+const std::u16string kQueryHost(u"www.google.com");
+std::u16string kResults;
-String16 currentPac;
-#define SCRIPT(x) (currentPac = String16(x))
+std::u16string currentPac;
+#define SCRIPT(x) (currentPac = std::u16string(x))
void addString(std::vector<std::string>* list, std::string str) {
if (str.compare(0, 6, "DIRECT") == 0) {
@@ -117,9 +111,21 @@
}
}
-std::vector<std::string> string16ToProxyList(String16 response) {
+std::unique_ptr<ProxyResolverV8Handle, void(*)(ProxyResolverV8Handle*)> newProxyResolverV8Handle() {
+ return std::unique_ptr<ProxyResolverV8Handle, void(*)(ProxyResolverV8Handle*)>(
+ ProxyResolverV8Handle_new(), &ProxyResolverV8Handle_delete);
+}
+
+std::unique_ptr<char16_t, decltype(&free)> getProxyForURL(ProxyResolverV8Handle* handle,
+ const char16_t* spec,
+ const char16_t* host) {
+ return std::unique_ptr<char16_t, decltype(&free)>(
+ ProxyResolverV8Handle_GetProxyForURL(handle, spec, host), &free);
+}
+
+std::vector<std::string> string16ToProxyList(const std::u16string& response) {
std::vector<std::string> ret;
- String8 response8(response);
+ android::String8 response8(response.data());
std::string rstr(response8.string());
if (rstr.find(';') == std::string::npos) {
addString(&ret, rstr);
@@ -163,6 +169,21 @@
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
}
+TEST(ProxyResolverV8Test, Direct_C_API) {
+ auto handle = newProxyResolverV8Handle();
+ int result = ProxyResolverV8Handle_SetPacScript(handle.get(), DIRECT_JS);
+ EXPECT_EQ(OK, result);
+
+ std::unique_ptr<char16_t, decltype(&free)> result_list = getProxyForURL(
+ handle.get(), kQueryUrl.data(), kQueryHost.data());
+
+ ASSERT_NE(nullptr, result_list.get());
+ kResults = result_list.get();
+ std::vector<std::string> proxies = string16ToProxyList(kResults);
+ EXPECT_EQ(proxies.size(), 1U);
+ EXPECT_EQ("DIRECT",proxies[0]);
+}
+
TEST(ProxyResolverV8Test, ReturnEmptyString) {
ProxyResolverV8WithMockBindings resolver(new MockJSBindings());
int result = resolver.SetPacScript(SCRIPT(RETURN_EMPTY_STRING_JS));
@@ -187,8 +208,8 @@
// arguments into a pseudo-host. The purpose of this test is to verify that
// the correct arguments are being passed to FindProxyForURL().
{
- String16 queryUrl("http://query.com/path");
- String16 queryHost("query.com");
+ std::u16string queryUrl(u"http://query.com/path");
+ std::u16string queryHost(u"query.com");
result = resolver.GetProxyForURL(queryUrl, queryHost, &kResults);
EXPECT_EQ(OK, result);
std::vector<std::string> proxies = string16ToProxyList(kResults);
@@ -196,8 +217,8 @@
EXPECT_EQ("http.query.com.path.query.com", proxies[0]);
}
{
- String16 queryUrl("ftp://query.com:90/path");
- String16 queryHost("query.com");
+ std::u16string queryUrl(u"ftp://query.com:90/path");
+ std::u16string queryHost(u"query.com");
int result = resolver.GetProxyForURL(queryUrl, queryHost, &kResults);
EXPECT_EQ(OK, result);
@@ -219,16 +240,33 @@
resolver.PurgeMemory();
}
+TEST(ProxyResolverV8Test, Basic_C_API) {
+ auto handle = newProxyResolverV8Handle();
+ int result = ProxyResolverV8Handle_SetPacScript(handle.get(), PASSTHROUGH_JS);
+ EXPECT_EQ(OK, result);
+
+ // The "FindProxyForURL" of this PAC script simply concatenates all of the
+ // arguments into a pseudo-host. The purpose of this test is to verify that
+ // the correct arguments are being passed to FindProxyForURL().
+ std::unique_ptr<char16_t, decltype(&free)> result_list = getProxyForURL(
+ handle.get(), u"http://query.com/path", u"query.com");
+ ASSERT_NE(nullptr, result_list.get());
+ kResults = result_list.get();
+ std::vector<std::string> proxies = string16ToProxyList(kResults);
+ EXPECT_EQ(1U, proxies.size());
+ EXPECT_EQ("http.query.com.path.query.com", proxies[0]);
+}
+
TEST(ProxyResolverV8Test, BadReturnType) {
// These are the files of PAC scripts which each return a non-string
// types for FindProxyForURL(). They should all fail with
// ERR_PAC_SCRIPT_FAILED.
- static const String16 files[] = {
- String16(RETURN_UNDEFINED_JS),
- String16(RETURN_INTEGER_JS),
- String16(RETURN_FUNCTION_JS),
- String16(RETURN_OBJECT_JS),
- String16(RETURN_NULL_JS)
+ static const std::u16string files[] = {
+ std::u16string(RETURN_UNDEFINED_JS),
+ std::u16string(RETURN_INTEGER_JS),
+ std::u16string(RETURN_FUNCTION_JS),
+ std::u16string(RETURN_OBJECT_JS),
+ std::u16string(RETURN_NULL_JS)
};
for (size_t i = 0; i < 5; ++i) {
@@ -273,10 +311,20 @@
EXPECT_EQ(0U, bindings->alerts.size());
// We get one error during compilation.
- ASSERT_EQ(1U, bindings->errors.size());
+ ASSERT_EQ(2U, bindings->errors.size());
EXPECT_EQ("Uncaught SyntaxError: Unexpected end of input",
bindings->errors[0]);
+ EXPECT_EQ("Context is null.", bindings->errors[1]);
+}
+
+TEST(ProxyResolverV8Test, ParseError_C_API) {
+ auto handle = newProxyResolverV8Handle();
+ int result = ProxyResolverV8Handle_SetPacScript(handle.get(), MISSING_CLOSE_BRACE_JS);
+ EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
+ std::unique_ptr<char16_t, decltype(&free)> result_list = getProxyForURL(
+ handle.get(), u"http://query.com/path", u"query.com");
+ EXPECT_EQ(nullptr, result_list.get());
}
// Run a PAC script several times, which has side-effects.
@@ -366,6 +414,9 @@
// Resolve should fail, as we are not yet initialized with a script.
int result = resolver.GetProxyForURL(kQueryUrl, kQueryHost, &kResults);
EXPECT_EQ(ERR_FAILED, result);
+ EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
+ EXPECT_EQ(1U, resolver.mock_js_bindings()->errors.size());
+ EXPECT_EQ("Context is null.", resolver.mock_js_bindings()->errors[0]);
// Initialize it.
result = resolver.SetPacScript(SCRIPT(DIRECT_JS));
@@ -382,6 +433,10 @@
result = resolver.GetProxyForURL(kQueryUrl, kQueryHost, &kResults);
EXPECT_EQ(ERR_FAILED, result);
+ EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
+ EXPECT_EQ(2U, resolver.mock_js_bindings()->errors.size());
+ EXPECT_EQ("Context is null.", resolver.mock_js_bindings()->errors[1]);
+
// Load a good script once more.
result = resolver.SetPacScript(SCRIPT(DIRECT_JS));
EXPECT_EQ(OK, result);
@@ -389,7 +444,7 @@
EXPECT_EQ(OK, result);
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
- EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
+ EXPECT_EQ(2U, resolver.mock_js_bindings()->errors.size());
}
// Test marshalling/un-marshalling of values between C++/V8.
@@ -522,7 +577,7 @@
TEST(ProxyResolverV8Test, DNSResolutionOfInternationDomainName) {
return;
ProxyResolverV8WithMockBindings resolver(new MockJSBindings());
- int result = resolver.SetPacScript(String16(INTERNATIONAL_DOMAIN_NAMES_JS));
+ int result = resolver.SetPacScript(SCRIPT(INTERNATIONAL_DOMAIN_NAMES_JS));
EXPECT_EQ(OK, result);
// Execute FindProxyForURL().
@@ -560,5 +615,19 @@
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
}
+TEST(ProxyResolverV8Test, GetterChangesElementKind) {
+ ProxyResolverV8WithMockBindings resolver(new MockJSBindings());
+ int result = resolver.SetPacScript(SCRIPT(CHANGE_ELEMENT_KIND_JS));
+ EXPECT_EQ(OK, result);
+
+ // Execute FindProxyForURL().
+ result = resolver.GetProxyForURL(kQueryUrl, kQueryHost, &kResults);
+
+ EXPECT_EQ(OK, result);
+ std::vector<std::string> proxies = string16ToProxyList(kResults);
+ EXPECT_EQ(1U, proxies.size());
+ EXPECT_EQ("DIRECT", proxies[0]);
+}
+
} // namespace
} // namespace net
diff --git a/test/proxy_test_script.h b/test/proxy_test_script.h
index bfd953a..092e262 100644
--- a/test/proxy_test_script.h
+++ b/test/proxy_test_script.h
@@ -5,6 +5,7 @@
#define PROXY_TEST_SCRIPT_H_
#define BINDING_FROM_GLOBAL_JS \
+ u""\
"// Calls a bindings outside of FindProxyForURL(). This causes the code to\n" \
"// get exercised during initialization.\n" \
"\n" \
@@ -15,6 +16,7 @@
"}\n" \
#define BINDINGS_JS \
+ u""\
"// Try calling the browser-side bound functions with varying (invalid)\n" \
"// inputs. There is no notion of \"success\" for this test, other than\n" \
"// verifying the correct C++ bindings were reached with expected values.\n" \
@@ -79,8 +81,9 @@
"\n" \
#define CHANGE_ELEMENT_KIND_JS \
+ u""\
"// PAC script with getter that changes element kind.\n" \
- " \n" \
+ "\n" \
"function FindProxyForURL(url, host) {\n" \
" let arr = [];\n" \
" arr[1000] = 0x1234;\n" \
@@ -91,17 +94,19 @@
" });\n" \
"\n" \
" let results = Object.entries(arr);\n" \
- " let str = results.toString(); \n" \
+ " let str = results.toString();\n" \
" return \"DIRECT\";\n" \
"}\n" \
#define DIRECT_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return \"DIRECT\";\n" \
"}\n" \
"\n" \
#define DNS_FAIL_JS \
+ u""\
"// This script should be run in an environment where all DNS resolution are\n" \
"// failing. It tests that functions return the expected values.\n" \
"//\n" \
@@ -131,6 +136,7 @@
"\n" \
#define ENDS_WITH_COMMENT_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return \"PROXY success:80\";\n" \
"}\n" \
@@ -141,11 +147,13 @@
"// those extra functions was being considered part of the comment.\n" \
#define ENDS_WITH_STATEMENT_NO_SEMICOLON_JS \
+ u""\
"// Ends with a statement, and no terminal newline.\n" \
"function FindProxyForURL(url, host) { return \"PROXY success:\" + x; }\n" \
"x = 3\n" \
#define INTERNATIONAL_DOMAIN_NAMES_JS \
+ u""\
"// Try resolving hostnames containing non-ASCII characters.\n" \
"\n" \
"function FindProxyForURL(url, host) {\n" \
@@ -164,6 +172,7 @@
"\n" \
#define MISSING_CLOSE_BRACE_JS \
+ u""\
"// This PAC script is invalid, because there is a missing close brace\n" \
"// on the function FindProxyForURL().\n" \
"\n" \
@@ -172,10 +181,12 @@
"\n" \
#define NO_ENTRYPOINT_JS \
+ u""\
"var x = \"This is an invalid PAC script because it lacks a \" +\n" \
" \"FindProxyForURL() function\";\n" \
#define PAC_LIBRARY_UNITTEST_JS \
+ u""\
"// This should output \"PROXY success:80\" if all the tests pass.\n" \
"// Otherwise it will output \"PROXY failure:<num-failures>\".\n" \
"//\n" \
@@ -544,6 +555,7 @@
"\n" \
#define PASSTHROUGH_JS \
+ u""\
"// Return a single-proxy result, which encodes ALL the arguments that were\n" \
"// passed to FindProxyForURL().\n" \
"\n" \
@@ -591,48 +603,56 @@
"}\n" \
#define RETURN_EMPTY_STRING_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return \"\";\n" \
"}\n" \
"\n" \
#define RETURN_FUNCTION_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return FindProxyForURL;\n" \
"}\n" \
"\n" \
#define RETURN_INTEGER_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return 0;\n" \
"}\n" \
"\n" \
#define RETURN_NULL_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return null;\n" \
"}\n" \
"\n" \
#define RETURN_OBJECT_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return {result: \"PROXY foo\"};\n" \
"}\n" \
"\n" \
#define RETURN_UNDEFINED_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return undefined;\n" \
"}\n" \
"\n" \
#define RETURN_UNICODE_JS \
+ u""\
"// U+200B is the codepoint for zero-width-space.\n" \
"function FindProxyForURL(url, host) {\n" \
" return \"PROXY foo.com\u200B\";\n" \
"}\n" \
#define SIDE_EFFECTS_JS \
+ u""\
"if (!gCounter) {\n" \
" // We write it this way so if the script gets loaded twice,\n" \
" // gCounter remains dirty.\n" \
@@ -645,6 +665,7 @@
"\n" \
#define SIMPLE_JS \
+ u""\
"// PAC script which uses isInNet on both IP addresses and hosts, and calls\n" \
"// isResolvable().\n" \
"\n" \
@@ -668,12 +689,13 @@
"}\n" \
#define STRING_FUNCTIONS_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" return \"direct\".toUpperCase();\n" \
"}\n" \
- "\n" \
#define UNHANDLED_EXCEPTION_JS \
+ u""\
"function FindProxyForURL(url, host) {\n" \
" // This will throw a runtime exception.\n" \
" return \"PROXY x\" + undefined_variable;\n" \