int ShowFolderInOSWindow(ExtensionString pathname) { int error = NO_ERROR; GError *gerror = NULL; gchar *uri = NULL, *parentdir = NULL; if (g_file_test(pathname.c_str(), G_FILE_TEST_IS_DIR)) { uri = g_filename_to_uri(pathname.c_str(), NULL, NULL); if (!gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &gerror)) { error = ConvertGnomeErrorCode(gerror); g_warning("%s", gerror->message); g_error_free(gerror); } g_free(uri); } else { if (!FileManager1_ShowItems(pathname.c_str())) { // Fall back to using gtk_show_uri on the dirname (without highlighting the file) parentdir = g_path_get_dirname(pathname.c_str()); uri = g_filename_to_uri(parentdir, NULL, NULL); if (!gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &gerror)) { error = ConvertGnomeErrorCode(gerror); g_warning("%s", gerror->message); g_error_free(gerror); } g_free(parentdir); g_free(uri); } } return error; }
int32 ShowOpenDialog(bool allowMultipleSelection, bool chooseDirectory, ExtensionString title, ExtensionString initialDirectory, ExtensionString fileTypes, CefRefPtr<CefListValue>& selectedFiles) { GtkWidget *dialog; GtkFileChooserAction file_or_directory = chooseDirectory ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : GTK_FILE_CHOOSER_ACTION_OPEN ; dialog = gtk_file_chooser_dialog_new (title.c_str(), NULL, file_or_directory, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if (!initialDirectory.empty()) { ExtensionString folderURI = std::string("file:///") + initialDirectory; gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), folderURI.c_str()); } if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { char *filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); selectedFiles->SetString(0,filename); g_free (filename); } gtk_widget_destroy (dialog); return NO_ERROR; }
int32 ShowSaveDialog(ExtensionString title, ExtensionString initialDirectory, ExtensionString proposedNewFilename, ExtensionString& newFilePath) { GtkWidget *openSaveDialog; openSaveDialog = gtk_file_chooser_dialog_new(title.c_str(), NULL, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (openSaveDialog), TRUE); if (!initialDirectory.empty()) { gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (openSaveDialog), proposedNewFilename.c_str()); ExtensionString folderURI = std::string("file:///") + initialDirectory; gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (openSaveDialog), folderURI.c_str()); } if (gtk_dialog_run (GTK_DIALOG (openSaveDialog)) == GTK_RESPONSE_ACCEPT) { char* filePath; filePath = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (openSaveDialog)); newFilePath = filePath; g_free (filePath); } gtk_widget_destroy (openSaveDialog); return NO_ERROR; }
int Rename(ExtensionString oldName, ExtensionString newName) { const char *newNameStr = newName.c_str(); if (g_file_test(newNameStr, G_FILE_TEST_EXISTS)) { return ERR_FILE_EXISTS; } if (rename(oldName.c_str(), newNameStr) == -1) { return ConvertLinuxErrorCode(errno); } }
int32 DeleteFileOrDirectory(ExtensionString filename) { DWORD dwAttr = GetFileAttributes(filename.c_str()); if (dwAttr == INVALID_FILE_ATTRIBUTES) return ERR_NOT_FOUND; if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0) return ERR_NOT_FILE; if (!DeleteFile(filename.c_str())) return ConvertWinErrorCode(GetLastError()); return NO_ERROR; }
int32 OpenURLInDefaultBrowser(ExtensionString url) { GError* error = NULL; gtk_show_uri(NULL, url.c_str(), GDK_CURRENT_TIME, &error); g_error_free(error); return NO_ERROR; }
int ReadFile(ExtensionString filename, ExtensionString encoding, std::string& contents) { if (encoding != "utf8") { return ERR_UNSUPPORTED_ENCODING; } int error = NO_ERROR; GError *gerror = NULL; gchar *file_get_contents = NULL; gsize len = 0; if (!g_file_get_contents(filename.c_str(), &file_get_contents, &len, &gerror)) { error = GErrorToErrorCode(gerror); if (error == ERR_NOT_FILE) { error = ERR_CANT_READ; } } else { if (has_utf16_32_BOM(file_get_contents, len)) { error = ERR_UNSUPPORTED_ENCODING; } else if (has_utf8_BOM(file_get_contents, len)) { contents.assign(file_get_contents + utf8_BOM_Len, len); } else if (!g_locale_to_utf8(file_get_contents, -1, NULL, NULL, &gerror)) { error = ERR_UNSUPPORTED_ENCODING; } else { contents.assign(file_get_contents, len); } g_free(file_get_contents); } return error; }
int32 WriteFile(ExtensionString filename, std::string contents, ExtensionString encoding) { const char *filenameStr = filename.c_str(); int error = NO_ERROR; GError *gerror = NULL; if (encoding != "utf8") { return ERR_UNSUPPORTED_ENCODING; } else if (g_file_test(filenameStr, G_FILE_TEST_EXISTS) && g_access(filenameStr, W_OK) == -1) { return ERR_CANT_WRITE; } FILE* file = fopen(filenameStr, "w"); if (file) { size_t size = fwrite(contents.c_str(), sizeof(gchar), contents.length(), file); if (size != contents.length()) { error = ERR_CANT_WRITE; } fclose(file); } else { return ConvertLinuxErrorCode(errno); } return error; }
int32 CopyFile(ExtensionString src, ExtensionString dest) { int error = NO_ERROR; GFile *source = g_file_new_for_path(src.c_str()); GFile *destination = g_file_new_for_path(dest.c_str()); GError *gerror = NULL; if (!g_file_copy(source, destination, (GFileCopyFlags)(G_FILE_COPY_OVERWRITE|G_FILE_COPY_NOFOLLOW_SYMLINKS|G_FILE_COPY_TARGET_DEFAULT_PERMS), NULL, NULL, NULL, &gerror)) { error = ConvertGnomeErrorCode(gerror); g_error_free(gerror); } g_object_unref(source); g_object_unref(destination); return error; }
int SetPosixPermissions(ExtensionString filename, int32 mode) { if (chmod(filename.c_str(),mode) == -1) { return ConvertLinuxErrorCode(errno); } return NO_ERROR; }
int DeleteFileOrDirectory(ExtensionString filename) { GFile *file = g_file_new_for_path(filename.c_str()); int error = _doDeleteFileOrDirectory(file); g_object_unref(file); return error; }
int32 GetFileModificationTime(ExtensionString filename, uint32& modtime, bool& isDir) { DWORD dwAttr = GetFileAttributes(filename.c_str()); if (dwAttr == INVALID_FILE_ATTRIBUTES) { return ConvertWinErrorCode(GetLastError()); } isDir = ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0); WIN32_FILE_ATTRIBUTE_DATA fad; if (!GetFileAttributesEx(filename.c_str(), GetFileExInfoStandard, &fad)) { return ConvertWinErrorCode(GetLastError()); } modtime = FiletimeToTime(fad.ftLastWriteTime); return NO_ERROR; }
int32 SetPosixPermissions(ExtensionString filename, int32 mode) { DWORD dwAttr = GetFileAttributes(filename.c_str()); if (dwAttr == INVALID_FILE_ATTRIBUTES) return ERR_NOT_FOUND; if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0) return NO_ERROR; bool write = (mode & 0200) != 0; bool read = (mode & 0400) != 0; int mask = (write ? _S_IWRITE : 0) | (read ? _S_IREAD : 0); if (_wchmod(filename.c_str(), mask) == -1) { return ConvertErrnoCode(errno); } return NO_ERROR; }
int32 OpenURLInDefaultBrowser(ExtensionString url) { DWORD result = (DWORD)ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_SHOWNORMAL); // If the result > 32, the function suceeded. If the result is <= 32, it is an // error code. if (result <= 32) return ConvertWinErrorCode(result); return NO_ERROR; }
int32 AddMenuItem(CefRefPtr<CefBrowser> browser, ExtensionString parentCommand, ExtensionString itemTitle, ExtensionString command, ExtensionString key, ExtensionString displayStr, ExtensionString position, ExtensionString relativeId) { GtkWidget* entry = gtk_menu_item_new_with_label(itemTitle.c_str()); g_signal_connect(entry, "activate", FakeCallback, NULL); // FIXME add lookup for menu widgets gtk_menu_shell_append(GTK_MENU_SHELL(_menuWidget), entry); gtk_widget_show(entry); return NO_ERROR; }
int32 ReadFile(ExtensionString filename, ExtensionString encoding, std::string& contents) { if (encoding != L"utf8") return ERR_UNSUPPORTED_ENCODING; DWORD dwAttr; dwAttr = GetFileAttributes(filename.c_str()); if (INVALID_FILE_ATTRIBUTES == dwAttr) return ConvertWinErrorCode(GetLastError()); if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) return ERR_CANT_READ; HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); int32 error = NO_ERROR; if (INVALID_HANDLE_VALUE == hFile) return ConvertWinErrorCode(GetLastError()); DWORD dwFileSize = GetFileSize(hFile, NULL); DWORD dwBytesRead; char* buffer = (char*)malloc(dwFileSize); if (buffer && ReadFile(hFile, buffer, dwFileSize, &dwBytesRead, NULL)) { contents = std::string(buffer, dwFileSize); } else { if (!buffer) error = ERR_UNKNOWN; else error = ConvertWinErrorCode(GetLastError()); } CloseHandle(hFile); if (buffer) free(buffer); return error; }
void MoveFileOrDirectoryToTrash(ExtensionString filename, CefRefPtr<CefBrowser> browser, CefRefPtr<CefProcessMessage> response) { int error = NO_ERROR; GFile *file = g_file_new_for_path(filename.c_str()); GError *gerror = NULL; if (!g_file_trash(file, NULL, &gerror)) { error = ConvertGnomeErrorCode(gerror); g_error_free(gerror); } g_object_unref(file); response->GetArgumentList()->SetInt(1, error); browser->SendProcessMessage(PID_RENDERER, response); }
int32 OpenLiveBrowser(ExtensionString argURL, bool enableRemoteDebugging) { const char *remoteDebuggingFormat = "--no-first-run --no-default-browser-check --allow-file-access-from-files --temp-profile --user-data-dir=%s --remote-debugging-port=9222"; gchar *remoteDebugging; gchar *cmdline; int error = ERR_BROWSER_NOT_INSTALLED; GError *gerror = NULL; if (enableRemoteDebugging) { CefString appSupportDirectory = ClientApp::AppGetSupportDirectory(); // TODO: (INGO) to better understand to string conversion issue, I need a consultant // here. Getting the char* from CefString I had to call ToString().c_str() // Calling only c_str() didn't return anything. gchar *userDataDir = g_strdup_printf("%s/live-dev-profile", appSupportDirectory.ToString().c_str()); g_message("USERDATADIR= %s", userDataDir); remoteDebugging = g_strdup_printf(remoteDebuggingFormat, userDataDir); g_free(userDataDir); } else { remoteDebugging = g_strdup(""); } // check for supported browsers (in PATH directories) for (size_t i = 0; i < sizeof(browsers) / sizeof(browsers[0]); i++) { cmdline = g_strdup_printf("%s %s %s", browsers[i].c_str(), argURL.c_str(), remoteDebugging); if (g_spawn_command_line_async(cmdline, &gerror)) { // browser is found in os; stop iterating error = NO_ERROR; } else { error = ConvertGnomeErrorCode(gerror); } g_free(cmdline); if (error == NO_ERROR) { break; } else { g_error_free(gerror); gerror = NULL; } } g_free(remoteDebugging); return error; }
int ShowFolderInOSWindow(ExtensionString pathname) { int error = NO_ERROR; GError *gerror = NULL; gchar *uri = g_strdup_printf("file://%s", pathname.c_str()); if (!gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &gerror)) { error = ConvertGnomeErrorCode(gerror); g_warning("%s", gerror->message); g_error_free(gerror); } g_free(uri); return error; }
int GetFileInfo(ExtensionString filename, uint32& modtime, bool& isDir, double& size, ExtensionString& realPath) { struct stat buf; if(stat(filename.c_str(),&buf)==-1) return ConvertLinuxErrorCode(errno); modtime = buf.st_mtime; isDir = S_ISDIR(buf.st_mode); size = (double)buf.st_size; // TODO: Implement realPath. If "filename" is a symlink, realPath should be the actual path // to the linked object. realPath = ""; return NO_ERROR; }
int32 ReadDir(ExtensionString path, CefRefPtr<CefListValue>& directoryContents) { if (path.length() && path[path.length() - 1] != '/') path += '/'; path += '*'; WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(path.c_str(), &ffd); std::vector<ExtensionString> resultFiles; std::vector<ExtensionString> resultDirs; if (hFind != INVALID_HANDLE_VALUE) { do { // Ignore '.' and '..' if (!wcscmp(ffd.cFileName, L".") || !wcscmp(ffd.cFileName, L"..")) continue; // Collect file and directory names separately if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { resultDirs.push_back(ExtensionString(ffd.cFileName)); } else { resultFiles.push_back(ExtensionString(ffd.cFileName)); } } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); } else { return ConvertWinErrorCode(GetLastError()); } // On Windows, list directories first, then files size_t i, total = 0; for (i = 0; i < resultDirs.size(); i++) directoryContents->SetString(total++, resultDirs[i]); for (i = 0; i < resultFiles.size(); i++) directoryContents->SetString(total++, resultFiles[i]); return NO_ERROR; }
int32 WriteFile(ExtensionString filename, std::string contents, ExtensionString encoding) { if (encoding != L"utf8") return ERR_UNSUPPORTED_ENCODING; HANDLE hFile = CreateFile(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwBytesWritten; int error = NO_ERROR; if (INVALID_HANDLE_VALUE == hFile) return ConvertWinErrorCode(GetLastError(), false); // TODO (issue 67) - Should write to temp file and handle encoding if (!WriteFile(hFile, contents.c_str(), contents.length(), &dwBytesWritten, NULL)) { error = ConvertWinErrorCode(GetLastError(), false); } CloseHandle(hFile); return error; }
int32 MakeDir(ExtensionString path, int mode) { const char *pathStr = path.c_str(); GFile *file; GError *gerror = NULL; int32 error = NO_ERROR; if (g_file_test(pathStr, G_FILE_TEST_EXISTS)) { return ERR_FILE_EXISTS; } file = g_file_new_for_path(pathStr); mode = mode | 0777; if (!g_file_make_directory(file, NULL, &gerror)) { error = GErrorToErrorCode(gerror); } g_object_unref(file); return error; }
int32 AddMenu(CefRefPtr<CefBrowser> browser, ExtensionString title, ExtensionString command, ExtensionString position, ExtensionString relativeId) { // if (tag == kTagNotFound) { // tag = NativeMenuModel::getInstance(getMenuParent(browser)).getOrCreateTag(command, ExtensionString()); // } else { // // menu already there // return NO_ERROR; // } GtkWidget* menuBar = GetMenuBar(browser); GtkWidget* menuWidget = gtk_menu_new(); GtkWidget* menuHeader = gtk_menu_item_new_with_label(title.c_str()); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuHeader), menuWidget); gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), menuHeader); gtk_widget_show(menuHeader); // FIXME add lookup for menu widgets _menuWidget = menuWidget; return NO_ERROR; }
int32 ShowFolderInOSWindow(ExtensionString pathname) { ShellExecute(NULL, L"open", pathname.c_str(), NULL, NULL, SW_SHOWDEFAULT); return NO_ERROR; }
int32 ShowOpenDialog(bool allowMultipleSelection, bool chooseDirectory, ExtensionString title, ExtensionString initialDirectory, ExtensionString fileTypes, CefRefPtr<CefListValue>& selectedFiles) { wchar_t szFile[MAX_PATH]; szFile[0] = 0; // TODO (issue #64) - This method should be using IFileDialog instead of the /* outdated SHGetPathFromIDList and GetOpenFileName. Useful function to parse fileTypesStr: template<class T> int inline findAndReplaceString(T& source, const T& find, const T& replace) { int num=0; int fLen = find.size(); int rLen = replace.size(); for (int pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen) { num++; source.replace(pos, fLen, replace); } return num; } */ // SHBrowseForFolder can handle Windows path only, not Unix path. // ofn.lpstrInitialDir also needs Windows path on XP and not Unix path. ConvertToNativePath(initialDirectory); if (chooseDirectory) { BROWSEINFO bi = {0}; bi.hwndOwner = GetActiveWindow(); bi.lpszTitle = title.c_str(); bi.ulFlags = BIF_NEWDIALOGSTYLE; bi.lpfn = SetInitialPathCallback; bi.lParam = (LPARAM)initialDirectory.c_str(); LPITEMIDLIST pidl = SHBrowseForFolder(&bi); if (pidl != 0) { if (SHGetPathFromIDList(pidl, szFile)) { // Add directory path to the result ExtensionString pathName(szFile); ConvertToUnixPath(pathName); selectedFiles->SetString(0, pathName); } IMalloc* pMalloc = NULL; SHGetMalloc(&pMalloc); if (pMalloc) { pMalloc->Free(pidl); pMalloc->Release(); } } } else { OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.hwndOwner = GetActiveWindow(); ofn.lStructSize = sizeof(ofn); ofn.lpstrFile = szFile; ofn.nMaxFile = MAX_PATH; // TODO (issue #65) - Use passed in file types. Note, when fileTypesStr is null, all files should be shown /* findAndReplaceString( fileTypesStr, std::string(" "), std::string(";*.")); LPCWSTR allFilesFilter = L"All Files\0*.*\0\0";*/ ofn.lpstrFilter = L"All Files\0*.*\0Web Files\0*.js;*.css;*.htm;*.html\0\0"; ofn.lpstrInitialDir = initialDirectory.c_str(); ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER; if (allowMultipleSelection) ofn.Flags |= OFN_ALLOWMULTISELECT; if (GetOpenFileName(&ofn)) { if (allowMultipleSelection) { // Multiple selection encodes the files differently // If multiple files are selected, the first null terminator // signals end of directory that the files are all in std::wstring dir(szFile); // Check for two null terminators, which signal that only one file // was selected if (szFile[dir.length() + 1] == '\0') { ExtensionString filePath(dir); ConvertToUnixPath(filePath); selectedFiles->SetString(0, filePath); } else { // Multiple files are selected wchar_t fullPath[MAX_PATH]; for (int i = (dir.length() + 1), fileIndex = 0; ; fileIndex++) { // Get the next file name std::wstring file(&szFile[i]); // Two adjacent null characters signal the end of the files if (file.length() == 0) break; // The filename is relative to the directory that was specified as // the first string if (PathCombine(fullPath, dir.c_str(), file.c_str()) != NULL) { ExtensionString filePath(fullPath); ConvertToUnixPath(filePath); selectedFiles->SetString(fileIndex, filePath); } // Go to the start of the next file name i += file.length() + 1; } } } else { // If multiple files are not allowed, add the single file selectedFiles->SetString(0, szFile); } } } return NO_ERROR; }
int32 ReadDir(ExtensionString path, CefRefPtr<CefListValue>& directoryContents) { //# Add trailing /slash if neccessary if (path.length() && path[path.length() - 1] != '/') path += '/'; DIR *dp; struct dirent *files; struct stat statbuf; ExtensionString curFile; /*struct dirent { unsigned char d_type; #not supported on all systems, faster than stat char d_name[] }*/ if((dp=opendir(path.c_str()))==NULL) return ConvertLinuxErrorCode(errno,true); std::vector<ExtensionString> resultFiles; std::vector<ExtensionString> resultDirs; while((files=readdir(dp))!=NULL) { if(!strcmp(files->d_name,".") || !strcmp(files->d_name,"..")) continue; if(files->d_type==DT_DIR) resultDirs.push_back(ExtensionString(files->d_name)); else if(files->d_type==DT_REG) resultFiles.push_back(ExtensionString(files->d_name)); else { // Some file systems do not support d_type we use // for faster type detection. So on these file systems // we may get DT_UNKNOWN for all file entries, but just // to be safe we will use slower stat call for all // file entries that are not DT_DIR or DT_REG. curFile = path + files->d_name; if(stat(curFile.c_str(), &statbuf) == -1) continue; if(S_ISDIR(statbuf.st_mode)) resultDirs.push_back(ExtensionString(files->d_name)); else if(S_ISREG(statbuf.st_mode)) resultFiles.push_back(ExtensionString(files->d_name)); } } closedir(dp); //# List dirs first, files next size_t i, total = 0; for (i = 0; i < resultDirs.size(); i++) directoryContents->SetString(total++, resultDirs[i]); for (i = 0; i < resultFiles.size(); i++) directoryContents->SetString(total++, resultFiles[i]); return NO_ERROR; }