#include "native_handler.h" #include "include/cef_base.h" #include "client_handler.h" #include #include #include #include #include #include #include #include #include #include using namespace std; NativeHandler::NativeHandler() : CefV8Handler() { object = CefV8Value::CreateObject(NULL, NULL); const char *functionNames[] = { "exists", "alert", "read", "write", "absolute", "list", "isFile", "isDirectory", "remove", "asyncList", "open", "openDialog", "quit", "writeToPasteboard", "readFromPasteboard", "showDevTools", "newWindow", "saveDialog", "exit", "watchPath", "unwatchPath", "makeDirectory", "move", "moveToTrash" }; int arrayLength = sizeof(functionNames) / sizeof(const char *); for (int i = 0; i < arrayLength; i++) { const char *functionName = functionNames[i]; CefRefPtr function = CefV8Value::CreateFunction( functionName, this); object->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE); } } void NativeHandler::Exists(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); struct stat statInfo; int result = stat(path.c_str(), &statInfo); retval = CefV8Value::CreateBool(result == 0); } void NativeHandler::Read(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); int fd = open(path.c_str(), O_RDONLY); if (fd < 0) return; char buffer[8192]; int r; string value; while ((r = read(fd, buffer, sizeof buffer)) > 0) value.append(buffer, 0, r); close(fd); retval = CefV8Value::CreateString(value); } void NativeHandler::Absolute(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); string relativePath; if (path[0] != '~') relativePath.append(path); else { relativePath.append(getenv("HOME")); relativePath.append(path, 1, path.length() - 1); } vector < string > segments; char allSegments[relativePath.length() + 1]; strcpy(allSegments, relativePath.c_str()); const char* segment; for (segment = strtok(allSegments, "/"); segment; segment = strtok(NULL, "/")) { if (strcmp(segment, ".") == 0) continue; if (strcmp(segment, "..") == 0) { if (segments.empty()) { retval = CefV8Value::CreateString("/"); return; } segments.pop_back(); } else segments.push_back(segment); } string absolutePath; unsigned int i; for (i = 0; i < segments.size(); i++) { absolutePath.append("/"); absolutePath.append(segments.at(i)); } retval = CefV8Value::CreateString(absolutePath); } void ListDirectory(string path, vector* paths, bool recursive) { dirent **children; int childrenCount = scandir(path.c_str(), &children, 0, alphasort); struct stat statInfo; int result; for (int i = 0; i < childrenCount; i++) { if (strcmp(children[i]->d_name, ".") == 0 || strcmp(children[i]->d_name, "..") == 0) { free(children[i]); continue; } string entryPath(path + "/" + children[i]->d_name); paths->push_back(entryPath); if (recursive) { result = stat(entryPath.c_str(), &statInfo); if (result == 0 && S_ISDIR(statInfo.st_mode)) ListDirectory(entryPath, paths, recursive); } free(children[i]); } free(children); } void DeleteContents(string path) { dirent **children; const char* dirPath = path.c_str(); int childrenCount = scandir(dirPath, &children, 0, alphasort); struct stat statInfo; for (int i = 0; i < childrenCount; i++) { if (strcmp(children[i]->d_name, ".") == 0 || strcmp(children[i]->d_name, "..") == 0) { free(children[i]); continue; } string entryPath(path + "/" + children[i]->d_name); if (stat(entryPath.c_str(), &statInfo) != 0) { free(children[i]); continue; } if (S_ISDIR(statInfo.st_mode)) DeleteContents(entryPath); else if (S_ISREG(statInfo.st_mode)) remove(entryPath.c_str()); } free(children); rmdir(dirPath); } void NativeHandler::List(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); bool recursive = arguments[1]->GetBoolValue(); vector < string > *paths = new vector; ListDirectory(path, paths, recursive); retval = CefV8Value::CreateArray(); for (uint i = 0; i < paths->size(); i++) retval->SetValue(i, CefV8Value::CreateString(paths->at(i))); free (paths); } void NativeHandler::IsFile(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); struct stat statInfo; int result = stat(path.c_str(), &statInfo); retval = CefV8Value::CreateBool(result == 0 && S_ISREG(statInfo.st_mode)); } void NativeHandler::IsDirectory(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); struct stat statInfo; int result = stat(path.c_str(), &statInfo); retval = CefV8Value::CreateBool(result == 0 && S_ISDIR(statInfo.st_mode)); } void NativeHandler::OpenDialog(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { char *filename; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); retval = CefV8Value::CreateString(filename); g_free(filename); } else retval = CefV8Value::CreateNull(); gtk_widget_destroy(dialog); } void NativeHandler::Open(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { path = arguments[0]->GetStringValue().ToString(); CefV8Context::GetCurrentContext()->GetBrowser()->Reload(); } void NativeHandler::Write(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); string content = arguments[1]->GetStringValue().ToString(); ofstream myfile; myfile.open(path.c_str()); myfile << content; myfile.close(); } void NativeHandler::WriteToPasteboard(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string content = arguments[0]->GetStringValue().ToString(); GtkClipboard* clipboard = gtk_clipboard_get_for_display( gdk_display_get_default(), GDK_NONE); gtk_clipboard_set_text(clipboard, content.c_str(), content.length()); gtk_clipboard_store(clipboard); } void NativeHandler::ReadFromPasteboard(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { GtkClipboard* clipboard = gtk_clipboard_get_for_display( gdk_display_get_default(), GDK_NONE); char* content = gtk_clipboard_wait_for_text(clipboard); retval = CefV8Value::CreateString(content); } void NativeHandler::AsyncList(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string path = arguments[0]->GetStringValue().ToString(); bool recursive = arguments[1]->GetBoolValue(); vector < string > *paths = new vector; ListDirectory(path, paths, recursive); CefRefPtr callbackPaths = CefV8Value::CreateArray(); for (uint i = 0; i < paths->size(); i++) callbackPaths->SetValue(i, CefV8Value::CreateString(paths->at(i))); CefV8ValueList args; args.push_back(callbackPaths); CefRefPtr e; arguments[2]->ExecuteFunction(arguments[2], args, retval, e, true); if (e) exception = e->GetMessage(); free (paths); } void NativeHandler::MakeDirectory(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string content = arguments[0]->GetStringValue().ToString(); mkdir(content.c_str(), S_IRWXU); } void NativeHandler::Move(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string from = arguments[0]->GetStringValue().ToString(); string to = arguments[1]->GetStringValue().ToString(); rename(from.c_str(), to.c_str()); } void NativeHandler::Remove(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { string pathArgument = arguments[0]->GetStringValue().ToString(); const char* path = pathArgument.c_str(); struct stat statInfo; if (stat(path, &statInfo) != 0) return; if (S_ISREG(statInfo.st_mode)) remove(path); else if (S_ISDIR(statInfo.st_mode)) DeleteContents(pathArgument); } void NativeHandler::Alert(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { CefRefPtr buttonNamesAndCallbacks; if (arguments.size() < 3) buttonNamesAndCallbacks = CefV8Value::CreateArray(); else buttonNamesAndCallbacks = arguments[2]; GtkWidget *dialog; dialog = gtk_dialog_new_with_buttons("atom", GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, NULL); for (int i = 0; i < buttonNamesAndCallbacks->GetArrayLength(); i++) { string title = buttonNamesAndCallbacks->GetValue(i)->GetValue(0)->GetStringValue().ToString(); gtk_dialog_add_button(GTK_DIALOG(dialog), title.c_str(), i); } gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); string dialogMessage(arguments[0]->GetStringValue().ToString()); dialogMessage.append("\n\n"); dialogMessage.append(arguments[1]->GetStringValue().ToString()); GtkWidget *label; label = gtk_label_new(dialogMessage.c_str()); GtkWidget *contentArea; contentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); gtk_container_add(GTK_CONTAINER(contentArea), label); gtk_widget_show_all(dialog); int result = gtk_dialog_run(GTK_DIALOG(dialog)); if (result >= 0) { CefRefPtr callback = buttonNamesAndCallbacks->GetValue( result)->GetValue(1); CefV8ValueList args; CefRefPtr e; callback->ExecuteFunction(callback, args, retval, e, true); if (e) exception = e->GetMessage(); } gtk_widget_destroy(dialog); } bool NativeHandler::Execute(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { if (name == "exists") Exists(name, object, arguments, retval, exception); else if (name == "read") Read(name, object, arguments, retval, exception); else if (name == "absolute") Absolute(name, object, arguments, retval, exception); else if (name == "list") List(name, object, arguments, retval, exception); else if (name == "isFile") IsFile(name, object, arguments, retval, exception); else if (name == "isDirectory") IsDirectory(name, object, arguments, retval, exception); else if (name == "showDevTools") CefV8Context::GetCurrentContext()->GetBrowser()->ShowDevTools(); else if (name == "openDialog") OpenDialog(name, object, arguments, retval, exception); else if (name == "open") Open(name, object, arguments, retval, exception); else if (name == "write") Write(name, object, arguments, retval, exception); else if (name == "writeToPasteboard") WriteToPasteboard(name, object, arguments, retval, exception); else if (name == "readFromPasteboard") ReadFromPasteboard(name, object, arguments, retval, exception); else if (name == "asyncList") AsyncList(name, object, arguments, retval, exception); else if (name == "makeDirectory") MakeDirectory(name, object, arguments, retval, exception); else if (name == "move") Move(name, object, arguments, retval, exception); else if (name == "remove") Remove(name, object, arguments, retval, exception); else if (name == "alert") Alert(name, object, arguments, retval, exception); else cout << "Unhandled -> " + name.ToString() << " : " << arguments[0]->GetStringValue().ToString() << endl; return true; }