]> git.sesse.net Git - casparcg/blobdiff - dependencies64/cef/linux/tests/cefclient/browser/dialog_handler_gtk.cc
Upgrade CEF to 3.3029.1611.g44e39a8 / Chromium 58.0.3029.81.
[casparcg] / dependencies64 / cef / linux / tests / cefclient / browser / dialog_handler_gtk.cc
diff --git a/dependencies64/cef/linux/tests/cefclient/browser/dialog_handler_gtk.cc b/dependencies64/cef/linux/tests/cefclient/browser/dialog_handler_gtk.cc
new file mode 100644 (file)
index 0000000..df66bb0
--- /dev/null
@@ -0,0 +1,434 @@
+// Copyright (c) 2015 The Chromium Embedded Framework 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 "tests/cefclient/browser/dialog_handler_gtk.h"
+
+#include <libgen.h>
+#include <sys/stat.h>
+
+#include "include/cef_browser.h"
+#include "include/cef_parser.h"
+#include "include/wrapper/cef_helpers.h"
+#include "tests/cefclient/browser/root_window.h"
+
+namespace client {
+
+namespace {
+
+const char kPromptTextId[] = "cef_prompt_text";
+
+// If there's a text entry in the dialog, get the text from the first one and
+// return it.
+std::string GetPromptText(GtkDialog* dialog) {
+  GtkWidget* widget = static_cast<GtkWidget*>(
+      g_object_get_data(G_OBJECT(dialog), kPromptTextId));
+  if (widget)
+    return gtk_entry_get_text(GTK_ENTRY(widget));
+  return std::string();
+}
+
+std::string GetDescriptionFromMimeType(const std::string& mime_type) {
+  // Check for wild card mime types and return an appropriate description.
+  static const struct {
+    const char* mime_type;
+    const char* label;
+  } kWildCardMimeTypes[] = {
+    { "audio", "Audio Files" },
+    { "image", "Image Files" },
+    { "text", "Text Files" },
+    { "video", "Video Files" },
+  };
+
+  for (size_t i = 0;
+       i < sizeof(kWildCardMimeTypes) / sizeof(kWildCardMimeTypes[0]); ++i) {
+    if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
+      return std::string(kWildCardMimeTypes[i].label);
+  }
+
+  return std::string();
+}
+
+void AddFilters(GtkFileChooser* chooser,
+                const std::vector<CefString>& accept_filters,
+                bool include_all_files,
+                std::vector<GtkFileFilter*>* filters) {
+  bool has_filter = false;
+
+  for (size_t i = 0; i < accept_filters.size(); ++i) {
+    const std::string& filter = accept_filters[i];
+    if (filter.empty())
+      continue;
+
+    std::vector<std::string> extensions;
+    std::string description;
+
+    size_t sep_index = filter.find('|');
+    if (sep_index != std::string::npos) {
+      // Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
+      description = filter.substr(0, sep_index);
+
+      const std::string& exts = filter.substr(sep_index + 1);
+      size_t last = 0;
+      size_t size = exts.size();
+      for (size_t i = 0; i <= size; ++i) {
+        if (i == size || exts[i] == ';') {
+          std::string ext(exts, last, i - last);
+          if (!ext.empty() && ext[0] == '.')
+            extensions.push_back(ext);
+          last = i + 1;
+        }
+      }
+    } else if (filter[0] == '.') {
+      // Treat as an extension beginning with the '.' character.
+      extensions.push_back(filter);
+    } else {
+      // Otherwise convert mime type to one or more extensions.
+      description = GetDescriptionFromMimeType(filter);
+
+      std::vector<CefString> ext;
+      CefGetExtensionsForMimeType(filter, ext);
+      for (size_t x = 0; x < ext.size(); ++x)
+        extensions.push_back("." + ext[x].ToString());
+    }
+
+    if (extensions.empty())
+      continue;
+
+    GtkFileFilter* gtk_filter = gtk_file_filter_new();
+
+    std::string ext_str;
+    for (size_t x = 0; x < extensions.size(); ++x) {
+      const std::string& pattern = "*" + extensions[x];
+      if (x != 0)
+        ext_str += ";";
+      ext_str += pattern;
+      gtk_file_filter_add_pattern(gtk_filter, pattern.c_str());
+    }
+
+    if (description.empty())
+      description = ext_str;
+    else
+      description += " (" + ext_str + ")";
+
+    gtk_file_filter_set_name(gtk_filter, description.c_str());
+    gtk_file_chooser_add_filter(chooser, gtk_filter);
+    if (!has_filter)
+      has_filter = true;
+
+    filters->push_back(gtk_filter);
+  }
+
+  // Add the *.* filter, but only if we have added other filters (otherwise it
+  // is implied).
+  if (include_all_files && has_filter) {
+    GtkFileFilter* filter = gtk_file_filter_new();
+    gtk_file_filter_add_pattern(filter, "*");
+    gtk_file_filter_set_name(filter, "All Files (*)");
+    gtk_file_chooser_add_filter(chooser, filter);
+  }
+}
+
+GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
+  scoped_refptr<RootWindow> root_window =
+      RootWindow::GetForBrowser(browser->GetIdentifier());
+  if (root_window) {
+    GtkWindow* window = GTK_WINDOW(root_window->GetWindowHandle());
+    if (!window)
+      LOG(ERROR) << "No GtkWindow for browser";
+    return window;
+  }
+  return NULL;
+}
+
+}  // namespace
+
+
+ClientDialogHandlerGtk::ClientDialogHandlerGtk()
+    : gtk_dialog_(NULL) {
+}
+
+bool ClientDialogHandlerGtk::OnFileDialog(
+    CefRefPtr<CefBrowser> browser,
+    FileDialogMode mode,
+    const CefString& title,
+    const CefString& default_file_path,
+    const std::vector<CefString>& accept_filters,
+    int selected_accept_filter,
+    CefRefPtr<CefFileDialogCallback> callback) {
+  std::vector<CefString> files;
+
+  GtkFileChooserAction action;
+  const gchar* accept_button;
+
+  // Remove any modifier flags.
+  FileDialogMode mode_type =
+     static_cast<FileDialogMode>(mode & FILE_DIALOG_TYPE_MASK);
+
+  if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
+    action = GTK_FILE_CHOOSER_ACTION_OPEN;
+    accept_button = GTK_STOCK_OPEN;
+  } else if (mode_type == FILE_DIALOG_OPEN_FOLDER) {
+    action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
+    accept_button = GTK_STOCK_OPEN;
+  } else if (mode_type == FILE_DIALOG_SAVE) {
+    action = GTK_FILE_CHOOSER_ACTION_SAVE;
+    accept_button = GTK_STOCK_SAVE;
+  } else {
+    NOTREACHED();
+    return false;
+  }
+
+  std::string title_str;
+  if (!title.empty()) {
+    title_str = title;
+  } else {
+    switch (mode_type) {
+      case FILE_DIALOG_OPEN:
+        title_str = "Open File";
+        break;
+      case FILE_DIALOG_OPEN_MULTIPLE:
+        title_str = "Open Files";
+        break;
+      case FILE_DIALOG_OPEN_FOLDER:
+        title_str = "Open Folder";
+        break;
+      case FILE_DIALOG_SAVE:
+        title_str = "Save File";
+        break;
+      default:
+        break;
+    }
+  }
+
+  GtkWindow* window = GetWindow(browser);
+  if (!window)
+    return false;
+
+  GtkWidget* dialog = gtk_file_chooser_dialog_new(
+      title_str.c_str(),
+      GTK_WINDOW(window),
+      action,
+      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+      accept_button, GTK_RESPONSE_ACCEPT,
+      NULL);
+
+  if (mode_type == FILE_DIALOG_OPEN_MULTIPLE)
+    gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
+
+  if (mode_type == FILE_DIALOG_SAVE) {
+    gtk_file_chooser_set_do_overwrite_confirmation(
+        GTK_FILE_CHOOSER(dialog),
+        !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG));
+  }
+
+  gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),
+                                   !(mode & FILE_DIALOG_HIDEREADONLY_FLAG));
+
+  if (!default_file_path.empty() && mode_type == FILE_DIALOG_SAVE) {
+    const std::string& file_path = default_file_path;
+    bool exists = false;
+
+    struct stat sb;
+    if (stat(file_path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)) {
+      // Use the directory and name of the existing file.
+      gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
+                                    file_path.data());
+      exists = true;
+    }
+
+    if (!exists) {
+      // Set the current file name but let the user choose the directory.
+      std::string file_name_str = file_path;
+      const char* file_name = basename(const_cast<char*>(file_name_str.data()));
+      gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), file_name);
+    }
+  }
+
+  std::vector<GtkFileFilter*> filters;
+  AddFilters(GTK_FILE_CHOOSER(dialog), accept_filters, true, &filters);
+  if (selected_accept_filter < static_cast<int>(filters.size())) {
+    gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog),
+                                filters[selected_accept_filter]);
+  }
+
+  bool success = false;
+
+  if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+    if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_FOLDER ||
+        mode_type == FILE_DIALOG_SAVE) {
+      char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+      files.push_back(std::string(filename));
+      success = true;
+    } else if (mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
+      GSList* filenames =
+          gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
+      if (filenames) {
+        for (GSList* iter = filenames; iter != NULL;
+             iter = g_slist_next(iter)) {
+          std::string path(static_cast<char*>(iter->data));
+          g_free(iter->data);
+          files.push_back(path);
+        }
+        g_slist_free(filenames);
+        success = true;
+      }
+    }
+  }
+
+  int filter_index = selected_accept_filter;
+  if (success) {
+    GtkFileFilter* selected_filter =
+        gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
+    if (selected_filter != NULL) {
+      for (size_t x = 0; x < filters.size(); ++x) {
+        if (filters[x] == selected_filter) {
+          filter_index = x;
+          break;
+        }
+      }
+    }
+  }
+
+  gtk_widget_destroy(dialog);
+
+  if (success)
+    callback->Continue(filter_index, files);
+  else
+    callback->Cancel();
+
+  return true;
+}
+
+bool ClientDialogHandlerGtk::OnJSDialog(
+    CefRefPtr<CefBrowser> browser,
+    const CefString& origin_url,
+    JSDialogType dialog_type,
+    const CefString& message_text,
+    const CefString& default_prompt_text,
+    CefRefPtr<CefJSDialogCallback> callback,
+    bool& suppress_message) {
+  CEF_REQUIRE_UI_THREAD();
+
+  GtkButtonsType buttons = GTK_BUTTONS_NONE;
+  GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER;
+  std::string title;
+
+  switch (dialog_type) {
+    case JSDIALOGTYPE_ALERT:
+      buttons = GTK_BUTTONS_NONE;
+      gtk_message_type = GTK_MESSAGE_WARNING;
+      title = "JavaScript Alert";
+      break;
+
+    case JSDIALOGTYPE_CONFIRM:
+      buttons = GTK_BUTTONS_CANCEL;
+      gtk_message_type = GTK_MESSAGE_QUESTION;
+      title = "JavaScript Confirm";
+      break;
+
+    case JSDIALOGTYPE_PROMPT:
+      buttons = GTK_BUTTONS_CANCEL;
+      gtk_message_type = GTK_MESSAGE_QUESTION;
+      title = "JavaScript Prompt";
+      break;
+  }
+
+  js_dialog_callback_ = callback;
+
+  if (!origin_url.empty()) {
+    title += " - ";
+    title += CefFormatUrlForSecurityDisplay(origin_url).ToString();
+  }
+
+  GtkWindow* window = GetWindow(browser);
+  if (!window)
+    return false;
+
+  gtk_dialog_ = gtk_message_dialog_new(GTK_WINDOW(window),
+                                       GTK_DIALOG_MODAL,
+                                       gtk_message_type,
+                                       buttons,
+                                       "%s",
+                                       message_text.ToString().c_str());
+  g_signal_connect(gtk_dialog_,
+                   "delete-event",
+                   G_CALLBACK(gtk_widget_hide_on_delete),
+                   NULL);
+
+  gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str());
+
+  GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
+                                               GTK_STOCK_OK,
+                                               GTK_RESPONSE_OK);
+
+  if (dialog_type != JSDIALOGTYPE_PROMPT)
+    gtk_widget_grab_focus(ok_button);
+
+  if (dialog_type == JSDIALOGTYPE_PROMPT) {
+    GtkWidget* content_area =
+        gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_));
+    GtkWidget* text_box = gtk_entry_new();
+    gtk_entry_set_text(GTK_ENTRY(text_box),
+                       default_prompt_text.ToString().c_str());
+    gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0);
+    g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
+    gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
+  }
+
+  gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK);
+  g_signal_connect(gtk_dialog_, "response", G_CALLBACK(OnDialogResponse), this);
+  gtk_widget_show_all(GTK_WIDGET(gtk_dialog_));
+
+  return true;
+}
+
+bool ClientDialogHandlerGtk::OnBeforeUnloadDialog(
+    CefRefPtr<CefBrowser> browser,
+    const CefString& message_text,
+    bool is_reload,
+    CefRefPtr<CefJSDialogCallback> callback) {
+  CEF_REQUIRE_UI_THREAD();
+
+  const std::string& new_message_text =
+      message_text.ToString() + "\n\nIs it OK to leave/reload this page?";
+  bool suppress_message = false;
+
+  return OnJSDialog(browser, CefString(), JSDIALOGTYPE_CONFIRM,
+                    new_message_text, CefString(), callback, suppress_message);
+}
+
+void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (!gtk_dialog_)
+    return;
+  gtk_widget_destroy(gtk_dialog_);
+  gtk_dialog_ = NULL;
+  js_dialog_callback_ = NULL;
+}
+
+// static
+void ClientDialogHandlerGtk::OnDialogResponse(GtkDialog* dialog,
+                                              gint response_id,
+                                              ClientDialogHandlerGtk* handler) {
+  CEF_REQUIRE_UI_THREAD();
+
+  DCHECK_EQ(dialog, GTK_DIALOG(handler->gtk_dialog_));
+  switch (response_id) {
+    case GTK_RESPONSE_OK:
+      handler->js_dialog_callback_->Continue(true, GetPromptText(dialog));
+      break;
+    case GTK_RESPONSE_CANCEL:
+    case GTK_RESPONSE_DELETE_EVENT:
+      handler->js_dialog_callback_->Continue(false, CefString());
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  handler->OnResetDialogState(NULL);
+}
+
+}  // namespace client
+