blob: e7d8d1c5451cd2bbf456bf9d0c85c62f37151889 [file] [log] [blame]
// Copyright (c) 2010 The Chromium OS 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 "entd/utils.h"
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <wordexp.h>
#include <iostream>
#include <base/basictypes.h>
#include <base/file_util.h>
#include <base/logging.h>
namespace entd {
namespace utils {
void* malloc(size_t size) {
void* rv = ::malloc(size);
if (!rv)
exit(2);
return rv;
}
void free(void *buf) {
::free(buf);
}
// Extracts a C string from a V8 Utf8Value.
const char* ToCString(const v8::String::Utf8Value& value) {
return *value ? *value : "<string conversion failed>";
}
bool CheckHostnameCharset(const std::string& str) {
for (std::string::const_iterator i = str.begin(); i < str.end(); ++i) {
if (!(isalnum(*i) || *i == '.' || *i == '-')) {
return false;
}
}
return true;
}
// Reads a file into a v8 string.
v8::Handle<v8::String> ReadFile(const std::string& name) {
std::string filestr;
v8::Handle<v8::String> result;
if (file_util::ReadFileToString(FilePath(name), &filestr))
result = v8::String::New(filestr.c_str(), filestr.size());
return result;
}
std::vector<std::string> ReadDirectory(const std::string& path) {
std::vector<std::string> dirnames;
DIR *dirp = opendir(path.c_str());
if (dirp == NULL) {
LOG(WARNING) << "Unable to open directory: " << path;
return dirnames;
}
while (1) {
struct dirent *direntp = readdir(dirp);
if (direntp == NULL)
break;
std::string dirname(direntp->d_name);
if (dirname == "." || dirname == "..")
continue;
dirnames.push_back(dirname);
}
closedir(dirp);
return dirnames;
}
std::string ExpandFilePath(const std::string& path) {
std::string res;
wordexp_t path_exp;
wordexp(path.c_str(), &path_exp, 0);
if (path_exp.we_wordc > 0) {
res = std::string(path_exp.we_wordv[0]);
} else {
res = path;
}
wordfree(&path_exp);
return res;
}
std::string ValueAsUtf8String(v8::Handle<v8::Value> value) {
v8::Local<v8::String> s = value->ToString();
return std::string(*v8::String::Utf8Value(s));
}
std::string GetPropertyAsString(v8::Handle<v8::Object> obj,
const std::string& name) {
std::string res;
v8::Handle<v8::String> jsname = v8::String::New(name.c_str());
if (obj->Has(jsname)) {
res = ValueAsUtf8String(obj->Get(jsname));
}
return res;
}
// "delim" only applies to object properties; it is ignored for Arrays
StringList GetPropertyAsStringList(v8::Handle<v8::Object> obj,
const std::string& name,
const std::string& delim) {
StringList result;
v8::Handle<v8::String> jsname = v8::String::New(name.c_str());
if (obj->Has(jsname)) {
v8::Local<v8::Value> jsvalue = obj->Get(jsname);
if (jsvalue->IsArray()) {
v8::Local<v8::Array> jsarray =
v8::Local<v8::Array>::Cast(obj->Get(jsname));
for (size_t i = 0; i < jsarray->Length(); i++) {
std::string s = ValueAsUtf8String(jsarray->Get(i));
result.push_back(s);
}
} else if (jsvalue->IsObject()) {
v8::Local<v8::Object> paramobj =
v8::Local<v8::Object>::Cast(obj->Get(jsname));
v8::Local<v8::Array> props = paramobj->GetPropertyNames();
for (size_t i = 0; i < props->Length(); ++i) {
v8::Handle<v8::Value> propname = props->Get(i);
std::string name = ValueAsUtf8String(propname);
std::string value = ValueAsUtf8String(paramobj->Get(propname));
std::string s = name + delim + value;
result.push_back(s);
}
}
}
return result;
}
v8::Handle<v8::Value> ThrowV8Exception(const std::string& err) {
ThrowException(v8::String::New(err.c_str()));
return v8::Undefined();
}
void ReportV8Exception(v8::TryCatch* try_catch) {
v8::HandleScope handle_scope;
v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = utils::ToCString(exception);
v8::Handle<v8::Message> message = try_catch->Message();
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
LOG(ERROR) << "V8 Exception: " << exception_string << '\n';
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(message->GetScriptResourceName());
const char* filename_string = utils::ToCString(filename);
int linenum = message->GetLineNumber();
LOG(ERROR) << "V8 Exception: " << filename_string << ':' << linenum <<
": " << exception_string;
// Print line of source code.
v8::String::Utf8Value sourceline(message->GetSourceLine());
const char* sourceline_string = utils::ToCString(sourceline);
LOG(ERROR) << sourceline_string;
}
}
// Note: This assumes it is not getting called from inside a JS
// stack (current use cases), so it users LOG(ERROR)
// instead of ThrowException
// If called from a JS stack, the caller should throw an
// exception if this returns an empty handle.
v8::Handle<v8::Value> CallV8Function(v8::Handle<v8::Object> obj,
const std::string& cb_name,
int argc, v8::Handle<v8::Value> argv[]) {
if (obj.IsEmpty() || !obj->IsObject()) {
LOG(ERROR) << "Invalid object when trying to call: " << cb_name;
return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> cb = obj->Get(v8::String::New(cb_name.c_str()));
if (cb->IsUndefined()) {
LOG(ERROR) << "Object does not have property: "<< cb_name;
return v8::Handle<v8::Value>();
}
if (!cb->IsFunction()) {
LOG(ERROR) << "Property is not a function: " << cb_name;
return v8::Handle<v8::Value>();
}
return v8::Handle<v8::Function>::Cast(cb)->Call(obj, argc, argv);
}
} // namespace utils
} // namespace entd