diff --git a/Gruntfile.js b/Gruntfile.js index 0732c8758..e0bb6b665 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -26,7 +26,8 @@ module.exports = function (grunt) { var common = require("./tasks/common")(grunt), platform = common.platform(), - staging; + staging, + cef_version = "3.2623.1397"; if (platform === "mac") { staging = "installer/mac/staging/<%= build.name %>.app/Contents"; @@ -36,6 +37,10 @@ module.exports = function (grunt) { staging = "installer/linux/debian/package-root/opt/brackets"; } + if (platform === "linux") { + cef_version = "3.2704.1414"; + } + grunt.initConfig({ "pkg": grunt.file.readJSON("package.json"), "config-json": staging + "/www/config.json", @@ -58,6 +63,14 @@ module.exports = function (grunt) { "dest" : "<%= downloads %>", "src" : "http://nodejs.org/dist/v<%= node.version %>/node-v<%= node.version %>-linux-x64.tar.gz" }, + "icu-linux32": { + "dest" : "<%= downloads %>", + "src" : "<%= icu.url %>/icu_<%= icu.version %>_linux32_release.zip" + }, + "icu-linux64": { + "dest" : "<%= downloads %>", + "src" : "<%= icu.url %>/icu_<%= icu.version %>_linux64_release.zip" + }, /* mac */ "cef-mac": { "dest" : "<%= downloads %>", @@ -171,7 +184,12 @@ module.exports = function (grunt) { "cef_100_percent.pak", "cef_200_percent.pak", "devtools_resources.pak", + "cef_extensions.pak", "icudtl.dat", + "libcef.so", + "natives_blob.bin", + "snapshot_blob.bin", + "chrome-sandbox", ], "dest" : "<%= build.staging %>" }, @@ -245,7 +263,7 @@ module.exports = function (grunt) { }, "cef": { "url" : "http://s3.amazonaws.com/files.brackets.io/cef", - "version" : "3.2623.1397" + "version" : cef_version }, "node": { "version" : "6.3.1" diff --git a/appshell.gyp b/appshell.gyp index 08920a4a5..4f22d247a 100755 --- a/appshell.gyp +++ b/appshell.gyp @@ -366,6 +366,7 @@ ], 'link_settings': { 'ldflags': [ + '-pthread', '-Wl,-rpath,\$$ORIGIN/', '<(march)' ], @@ -373,6 +374,11 @@ "$(BUILDTYPE)/libcef.so", "-lX11", 'appshell_extensions_js.o', + 'deps/icu/lib/libicuuc.a', + 'deps/icu/lib/libicuio.a', + 'deps/icu/lib/libicui18n.a', + 'deps/icu/lib/libicudata.a', + '-ldl', ], }, 'sources': [ diff --git a/appshell/appshell_extensions.cpp b/appshell/appshell_extensions.cpp index d07eb0d2c..38a44ac8b 100644 --- a/appshell/appshell_extensions.cpp +++ b/appshell/appshell_extensions.cpp @@ -28,6 +28,11 @@ #include "appshell_node_process.h" #include "config.h" +#ifdef OS_LINUX +#include "appshell/browser/main_context.h" +#include "appshell/browser/root_window_manager.h" +#endif + #include extern std::vector gDroppedFiles; @@ -394,10 +399,15 @@ class ProcessMessageDelegate : public ClientHandler::ProcessMessageDelegate { CefWindowInfo wi; CefBrowserSettings settings; -#if defined(OS_WIN) - wi.SetAsPopup(NULL, "DevTools"); -#endif - browser->GetHost()->ShowDevTools(wi, browser->GetHost()->GetClient(), settings, CefPoint()); + #if defined(OS_WIN) + wi.SetAsPopup(NULL, "DevTools"); + #elif defined(OS_LINUX) + handler->ShowDevTools(browser, CefPoint()); + #endif + + #ifndef OS_LINUX + browser->GetHost()->ShowDevTools(wi, browser->GetHost()->GetClient(), settings, CefPoint()); + #endif } else if (message_name == "GetNodeState") { // Parameters: @@ -423,7 +433,15 @@ class ProcessMessageDelegate : public ClientHandler::ProcessMessageDelegate { // The DispatchCloseToNextBrowser() call initiates a quit sequence. The app will // quit if all browser windows are closed. - handler->DispatchCloseToNextBrowser(); + #ifdef OS_LINUX + if(client::MainContext::Get() && + client::MainContext::Get()->GetRootWindowManager()){ + client::MainContext::Get()->GetRootWindowManager()->DispatchCloseToNextWindow(); + } + #else + handler->DispatchCloseToNextBrowser(); + #endif + } else if (message_name == "AbortQuit") { // Parameters - none @@ -765,8 +783,53 @@ class ProcessMessageDelegate : public ClientHandler::ProcessMessageDelegate { // 0: int32 - callback id responseArgs->SetString(2, GetSystemUniqueID()); - } - else { + } + else if (message_name == "ReadDirWithStats") { + // Parameters: + // 0: int32 - callback id + + CefRefPtr uberDict = CefListValue::Create(); + CefRefPtr dirContents = CefListValue::Create(); + CefRefPtr allStats = CefListValue::Create(); + + ExtensionString path = argList->GetString(1); + ReadDir(path, dirContents); + + // Now we iterator through the contents of directoryContents. + size_t theSize = dirContents->GetSize(); + for ( size_t iFileEntry = 0; iFileEntry < theSize ; ++iFileEntry) { + CefRefPtr fileStats = CefListValue::Create(); + + #ifdef OS_WIN + ExtensionString theFile = path + L"/"; + #else + ExtensionString theFile = path + "/"; + #endif + + ExtensionString fileName = dirContents->GetString(iFileEntry); + theFile = theFile + fileName; + + ExtensionString realPath; + uint32 modtime; + double size; + bool isDir; + GetFileInfo(theFile, modtime, isDir, size, realPath); + + fileStats->SetInt(0, modtime); + fileStats->SetBool(1, isDir); + fileStats->SetInt(2, size); + fileStats->SetString(3, realPath); + + allStats->SetList(iFileEntry, fileStats); + + } + + uberDict->SetList(0, dirContents); + uberDict->SetList(1, allStats); + responseArgs->SetList(2, uberDict); + } + + else { fprintf(stderr, "Native function not implemented yet: %s\n", message_name.c_str()); return false; } diff --git a/appshell/appshell_extensions.js b/appshell/appshell_extensions.js index e67dbf8c6..91a945444 100644 --- a/appshell/appshell_extensions.js +++ b/appshell/appshell_extensions.js @@ -326,8 +326,50 @@ if (!appshell.app) { }, path); }; - - + /** + * Reads the contents of a directory and reports contents along with stats. + * + * @param {string} path The path of the directory to read. + * @param {function(err, files)} callback Asynchronous callback function. The callback gets three arguments + * (err, files, stats) where files is an array of the names of the files + * in the directory excluding '.' and '..' and stats is an array of all stats of the files. + * Possible error values: + * NO_ERROR + * ERR_UNKNOWN + * ERR_INVALID_PARAMS + * ERR_NOT_FOUND + * ERR_CANT_READ + * + * @return None. This is an asynchronous call that sends all return information to the callback. + */ + // Test dictionary + native function ReadDirWithStats(); + appshell.fs.readDirWithStats = function (path, callback){ + + ReadDirWithStats(function (err, allPaths){ + if (callback) { + var finalArray = []; + var allContents = allPaths[0]; + var allStats = allPaths[1]; + + allStats.forEach(function (val, idx) { + finalArray[idx] = { + isFile: function () { + return !val[1]; + }, + isDirectory: function () { + return val[1]; + }, + mtime: new Date(val[0] * 1000), // modtime is seconds since 1970, convert to ms + size: new Number(val[2]), + realPath: val[3] ? val[3] : null + } + }); + callback(err, allContents, finalArray); + } + }, path); + }; + /** * Quits native shell application */ diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 2200d7952..f101c513e 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -1,30 +1,27 @@ /* * Copyright (c) 2012 Chhatoi Pritam Baral . All rights reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * + * */ -#include "appshell_extensions_platform.h" - -#include "appshell/appshell_helpers.h" - +#include "client_app.h" #include #include #include @@ -45,6 +42,30 @@ #include #include #include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "appshell_helpers.h" + +#define UTF8_BOM "\xEF\xBB\xBF" // Modifiers #define MODIFIER_CONTROL "Ctrl" @@ -72,24 +93,9 @@ #define KEY_BACK_QUOTE "`" #define KEY_COMMA "," +typedef char s8; extern CefRefPtr g_handler; -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -GtkWidget* _menuWidget; // Supported browsers (order matters): // - google-chorme @@ -426,19 +432,17 @@ bool has_utf32le_BOM(gchar* data, gsize length) } -bool has_utf16_32_BOM(gchar* data, gsize length) +bool has_utf_32_BOM(gchar* data, gsize length) { return (has_utf32be_BOM(data ,length) || - has_utf32le_BOM(data ,length) || - has_utf16be_BOM(data ,length) || - has_utf16le_BOM(data ,length) ); + has_utf32le_BOM(data ,length)); } -int ReadFile(ExtensionString filename, ExtensionString encoding, std::string& contents) +int32 ReadFile(ExtensionString filename, ExtensionString& encoding, std::string& contents, bool& preserveBOM) { - if (encoding != "utf8") { - return ERR_UNSUPPORTED_ENCODING; + if (encoding == "utf8") { + encoding = "UTF-8"; } int error = NO_ERROR; @@ -452,47 +456,92 @@ int ReadFile(ExtensionString filename, ExtensionString encoding, std::string& co error = ERR_CANT_READ; } } else { - if (has_utf16_32_BOM(file_get_contents, len)) { + if (has_utf_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; + // if file contains BOM chars, + // then we set preserveBOM to true, + // so that while writing we can + // prepend the BOM chars + std::ifstream file(filename.c_str()); + std::stringstream ss; + ss << file.rdbuf(); + contents = ss.str(); + contents.erase(0, 3); + preserveBOM = true; + } else if (!g_locale_to_utf8(file_get_contents, -1, NULL, NULL, &gerror) || encoding != "UTF-8") { + contents.assign(file_get_contents, len); + std::string detectedCharSet; + try { + if (encoding == "UTF-8") { + CharSetDetect ICUDetector; + ICUDetector(contents.c_str(), contents.size(), detectedCharSet); + } + else { + detectedCharSet = encoding; + } + if (detectedCharSet == "UTF-16LE" || detectedCharSet == "UTF-16BE") { + error = ERR_UNSUPPORTED_UTF16_ENCODING; + } + if (!detectedCharSet.empty() && error == NO_ERROR) { + std::transform(detectedCharSet.begin(), detectedCharSet.end(), detectedCharSet.begin(), ::toupper); + DecodeContents(contents, detectedCharSet); + encoding = detectedCharSet; + } + else if (detectedCharSet.empty()) { + error = ERR_UNSUPPORTED_ENCODING; + } + } catch (...) { + 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) +int32 WriteFile(ExtensionString filename, std::string contents, ExtensionString encoding, bool preserveBOM) { 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) { + if (g_file_test(filenameStr, G_FILE_TEST_EXISTS) && g_access(filenameStr, W_OK) == -1) { return ERR_CANT_WRITE; } + + if (encoding == "utf8") { + encoding = "UTF-8"; + } - FILE* file = fopen(filenameStr, "w"); - if (file) { - size_t size = fwrite(contents.c_str(), sizeof(gchar), contents.length(), file); - if (size != contents.length()) { + if (encoding != "UTF-8") { + try { + CharSetEncode ICUEncoder(encoding); + ICUEncoder(contents); + } catch (...) { + error = ERR_ENCODE_FILE_FAILED; + } + } else if (encoding == "UTF-8" && preserveBOM) { + // File originally contained BOM chars + // so we prepend BOM chars + contents = UTF8_BOM + contents; + } + + try { + std::ofstream file; + file.open (filenameStr); + file << contents; + if (file.fail()) { error = ERR_CANT_WRITE; } - - fclose(file); - } else { - return ConvertLinuxErrorCode(errno); + file.close(); + } catch (...) { + return ERR_CANT_WRITE; } - + return error; } @@ -1008,7 +1057,9 @@ int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, entry = gtk_separator_menu_item_new(); else entry = gtk_menu_item_new_with_label(itemTitle.c_str()); - g_signal_connect(entry, "activate", G_CALLBACK(Callback), GINT_TO_POINTER(tag)); + + InstallMenuHandler(entry, browser, tag); + ExtensionString commandId = model.getCommandId(tag); model.setOsItem(tag, entry); ParseShortcut(browser, entry, key, commandId); diff --git a/appshell/appshell_extensions_platform.cpp b/appshell/appshell_extensions_platform.cpp index e9c3f1f24..1c74a8a5a 100644 --- a/appshell/appshell_extensions_platform.cpp +++ b/appshell/appshell_extensions_platform.cpp @@ -3,6 +3,12 @@ #include #include +#ifdef OS_LINUX +#include "appshell/browser/main_context.h" +#include "appshell/browser/root_window_manager.h" +#include "appshell/browser/root_window_gtk.h" +#endif + #define UTF8_BOM "\xEF\xBB\xBF" CharSetDetect::CharSetDetect() { @@ -75,7 +81,8 @@ void CharSetEncode::operator()(std::string &contents) { void DecodeContents(std::string &contents, const std::string& encoding) { UnicodeString ustr(contents.c_str(), encoding.c_str()); UErrorCode status = U_ZERO_ERROR; - int targetLen = ustr.extract(NULL, 0, NULL, status); + UConverter *conv = NULL; + int targetLen = ustr.extract(NULL, 0, conv, status); if(status != U_BUFFER_OVERFLOW_ERROR) { throw "Unable to decode contents"; } @@ -118,3 +125,43 @@ void CheckForUTF8BOM(const std::string& filename, bool& preserveBOM) { } } +#ifdef OS_LINUX +// The following routine will get the containing GTK root window, for a browser. +scoped_refptr getRootGtkWindow(CefRefPtr browser) +{ + DCHECK(browser); + scoped_refptr rootGtkWindow; + if(browser.get() && + client::MainContext::Get() && + client::MainContext::Get()->GetRootWindowManager()){ + scoped_refptr rootWindow = client::MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser(browser->GetIdentifier()); + if (rootWindow){ + rootGtkWindow = dynamic_cast (rootWindow.get()); + } + } + return rootGtkWindow; +} + +void* getMenuParent(CefRefPtrbrowser) +{ + scoped_refptr rootGtkWindow = getRootGtkWindow(browser); + if (rootGtkWindow){ + // This returns the underlying vbox. GetWindowHandle() is going to + // return X11 ref because of which all our routines will break. + return (void*)(rootGtkWindow->GetContainerHandle()); + } else { + return NULL; + } +} + +void InstallMenuHandler(GtkWidget* entry, CefRefPtr browser, int tag) +{ + scoped_refptr rootGtkWindow = getRootGtkWindow(browser); + if (rootGtkWindow){ + // Let the gtk root window handle menu activations. + rootGtkWindow->InstallMenuHandler(entry, tag); + rootGtkWindow->Show(client::RootWindowGtk::ShowNormal); + } +} + +#endif diff --git a/appshell/appshell_extensions_platform.h b/appshell/appshell_extensions_platform.h index fa65a0de0..b2cea7b51 100644 --- a/appshell/appshell_extensions_platform.h +++ b/appshell/appshell_extensions_platform.h @@ -83,11 +83,8 @@ inline void* getMenuParent(CefRefPtrbrowser) {return NULL;} // Mac u int32 InstallCommandLineTools(); #else typedef std::string ExtensionString; -inline void* getMenuParent(CefRefPtrbrowser) { - return gtk_widget_get_ancestor( - GTK_WIDGET(browser->GetHost()->GetWindowHandle()), - GTK_TYPE_VBOX); -} +void* getMenuParent(CefRefPtrbrowser); +void InstallMenuHandler(GtkWidget* entry, CefRefPtr browser, int id); inline int32 InstallCommandLineTools() { return ERR_CL_TOOLS_NOTSUPPORTED; } #endif diff --git a/appshell/browser/browser_window.cc b/appshell/browser/browser_window.cc index c021e9fb9..40c9478a9 100644 --- a/appshell/browser/browser_window.cc +++ b/appshell/browser/browser_window.cc @@ -7,6 +7,12 @@ #include "include/base/cef_bind.h" #include "appshell/browser/main_message_loop.h" +// Brackets specific change +#ifdef OS_LINUX +#include "appshell/command_callbacks.h" +#include "appshell/native_menu_model.h" +#endif + namespace client { BrowserWindow::BrowserWindow(Delegate* delegate) @@ -88,4 +94,29 @@ void BrowserWindow::OnSetDraggableRegions( delegate_->OnSetDraggableRegions(regions); } +#ifdef OS_LINUX +// Brackets specific change. +// The following is usually called in the multi window workflows. +// Once a window is done processing the "QuitApplication" command, +// We pass the quit to the next window. +void BrowserWindow::DispatchCloseToBrowser(CefRefPtr browser) +{ + if(client_handler_){ + CefRefPtr callback = new CloseWindowCommandCallback(browser); + client_handler_->SendJSCommand(browser, FILE_CLOSE_WINDOW, callback); + } +} + +// The following routine dispatches brackets specific commands to the browser. +void BrowserWindow::DispatchCommandToBrowser(CefRefPtr browser, int tag) +{ + if(client_handler_){ + ExtensionString commandId = NativeMenuModel::getInstance(getMenuParent(browser)).getCommandId(tag); + CefRefPtr callback = new EditCommandCallback(browser, commandId); + client_handler_->SendJSCommand(browser, commandId, callback); + } +} + +#endif + } // namespace client diff --git a/appshell/browser/browser_window.h b/appshell/browser/browser_window.h index e8b3a196b..37a035f8a 100644 --- a/appshell/browser/browser_window.h +++ b/appshell/browser/browser_window.h @@ -99,6 +99,12 @@ class BrowserWindow : public ClientHandler::Delegate { // Returns true if the browser is closing. bool IsClosing() const; + // Brackets specific change. +#ifdef OS_LINUX + void DispatchCloseToBrowser(CefRefPtr browser) ; + void DispatchCommandToBrowser(CefRefPtr browser, int tag); +#endif + protected: // Allow deletion via scoped_ptr only. friend struct base::DefaultDeleter; diff --git a/appshell/browser/browser_window_std_gtk.cc b/appshell/browser/browser_window_std_gtk.cc index 77adcb758..326b66027 100644 --- a/appshell/browser/browser_window_std_gtk.cc +++ b/appshell/browser/browser_window_std_gtk.cc @@ -97,10 +97,19 @@ void BrowserWindowStdGtk::CreateBrowser( CefWindowInfo window_info; window_info.SetAsChild(GetXWindowForWidget(parent_handle), rect); + + // Brackets specific overrides. + CefBrowserSettings browserSettings; + + browserSettings.web_security = STATE_DISABLED; + + // Necessary to enable document.executeCommand("paste") + browserSettings.javascript_access_clipboard = STATE_ENABLED; + browserSettings.javascript_dom_paste = STATE_ENABLED; CefBrowserHost::CreateBrowser(window_info, client_handler_, client_handler_->startup_url(), - settings, request_context); + browserSettings, request_context); } void BrowserWindowStdGtk::GetPopupConfig(CefWindowHandle temp_handle, diff --git a/appshell/browser/client_handler.cc b/appshell/browser/client_handler.cc index 51bb654d1..ac8fc66f4 100644 --- a/appshell/browser/client_handler.cc +++ b/appshell/browser/client_handler.cc @@ -20,6 +20,11 @@ #include "appshell/browser/root_window_manager.h" #include "appshell/common/client_switches.h" +// Brackets specific change. +#ifdef OS_LINUX +#include "appshell/appshell_extensions.h" +#endif + namespace client { #if defined(OS_WIN) @@ -189,7 +194,12 @@ bool ClientHandler::OnProcessMessageReceived( return true; } +#ifdef OS_LINUX + // Give an opportunity to the base class. brackets/appshell specific change. + return _parent::OnProcessMessageReceived(browser, source_process, message); +#else return false; +#endif } void ClientHandler::OnBeforeContextMenu( diff --git a/appshell/browser/client_handler.h b/appshell/browser/client_handler.h index bc2886c8f..b3363a10a 100644 --- a/appshell/browser/client_handler.h +++ b/appshell/browser/client_handler.h @@ -17,13 +17,25 @@ #if defined(OS_LINUX) #include "appshell/browser/dialog_handler_gtk.h" +// Brackets specific change. +#include "appshell/client_handler.h" #endif + namespace client { // Client handler abstract base class. Provides common functionality shared by // all concrete client handler implementations. -class ClientHandler : public CefClient, + +// Brackets specific change. +// On Linux we are going to be using this client handler instead of +// appshell/ClientHandler. +class ClientHandler : + #ifdef OS_LINUX + public ::ClientHandler, + public CefDownloadHandler { + #else + public CefClient, public CefContextMenuHandler, public CefDisplayHandler, public CefDownloadHandler, @@ -33,7 +45,9 @@ class ClientHandler : public CefClient, public CefLifeSpanHandler, public CefLoadHandler, public CefRequestHandler { + #endif public: + typedef ::ClientHandler _parent; // Implement this interface to receive notification of ClientHandler // events. The methods of this class will be called on the main thread. class Delegate { @@ -109,7 +123,8 @@ class ClientHandler : public CefClient, CefRefPtr GetRequestHandler() OVERRIDE { return this; } - bool OnProcessMessageReceived(CefRefPtr browser, + + virtual bool OnProcessMessageReceived(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) OVERRIDE; @@ -253,7 +268,7 @@ class ClientHandler : public CefClient, int GetBrowserCount() const; // Show a new DevTools popup window. - void ShowDevTools(CefRefPtr browser, + virtual void ShowDevTools(CefRefPtr browser, const CefPoint& inspect_element_at); // Close the existing DevTools popup window, if any. diff --git a/appshell/browser/dialog_handler_gtk.cc b/appshell/browser/dialog_handler_gtk.cc old mode 100644 new mode 100755 index 264897499..33ba2d153 --- a/appshell/browser/dialog_handler_gtk.cc +++ b/appshell/browser/dialog_handler_gtk.cc @@ -129,11 +129,15 @@ void AddFilters(GtkFileChooser* chooser, } } -GtkWidget* GetWindow(CefRefPtr browser) { +GtkWindow* GetWindow(CefRefPtr browser) { scoped_refptr root_window = RootWindow::GetForBrowser(browser->GetIdentifier()); - if (root_window.get()) - return root_window->GetWindowHandle(); + if (root_window) { + GtkWindow* window = GTK_WINDOW(root_window->GetWindowHandle()); + if (!window) + LOG(ERROR) << "No GtkWindow for browser"; + return window; + } return NULL; } @@ -197,8 +201,9 @@ bool ClientDialogHandlerGtk::OnFileDialog( } } - GtkWidget* window = GetWindow(browser); - DCHECK(window); + GtkWindow* window = GetWindow(browser); + if (!window) + return false; GtkWidget* dialog = gtk_file_chooser_dialog_new( title_str.c_str(), @@ -298,7 +303,6 @@ bool ClientDialogHandlerGtk::OnFileDialog( bool ClientDialogHandlerGtk::OnJSDialog( CefRefPtr browser, const CefString& origin_url, - const CefString& accept_lang, JSDialogType dialog_type, const CefString& message_text, const CefString& default_prompt_text, @@ -334,11 +338,12 @@ bool ClientDialogHandlerGtk::OnJSDialog( if (!origin_url.empty()) { title += " - "; - title += CefFormatUrlForSecurityDisplay(origin_url, accept_lang).ToString(); + title += CefFormatUrlForSecurityDisplay(origin_url).ToString(); } - GtkWidget* window = GetWindow(browser); - DCHECK(window); + GtkWindow* window = GetWindow(browser); + if (!window) + return false; gtk_dialog_ = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, @@ -389,7 +394,7 @@ bool ClientDialogHandlerGtk::OnBeforeUnloadDialog( message_text.ToString() + "\n\nIs it OK to leave/reload this page?"; bool suppress_message = false; - return OnJSDialog(browser, CefString(), CefString(), JSDIALOGTYPE_CONFIRM, + return OnJSDialog(browser, CefString(), JSDIALOGTYPE_CONFIRM, new_message_text, CefString(), callback, suppress_message); } diff --git a/appshell/browser/dialog_handler_gtk.h b/appshell/browser/dialog_handler_gtk.h old mode 100644 new mode 100755 index 0286ebd29..95ffd8e05 --- a/appshell/browser/dialog_handler_gtk.h +++ b/appshell/browser/dialog_handler_gtk.h @@ -30,7 +30,6 @@ class ClientDialogHandlerGtk : public CefDialogHandler, // CefJSDialogHandler methods. bool OnJSDialog(CefRefPtr browser, const CefString& origin_url, - const CefString& accept_lang, JSDialogType dialog_type, const CefString& message_text, const CefString& default_prompt_text, diff --git a/appshell/browser/main_context_impl.cc b/appshell/browser/main_context_impl.cc index 9dc62f52d..3caaec264 100644 --- a/appshell/browser/main_context_impl.cc +++ b/appshell/browser/main_context_impl.cc @@ -6,7 +6,6 @@ #include "include/cef_parser.h" #include "appshell/common/client_switches.h" - namespace client { namespace { @@ -14,6 +13,27 @@ namespace { // The default URL to load in a browser window. const char kDefaultUrl[] = "http://www.google.com"; +// Returns the ARGB value for |color|. +cef_color_t ParseColor(const std::string& color) { + std::string colorToLower; + colorToLower.resize(color.size()); + std::transform(color.begin(), color.end(), colorToLower.begin(), ::tolower); + + if (colorToLower == "black") + return CefColorSetARGB(255, 0, 0, 0); + else if (colorToLower == "blue") + return CefColorSetARGB(255, 0, 0, 255); + else if (colorToLower == "green") + return CefColorSetARGB(255, 0, 255, 0); + else if (colorToLower == "red") + return CefColorSetARGB(255, 255, 0, 0); + else if (colorToLower == "white") + return CefColorSetARGB(255, 255, 255, 255); + + // Use the default color. + return 0U; +} + } // namespace MainContextImpl::MainContextImpl(CefRefPtr command_line, @@ -33,8 +53,8 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, if (command_line_->HasSwitch(switches::kBackgroundColor)) { // Parse the background color value. - CefParseCSSColor(command_line_->GetSwitchValue(switches::kBackgroundColor), - false, background_color_); + background_color_ = + ParseColor(command_line_->GetSwitchValue(switches::kBackgroundColor)); } } @@ -83,6 +103,7 @@ RootWindowManager* MainContextImpl::GetRootWindowManager() { return root_window_manager_.get(); } + bool MainContextImpl::Initialize(const CefMainArgs& args, const CefSettings& settings, CefRefPtr application, diff --git a/appshell/browser/print_handler_gtk.cc b/appshell/browser/print_handler_gtk.cc index 3ae4219e5..377e30289 100644 --- a/appshell/browser/print_handler_gtk.cc +++ b/appshell/browser/print_handler_gtk.cc @@ -492,7 +492,7 @@ void ClientPrintHandlerGtk::OnDialogResponse(GtkDialog *dialog, if (gtk_range) { for (int i = 0; i < num_ranges; ++i) { ranges_vector.push_back( - CefPageRange(gtk_range[i].start, gtk_range[i].end)); + CefRange(gtk_range[i].start, gtk_range[i].end)); } g_free(gtk_range); } diff --git a/appshell/browser/root_window.h b/appshell/browser/root_window.h index 75353e619..47af0781a 100644 --- a/appshell/browser/root_window.h +++ b/appshell/browser/root_window.h @@ -117,6 +117,11 @@ class RootWindow : // Returns the native handle for this window, if any. virtual ClientWindowHandle GetWindowHandle() const = 0; +#ifdef OS_LINUX + // Brackets specific: Dispatches close command to the next browser window. + virtual void DispatchCloseToBrowser(CefRefPtr browser) = 0; +#endif + protected: // Allow deletion via scoped_refptr only. friend struct DeleteOnMainThread; diff --git a/appshell/browser/root_window_gtk.cc b/appshell/browser/root_window_gtk.cc index bf7e9815b..b22c63509 100644 --- a/appshell/browser/root_window_gtk.cc +++ b/appshell/browser/root_window_gtk.cc @@ -21,6 +21,10 @@ #include "appshell/browser/window_test.h" #include "appshell/common/client_switches.h" +// Brackets specific change. +#include "appshell/native_menu_model.h" +#include "appshell/command_callbacks.h" + namespace client { namespace { @@ -149,6 +153,13 @@ void RootWindowGtk::Show(ShowMode mode) { MinimizeWindow(GTK_WINDOW(window_)); else if (mode == ShowMaximized) MaximizeWindow(GTK_WINDOW(window_)); + + // Flush the display to make sure the underlying X11 window gets created + // immediately. + GdkWindow* gdk_window = gtk_widget_get_window(window_); + GdkDisplay* display = gdk_window_get_display(gdk_window); + gdk_display_flush(display); + } void RootWindowGtk::Hide() { @@ -265,6 +276,9 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) { g_signal_connect(vbox, "size-allocate", G_CALLBACK(&RootWindowGtk::VboxSizeAllocated), this); gtk_container_add(GTK_CONTAINER(window_), vbox); + + // Brackets specific change. + v_box_ = vbox; if (with_controls_) { GtkWidget* menu_bar = CreateMenuBar(); @@ -311,6 +325,12 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) { gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); + } else { + // Brackets specific change. + GtkWidget *menu_bar_ = gtk_menu_bar_new(); + gtk_box_pack_start(GTK_BOX(vbox), menu_bar_, FALSE, FALSE, 0); + g_signal_connect(menu_bar_, "size-allocate", + G_CALLBACK(&RootWindowGtk::MenubarSizeAllocated), this); } // Realize (show) the GTK widget. This must be done before the browser is @@ -387,12 +407,15 @@ void RootWindowGtk::OnSetFullscreen(bool fullscreen) { REQUIRE_MAIN_THREAD(); CefRefPtr browser = GetBrowser(); + // Brackets specific change. + /* if (browser) { if (fullscreen) window_test::Maximize(browser); else window_test::Restore(browser); } + */ } void RootWindowGtk::OnSetLoadingState(bool isLoading, @@ -482,13 +505,12 @@ gboolean RootWindowGtk::WindowDelete(GtkWidget* widget, if (self->force_close_) return FALSE; // Allow the close. + // Brackets specific change. if (self->browser_window_.get() && !self->browser_window_->IsClosing()) { CefRefPtr browser = self->GetBrowser(); if (browser) { - // Notify the browser window that we would like to close it. This - // will result in a call to ClientHandler::DoClose() if the - // JavaScript 'onbeforeunload' event handler allows it. - browser->GetHost()->CloseBrowser(false); + // Brackets specific change. + self->DispatchCloseToBrowser(browser); // Cancel the close. return TRUE; @@ -499,13 +521,35 @@ gboolean RootWindowGtk::WindowDelete(GtkWidget* widget, return FALSE; } +// Brackets specific change. +void RootWindowGtk::DispatchCloseToBrowser(CefRefPtr browser) +{ + DCHECK(browser_window_); + if(browser_window_) + browser_window_->DispatchCloseToBrowser(browser); +} + +ClientWindowHandle RootWindowGtk::GetContainerHandle() const +{ + return v_box_; +} + +void RootWindowGtk::InstallMenuHandler(GtkWidget* entry, int tag) +{ + if(entry){ + g_object_set_data(G_OBJECT(entry), kMenuIdKey, GINT_TO_POINTER(tag)); + g_signal_connect(entry, "activate", G_CALLBACK(&RootWindowGtk::MenuItemActivated), this); + } +} +// End of Brackets specific changes. + // static void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget, GtkAllocation* allocation, RootWindowGtk* self) { // Offset browser positioning by any controls that will appear in the client // area. - const int ux_height = self->toolbar_height_ + self->menubar_height_; + const int ux_height = self->toolbar_height_ + self->menubar_height_ > 1 ? self->menubar_height_ : 0; const int x = allocation->x; const int y = allocation->y + ux_height; const int width = allocation->width; @@ -528,12 +572,9 @@ void RootWindowGtk::MenubarSizeAllocated(GtkWidget* widget, gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget, RootWindowGtk* self) { // Retrieve the menu ID set in AddMenuEntry. - int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey)); - // Run the test. - if (self->delegate_) - self->delegate_->OnTest(self, id); - - return FALSE; // Don't stop this message. + int tag = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey)); + if (self && self->browser_window_) + self->browser_window_->DispatchCommandToBrowser(self->GetBrowser(), tag); } // static @@ -627,7 +668,7 @@ gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget, GtkWidget* RootWindowGtk::CreateMenuBar() { GtkWidget* menu_bar = gtk_menu_bar_new(); - + // Create the test menu. GtkWidget* test_menu = CreateMenu(menu_bar, "Tests"); AddMenuEntry(test_menu, "Get Source", ID_TESTS_GETSOURCE); diff --git a/appshell/browser/root_window_gtk.h b/appshell/browser/root_window_gtk.h index 2db2de115..2dd0b9ac3 100644 --- a/appshell/browser/root_window_gtk.h +++ b/appshell/browser/root_window_gtk.h @@ -47,6 +47,11 @@ class RootWindowGtk : public RootWindow, float GetDeviceScaleFactor() const OVERRIDE; CefRefPtr GetBrowser() const OVERRIDE; ClientWindowHandle GetWindowHandle() const OVERRIDE; + + // Brackets specific change. + ClientWindowHandle GetContainerHandle() const; + virtual void DispatchCloseToBrowser(CefRefPtr browser); + virtual void InstallMenuHandler(GtkWidget* entry, int tag); private: void CreateBrowserWindow(const std::string& startup_url); @@ -130,6 +135,9 @@ class RootWindowGtk : public RootWindow, // Main window. GtkWidget* window_; + // Brackets specific change. + GtkWidget* v_box_; + // Buttons. GtkToolItem* back_button_; GtkToolItem* forward_button_; diff --git a/appshell/browser/root_window_manager.cc b/appshell/browser/root_window_manager.cc index b8ab9e81e..92a735dbd 100644 --- a/appshell/browser/root_window_manager.cc +++ b/appshell/browser/root_window_manager.cc @@ -66,6 +66,10 @@ scoped_refptr RootWindowManager::CreateRootWindow( MainContext::Get()->PopulateBrowserSettings(&settings); scoped_refptr root_window = RootWindow::Create(); + + // Brackets specific change. + with_controls = false; + root_window->Init(this, with_controls, with_osr, bounds, settings, url.empty() ? MainContext::Get()->GetMainURL() : url); @@ -84,6 +88,9 @@ scoped_refptr RootWindowManager::CreateRootWindowAsPopup( CefBrowserSettings& settings) { MainContext::Get()->PopulateBrowserSettings(&settings); + // Brackets specific change. + with_controls = false; + scoped_refptr root_window = RootWindow::Create(); root_window->InitAsPopup(this, with_controls, with_osr, popupFeatures, windowInfo, client, settings); @@ -200,4 +207,15 @@ void RootWindowManager::OnRootWindowDestroyed(RootWindow* root_window) { } } +// Brackets specific change. +void RootWindowManager::DispatchCloseToNextWindow(){ + if (!root_windows_.empty()){ + RootWindowSet::const_iterator it = root_windows_.begin(); + for (; it != root_windows_.end(); ++it) { + CefRefPtr browser = (*it)->GetBrowser(); + (*it)->DispatchCloseToBrowser(browser); + } + } +} + } // namespace client diff --git a/appshell/browser/root_window_manager.h b/appshell/browser/root_window_manager.h index 68dd0703e..9da7aca62 100644 --- a/appshell/browser/root_window_manager.h +++ b/appshell/browser/root_window_manager.h @@ -55,6 +55,9 @@ class RootWindowManager : public RootWindow::Delegate { // be executed. void CloseAllWindows(bool force); + // Brackets specific change. + void DispatchCloseToNextWindow(); + private: // Allow deletion via scoped_ptr only. friend struct base::DefaultDeleter; diff --git a/appshell/cefclient.cpp b/appshell/cefclient.cpp index d0ccbe1da..72777401b 100644 --- a/appshell/cefclient.cpp +++ b/appshell/cefclient.cpp @@ -11,7 +11,6 @@ #include "include/cef_browser.h" #include "include/cef_command_line.h" #include "include/cef_frame.h" -#include "include/cef_runnable.h" #include "include/cef_web_plugin.h" #include "include/base/cef_logging.h" #include "client_handler.h" diff --git a/appshell/cefclient_gtk.cc b/appshell/cefclient_gtk.cc index 568bfa861..e4304db01 100644 --- a/appshell/cefclient_gtk.cc +++ b/appshell/cefclient_gtk.cc @@ -13,11 +13,20 @@ #include "include/cef_version.h" #include "include/cef_browser.h" #include "include/cef_frame.h" -#include "include/cef_runnable.h" #include "client_handler.h" #include "appshell/common/client_switches.h" #include "appshell/appshell_helpers.h" #include "appshell_node_process.h" +#include "appshell/common/client_app.h" +#include "appshell/common/client_app_other.h" +#include "appshell/browser/client_app_browser.h" +#include "appshell/renderer/client_app_renderer.h" +#include "appshell/browser/main_context_impl.h" +#include "appshell/browser/main_message_loop_std.h" +#include "include/wrapper/cef_helpers.h" +#include "appshell/browser/client_handler_std.h" +#include +#include static std::string APPICONS[] = {"appshell32.png","appshell48.png","appshell128.png","appshell256.png"}; int add_handler_id; @@ -33,9 +42,6 @@ void destroy(void) { CefQuitMessageLoop(); } -void TerminationSignalHandler(int signatl) { - destroy(); -} void HandleAdd(GtkContainer *container, GtkWidget *widget, gpointer user_data) { @@ -82,122 +88,150 @@ gboolean GetSourceActivated(GtkWidget* widget) { return FALSE; } -int main(int argc, char* argv[]) { - CefMainArgs main_args(argc, argv); +namespace client { +namespace { + +int XErrorHandlerImpl(Display *display, XErrorEvent *event) { + LOG(WARNING) + << "X error received: " + << "type " << event->type << ", " + << "serial " << event->serial << ", " + << "error_code " << static_cast(event->error_code) << ", " + << "request_code " << static_cast(event->request_code) << ", " + << "minor_code " << static_cast(event->minor_code); + return 0; +} + +int XIOErrorHandlerImpl(Display *display) { + return 0; +} + +void TerminationSignalHandler(int signatl) { + LOG(ERROR) << "Received termination signal: " << signatl; + MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true); +} + +int RunMain(int argc, char* argv[]) { + // Create a copy of |argv| on Linux because Chromium mangles the value + // internally (see issue #620). + CefScopedArgArray scoped_arg_array(argc, argv); + char** argv_copy = scoped_arg_array.array(); + CefMainArgs main_args(argc, argv); + g_appStartupTime = time(NULL); - gtk_init(&argc, &argv); - CefRefPtr app(new ClientApp); + // Parse command-line arguments. + CefRefPtr command_line = CefCommandLine::CreateCommandLine(); + command_line->InitFromArgv(argc, argv); + + // Create a ClientApp of the correct type. + CefRefPtr app; + ClientApp::ProcessType process_type = ClientApp::GetProcessType(command_line); + if (process_type == ClientApp::RendererProcess || + process_type == ClientApp::ZygoteProcess || + process_type == ClientApp::BrowserProcess) { + app = new ::ClientApp(); + } else if (process_type == ClientApp::OtherProcess) { + app = new ClientAppOther(); + } // Execute the secondary process, if any. - int exit_code = CefExecuteProcess(main_args, app.get(), NULL); + int exit_code = CefExecuteProcess(main_args, app, NULL); if (exit_code >= 0) return exit_code; - //Retrieve the current working directory - if (!appshell::AppInitWorkingDirectory()) - return -1; - - GtkWidget* window; - - // Parse command line arguments. - CefRefPtr cmdLine = CefCommandLine::CreateCommandLine(); - cmdLine->InitFromArgv(argc, argv); + // Create the main context object. + scoped_ptr context(new MainContextImpl(command_line, true)); CefSettings settings; // Populate the settings based on command line arguments. - AppGetSettings(settings, cmdLine); - - settings.no_sandbox = TRUE; + AppGetSettings(settings, command_line); // Check cache_path setting if (CefString(&settings.cache_path).length() == 0) { CefString(&settings.cache_path) = appshell::AppGetCachePath(); } + + startNodeProcess(); - if (appshell::AppInitInitialURL(cmdLine) < 0) { + // Initialize CEF. + context->Initialize(main_args, settings, app, NULL); + + // The Chromium sandbox requires that there only be a single thread during + // initialization. Therefore initialize GTK after CEF. + gtk_init(&argc, &argv_copy); + + if (appshell::AppInitInitialURL(command_line) < 0) { + context->Shutdown(); return 0; } - // Initialize CEF. - CefInitialize(main_args, settings, app.get(), NULL); + // Install xlib error handlers so that the application won't be terminated + // on non-fatal errors. Must be done after initializing GTK. + XSetErrorHandler(XErrorHandlerImpl); + XSetIOErrorHandler(XIOErrorHandlerImpl); + + // Install a signal handler so we clean up after ourselves. + signal(SIGINT, TerminationSignalHandler); + signal(SIGTERM, TerminationSignalHandler); - // Set window icon - std::vector icons(APPICONS, APPICONS + sizeof(APPICONS) / sizeof(APPICONS[0]) ); - GList *list = NULL; - for (int i = 0; i < icons.size(); ++i) { - std::string path = icons[i]; + // Create the main message loop object. + scoped_ptr message_loop(new MainMessageLoopStd); + + // Create the first window. + scoped_refptr root_window = context->GetRootWindowManager()->CreateRootWindow( + false, //Hide controls. + settings.windowless_rendering_enabled ? true : false, + CefRect(), // Use default system size. + "file://" + appshell::AppGetInitialURL() + ); - GdkPixbuf *icon = gdk_pixbuf_new_from_file(path.c_str(), NULL); - if (!icon) - continue; + // get the reference to the root window. + GtkWidget* window = root_window->GetWindowHandle(); + if (window) { + // Set window icon + std::vector icons(APPICONS, APPICONS + sizeof(APPICONS) / sizeof(APPICONS[0]) ); + GList *list = NULL; + for (int i = 0; i < icons.size(); ++i) { + std::string path = icons[i]; + + GdkPixbuf *icon = gdk_pixbuf_new_from_file(path.c_str(), NULL); + if (!icon) + continue; + + list = g_list_append(list, icon); + } + + gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); + gtk_window_set_icon_list(GTK_WINDOW(window), list); - list = g_list_append(list, icon); + // Free icon list + g_list_foreach(list, (GFunc) g_object_unref, NULL); + g_list_free(list); } - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); + // Run the message loop. This will block until Quit() is called. + int result = message_loop->Run(); - gtk_window_set_icon_list(GTK_WINDOW(window), list); + root_window = NULL; - // Free icon list - g_list_foreach(list, (GFunc) g_object_unref, NULL); - g_list_free(list); - - GtkWidget* vbox = gtk_vbox_new(FALSE, 0); - - GtkWidget* menuBar = gtk_menu_bar_new(); - // GtkWidget* debug_menu = CreateMenu(menuBar, "Tests"); - // AddMenuEntry(debug_menu, "Hello World Menu", - // G_CALLBACK(GetSourceActivated)); - - gtk_box_pack_start(GTK_BOX(vbox), menuBar, FALSE, FALSE, 0); - - g_signal_connect(G_OBJECT(window), "delete_event", - G_CALLBACK(HandleQuit), NULL); - g_signal_connect(G_OBJECT(window), "destroy", - G_CALLBACK(gtk_widget_destroyed), &window); - add_handler_id = g_signal_connect(G_OBJECT(window), "add", - G_CALLBACK(HandleAdd), NULL); - // g_signal_connect(G_OBJECT(window), "destroy", - // G_CALLBACK(destroy), NULL); - - // Create the handler. - g_handler = new ClientHandler(); - g_handler->SetMainHwnd(vbox); - - // Create the browser view. - CefWindowInfo window_info; - CefBrowserSettings browserSettings; + // Shut down CEF. + context->Shutdown(); - browserSettings.web_security = STATE_DISABLED; + // Release objects in reverse order of creation. + message_loop.reset(); + context.reset(); - // Necessary to enable document.executeCommand("paste") - browserSettings.javascript_access_clipboard = STATE_ENABLED; - browserSettings.javascript_dom_paste = STATE_ENABLED; - - window_info.SetAsChild(vbox); - - CefBrowserHost::CreateBrowser( - window_info, - static_cast >(g_handler), - "file://" + appshell::AppGetInitialURL(), browserSettings, NULL); - - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show_all(GTK_WIDGET(window)); - - // Install an signal handler so we clean up after ourselves. - signal(SIGINT, TerminationSignalHandler); - signal(SIGTERM, TerminationSignalHandler); - - // Start the node server process - startNodeProcess(); + return result; +} - CefRunMessageLoop(); +} // namespace +} // namespace client - CefShutdown(); - return 0; +// Program entry point function. +int main(int argc, char* argv[]) { + return client::RunMain(argc, argv); } diff --git a/appshell/client_handler.cpp b/appshell/client_handler.cpp index 8210284c7..18698d2f6 100644 --- a/appshell/client_handler.cpp +++ b/appshell/client_handler.cpp @@ -356,7 +356,7 @@ bool ClientHandler::OnContextMenuCommand( EventFlags event_flags) { switch (command_id) { case CLIENT_ID_SHOW_DEVTOOLS: - ShowDevTools(browser); + ShowDevTools(browser, CefPoint()); return true; default: // Allow default handling, if any. return false; @@ -399,7 +399,8 @@ std::string ClientHandler::GetLastDownloadFile() { return m_LastDownloadFile; } -void ClientHandler::ShowDevTools(CefRefPtr browser) { +void ClientHandler::ShowDevTools(CefRefPtr browser, + const CefPoint& inspect_element_at) { CefWindowInfo wi; CefBrowserSettings settings; diff --git a/appshell/client_handler.h b/appshell/client_handler.h index b697ccac3..ed6ade301 100644 --- a/appshell/client_handler.h +++ b/appshell/client_handler.h @@ -212,7 +212,8 @@ virtual bool OnBeforePopup(CefRefPtr browser, void SendNotification(NotificationType type); void CloseMainWindow(); - void ShowDevTools(CefRefPtr browser); + virtual void ShowDevTools(CefRefPtr browserShowDevTools, + const CefPoint& inspect_element_at); // Call the "executeCommand" method, passing the command name. // If callback is specified, it will be called with the result from the command. diff --git a/appshell/common/client_app_delegates_common.cc b/appshell/common/client_app_delegates_common.cc index 001537851..67c091f63 100644 --- a/appshell/common/client_app_delegates_common.cc +++ b/appshell/common/client_app_delegates_common.cc @@ -3,7 +3,7 @@ // can be found in the LICENSE file. #include "appshell/common/client_app.h" -#include "appshell/common/scheme_test_common.h" +//#include "appshell/common/scheme_test_common.h" namespace client { @@ -11,7 +11,8 @@ namespace client { void ClientApp::RegisterCustomSchemes( CefRefPtr registrar, std::vector& cookiable_schemes) { - scheme_test::RegisterCustomSchemes(registrar, cookiable_schemes); + // Brackets specific change. + //scheme_test::RegisterCustomSchemes(registrar, cookiable_schemes); } } // namespace client diff --git a/appshell/renderer/client_app_delegates_renderer.cc b/appshell/renderer/client_app_delegates_renderer.cc index 44e095bdf..abd3939c1 100644 --- a/appshell/renderer/client_app_delegates_renderer.cc +++ b/appshell/renderer/client_app_delegates_renderer.cc @@ -4,14 +4,16 @@ #include "appshell/renderer/client_app_renderer.h" #include "appshell/renderer/client_renderer.h" -#include "appshell/renderer/performance_test.h" +//#include "appshell/renderer/performance_test.h" namespace client { // static void ClientAppRenderer::CreateDelegates(DelegateSet& delegates) { renderer::CreateDelegates(delegates); - performance_test::CreateDelegates(delegates); + // Brackets specific change. + //performance_test::CreateDelegates(delegates); } } // namespace client + \ No newline at end of file diff --git a/appshell_paths.gypi b/appshell_paths.gypi index 021a2fdce..6a3db0601 100755 --- a/appshell_paths.gypi +++ b/appshell_paths.gypi @@ -171,8 +171,6 @@ 'appshell/browser/root_window_manager.cc', 'appshell/browser/root_window_manager.h', 'appshell/browser/temp_window.h', - 'appshell/browser/window_test.cc', - 'appshell/browser/window_test.h', ], 'appshell_sources_common_helper': [ 'appshell/common/client_switches.cc', @@ -380,7 +378,6 @@ 'appshell/browser/root_window_gtk.h', 'appshell/browser/temp_window_x11.cc', 'appshell/browser/temp_window_x11.h', - 'appshell/browser/window_test_gtk.cc', 'appshell/cefclient_gtk.cc', 'appshell/appshell_extensions_gtk.cpp', diff --git a/installer/linux/build_installer.sh b/installer/linux/build_installer.sh index 7ee41c7e0..009c3107e 100755 --- a/installer/linux/build_installer.sh +++ b/installer/linux/build_installer.sh @@ -9,6 +9,9 @@ chmod 755 debian/package-root/opt/brackets/www/node_modules/opn/xdg-open chmod 755 debian/package-root/DEBIAN/prerm chmod 755 debian/package-root/DEBIAN/postrm chmod 755 debian/package-root/DEBIAN/postinst +chown root debian/package-root/opt/brackets/chrome-sandbox +chmod 4755 debian/package-root/opt/brackets/chrome-sandbox + # set permissions on subdirectories find debian -type d -exec chmod 755 {} \; diff --git a/installer/linux/debian/control b/installer/linux/debian/control index 410cc1ee4..3a924a309 100644 --- a/installer/linux/debian/control +++ b/installer/linux/debian/control @@ -5,7 +5,7 @@ Priority: optional Architecture: <%= arch %> Installed-Size: <%= size %> Pre-Depends: dpkg (>= 1.14.0) -Depends: gconf-service, libasound2 (>= 1.0.23), libatk1.0-0 (>= 1.12.4), libc6 (>= 2.11), libcairo2 (>= 1.6.0), libcups2 (>= 1.4.0), libdbus-1-3 (>= 1.2.14), libexpat1 (>= 1.95.8), libfontconfig1 (>= 2.8.0), libfreetype6 (>= 2.3.9), libgcc1 (>= 1:4.1.1), libgconf-2-4 (>= 2.31.1), libgcrypt11 (>= 1.4.5), libgdk-pixbuf2.0-0 (>= 2.22.0), libglib2.0-0 (>= 2.18.0), libgtk2.0-0 (>= 2.24.0), libnspr4 (>= 1.8.0.10), libnss3 (>= 3.12.6), libpango1.0-0 (>= 1.22.0), libstdc++6 (>= 4.6), libudev0 (>= 147) | libudev1 (>= 198), libx11-6 (>= 2:1.4.99.1), libxcomposite1 (>= 1:0.3-1), libxdamage1 (>= 1:1.1), libxext6, libxfixes3, libxrandr2 (>= 2:1.2.0), libxrender1, ca-certificates, libcurl3, lsb-base (>= 3.2), xdg-utils (>= 1.0.2), wget +Depends: gconf-service, libasound2 (>= 1.0.23), libatk1.0-0 (>= 1.12.4), libc6 (>= 2.11), libcairo2 (>= 1.6.0), libcups2 (>= 1.4.0), libdbus-1-3 (>= 1.2.14), libexpat1 (>= 1.95.8), libfontconfig1 (>= 2.8.0), libfreetype6 (>= 2.3.9), libgcc1 (>= 1:4.1.1), libgconf-2-4 (>= 2.31.1), libgdk-pixbuf2.0-0 (>= 2.22.0), libglib2.0-0 (>= 2.18.0), libgtk2.0-0 (>= 2.24.0), libnspr4 (>= 1.8.0.10), libnss3 (>= 3.12.6), libpango1.0-0 (>= 1.22.0), libstdc++6 (>= 4.6), libudev0 (>= 147) | libudev1 (>= 198), libx11-6 (>= 2:1.4.99.1), libxcomposite1 (>= 1:0.3-1), libxdamage1 (>= 1:1.1), libxext6, libxfixes3, libxrandr2 (>= 2:1.2.0), libxrender1, ca-certificates, libcurl3, lsb-base (>= 3.2), xdg-utils (>= 1.0.2), wget Maintainer: Brackets Team Description: Brackets Brackets is an open-source editor for web design and development diff --git a/tasks/setup.js b/tasks/setup.js index fa220cfd0..223c87b41 100644 --- a/tasks/setup.js +++ b/tasks/setup.js @@ -123,39 +123,38 @@ module.exports = function (grunt) { grunt.task.run("curl-dir:" + grunt.config("cefConfig")); }); - + + // task: icu grunt.registerTask("icu", "Download and setup ICU", function () { - if (platform === "win" || platform === "mac") { - var config = "icu-" + platform + common.arch(), - zipSrc = grunt.config("curl-dir." + config + ".src"), - zipName = path.basename(zipSrc), - zipDest = path.resolve(process.cwd(), path.join(grunt.config("curl-dir." + config + ".dest"), zipName)), - txtName; - - // extract zip file name and set config property - grunt.config("icuZipDest", zipDest); - grunt.config("icuZipSrc", zipSrc); - grunt.config("icuZipName", zipName); - grunt.config("icuConfig", config); - - // remove .zip extension - txtName = zipName.substr(0, zipName.lastIndexOf(".")) + ".txt"; - - // optionally download if ICU is not found - if (!grunt.file.exists("deps/icu/" + txtName)) { - var icuTasks = ["icu-clean", "icu-extract"]; - - if (grunt.file.exists(zipDest)) { - grunt.verbose.writeln("Found ICU download " + zipDest); - } else { - icuTasks.unshift("icu-download"); - } + var config = "icu-" + platform + common.arch(), + zipSrc = grunt.config("curl-dir." + config + ".src"), + zipName = path.basename(zipSrc), + zipDest = path.resolve(process.cwd(), path.join(grunt.config("curl-dir." + config + ".dest"), zipName)), + txtName; - grunt.task.run(icuTasks); + // extract zip file name and set config property + grunt.config("icuZipDest", zipDest); + grunt.config("icuZipSrc", zipSrc); + grunt.config("icuZipName", zipName); + grunt.config("icuConfig", config); + + // remove .zip extension + txtName = zipName.substr(0, zipName.lastIndexOf(".")) + ".txt"; + + // optionally download if ICU is not found + if (!grunt.file.exists("deps/icu/" + txtName)) { + var icuTasks = ["icu-clean", "icu-extract"]; + + if (grunt.file.exists(zipDest)) { + grunt.verbose.writeln("Found ICU download " + zipDest); } else { - grunt.verbose.writeln("Skipping ICU download. Found deps/icu/" + txtName); + icuTasks.unshift("icu-download"); } + + grunt.task.run(icuTasks); + } else { + grunt.verbose.writeln("Skipping ICU download. Found deps/icu/" + txtName); } });