// Copyright (c) 2012 The Chromium 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 "chrome/browser/ui/gtk/web_dialog_gtk.h" #include #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/gtk/gtk_util.h" #include "chrome/browser/ui/webui/chrome_web_contents_handler.h" #include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" #include "ui/web_dialogs/web_dialog_ui.h" using content::NativeWebKeyboardEvent; using content::WebContents; using content::WebUIMessageHandler; using ui::WebDialogDelegate; using ui::WebDialogUI; using ui::WebDialogWebContentsDelegate; namespace chrome { gfx::NativeWindow ShowWebDialog(gfx::NativeWindow parent, content::BrowserContext* context, WebDialogDelegate* delegate) { WebDialogGtk* web_dialog = new WebDialogGtk(context, delegate, parent); return web_dialog->InitDialog(); } } // namespace chrome namespace { void SetDialogStyle() { static bool style_was_set = false; if (style_was_set) return; style_was_set = true; gtk_rc_parse_string( "style \"chrome-html-dialog\" {\n" " GtkDialog::action-area-border = 0\n" " GtkDialog::content-area-border = 0\n" " GtkDialog::content-area-spacing = 0\n" "}\n" "widget \"*chrome-html-dialog\" style \"chrome-html-dialog\""); } } // namespace //////////////////////////////////////////////////////////////////////////////// // WebDialogGtk, public: WebDialogGtk::WebDialogGtk(content::BrowserContext* context, WebDialogDelegate* delegate, gfx::NativeWindow parent_window) : WebDialogWebContentsDelegate(context, new ChromeWebContentsHandler), delegate_(delegate), parent_window_(parent_window), dialog_(NULL) { } WebDialogGtk::~WebDialogGtk() { } //////////////////////////////////////////////////////////////////////////////// // WebDialogDelegate implementation: ui::ModalType WebDialogGtk::GetDialogModalType() const { return delegate_ ? delegate_->GetDialogModalType() : ui::MODAL_TYPE_NONE; } base::string16 WebDialogGtk::GetDialogTitle() const { return delegate_ ? delegate_->GetDialogTitle() : base::string16(); } GURL WebDialogGtk::GetDialogContentURL() const { if (delegate_) return delegate_->GetDialogContentURL(); else return GURL(); } void WebDialogGtk::GetWebUIMessageHandlers( std::vector* handlers) const { if (delegate_) delegate_->GetWebUIMessageHandlers(handlers); else handlers->clear(); } void WebDialogGtk::GetDialogSize(gfx::Size* size) const { if (delegate_) delegate_->GetDialogSize(size); else *size = gfx::Size(); } void WebDialogGtk::GetMinimumDialogSize(gfx::Size* size) const { if (delegate_) delegate_->GetMinimumDialogSize(size); else *size = gfx::Size(); } std::string WebDialogGtk::GetDialogArgs() const { if (delegate_) return delegate_->GetDialogArgs(); else return std::string(); } void WebDialogGtk::OnDialogClosed(const std::string& json_retval) { DCHECK(dialog_); Detach(); if (delegate_) { WebDialogDelegate* dialog_delegate = delegate_; delegate_ = NULL; // We will not communicate further with the delegate. // Store the dialog bounds. gfx::Rect dialog_bounds = gtk_util::GetDialogBounds(GTK_WIDGET(dialog_)); dialog_delegate->StoreDialogSize(dialog_bounds.size()); dialog_delegate->OnDialogClosed(json_retval); } gtk_widget_destroy(dialog_); delete this; } void WebDialogGtk::OnCloseContents(WebContents* source, bool* out_close_dialog) { if (delegate_) delegate_->OnCloseContents(source, out_close_dialog); } void WebDialogGtk::CloseContents(WebContents* source) { DCHECK(dialog_); bool close_dialog = false; OnCloseContents(source, &close_dialog); if (close_dialog) OnDialogClosed(std::string()); } content::WebContents* WebDialogGtk::OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) { content::WebContents* new_contents = NULL; if (delegate_ && delegate_->HandleOpenURLFromTab(source, params, &new_contents)) { return new_contents; } return WebDialogWebContentsDelegate::OpenURLFromTab(source, params); } void WebDialogGtk::AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { if (delegate_ && delegate_->HandleAddNewContents( source, new_contents, disposition, initial_pos, user_gesture)) { return; } WebDialogWebContentsDelegate::AddNewContents( source, new_contents, disposition, initial_pos, user_gesture, was_blocked); } void WebDialogGtk::LoadingStateChanged(content::WebContents* source) { if (delegate_) delegate_->OnLoadingStateChanged(source); } bool WebDialogGtk::ShouldShowDialogTitle() const { return true; } //////////////////////////////////////////////////////////////////////////////// // content::WebContentsDelegate implementation: // A simplified version of BrowserWindowGtk::HandleKeyboardEvent(). // We don't handle global keyboard shortcuts here, but that's fine since // they're all browser-specific. (This may change in the future.) void WebDialogGtk::HandleKeyboardEvent(content::WebContents* source, const NativeWebKeyboardEvent& event) { GdkEventKey* os_event = &event.os_event->key; if (!os_event || event.type == blink::WebInputEvent::Char) return; // To make sure the default key bindings can still work, such as Escape to // close the dialog. gtk_bindings_activate_event(GTK_OBJECT(dialog_), os_event); } //////////////////////////////////////////////////////////////////////////////// // WebDialogGtk: gfx::NativeWindow WebDialogGtk::InitDialog() { web_contents_.reset(WebContents::Create( WebContents::CreateParams(browser_context()))); web_contents_->SetDelegate(this); // This must be done before loading the page; see the comments in // WebDialogUI. WebDialogUI::SetDelegate(web_contents_.get(), this); web_contents_->GetController().LoadURL( GetDialogContentURL(), content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); GtkDialogFlags flags = GTK_DIALOG_NO_SEPARATOR; if (delegate_->GetDialogModalType() != ui::MODAL_TYPE_NONE) flags = static_cast(flags | GTK_DIALOG_MODAL); dialog_ = gtk_dialog_new_with_buttons( UTF16ToUTF8(delegate_->GetDialogTitle()).c_str(), parent_window_, flags, NULL); SetDialogStyle(); gtk_widget_set_name(dialog_, "chrome-html-dialog"); g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this); GtkWidget* content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog_)); gfx::NativeView web_contents_widget = web_contents_->GetView()->GetNativeView(); gtk_box_pack_start(GTK_BOX(content_area), web_contents_widget, TRUE, TRUE, 0); gfx::Size dialog_size; delegate_->GetDialogSize(&dialog_size); if (!dialog_size.IsEmpty()) { gtk_window_set_default_size(GTK_WINDOW(dialog_), dialog_size.width(), dialog_size.height()); } gfx::Size minimum_dialog_size; delegate_->GetMinimumDialogSize(&minimum_dialog_size); if (!minimum_dialog_size.IsEmpty()) { gtk_widget_set_size_request(GTK_WIDGET(web_contents_widget), minimum_dialog_size.width(), minimum_dialog_size.height()); } gtk_widget_show_all(dialog_); web_contents_->GetView()->SetInitialFocus(); return GTK_WINDOW(dialog_); } void WebDialogGtk::OnResponse(GtkWidget* dialog, int response_id) { OnDialogClosed(std::string()); }