diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-19 22:16:28 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-19 22:16:28 +0000 |
commit | e838217a07f277f8bf751aaaac6fb1005a533d47 (patch) | |
tree | f34f7f4522a9eed3a8172751fb1a3202705c16f6 /chrome/browser | |
parent | e804e052523e23df3881132ab2e31791e0c0d1b6 (diff) | |
download | chromium_src-e838217a07f277f8bf751aaaac6fb1005a533d47.zip chromium_src-e838217a07f277f8bf751aaaac6fb1005a533d47.tar.gz chromium_src-e838217a07f277f8bf751aaaac6fb1005a533d47.tar.bz2 |
GTK: HTTP Auth dialogs under linux.
- Implements a ConstrainedWindowGtk which positions itself in the center of its corresponding TabContentsViewGtk.
- Implements LoginPromptGtk. HTTP Auth now works under Linux.
- Renames ConstrainedWindowImpl to ConstrainedWindowWin
http://crbug.com/11512
Review URL: http://codereview.chromium.org/132047
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18864 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rwxr-xr-x | chrome/browser/automation/automation_provider.cc | 6 | ||||
-rw-r--r-- | chrome/browser/gtk/constrained_window_gtk.cc | 63 | ||||
-rw-r--r-- | chrome/browser/gtk/constrained_window_gtk.h | 64 | ||||
-rw-r--r-- | chrome/browser/login_prompt_gtk.cc | 312 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_dispatcher_host.cc | 5 | ||||
-rw-r--r-- | chrome/browser/tab_contents/constrained_window.h | 33 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 7 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.h | 4 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_gtk.cc | 52 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_gtk.h | 14 | ||||
-rw-r--r-- | chrome/browser/views/constrained_window_win.cc (renamed from chrome/browser/views/constrained_window_impl.cc) | 43 | ||||
-rw-r--r-- | chrome/browser/views/constrained_window_win.h (renamed from chrome/browser/views/constrained_window_impl.h) | 22 |
12 files changed, 567 insertions, 58 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 7cde178..bcfd7a5 100755 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -60,10 +60,14 @@ #include "chrome/browser/character_encoding.h" #include "chrome/browser/download/save_package.h" #include "chrome/browser/external_tab_container.h" -#include "chrome/browser/login_prompt.h" #include "chrome/browser/printing/print_job.h" #endif // defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) +// TODO(port): Port these to the mac. +#include "chrome/browser/login_prompt.h" +#endif + #if defined(OS_WIN) #include "chrome/browser/views/bookmark_bar_view.h" #include "views/widget/root_view.h" diff --git a/chrome/browser/gtk/constrained_window_gtk.cc b/chrome/browser/gtk/constrained_window_gtk.cc new file mode 100644 index 0000000..21b45b8 --- /dev/null +++ b/chrome/browser/gtk/constrained_window_gtk.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2009 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/gtk/constrained_window_gtk.h" + +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view_gtk.h" +#include "chrome/common/gtk_util.h" + +// The minimal border around the edge of the notification. +const int kSmallPadding = 2; + +ConstrainedWindowGtk::ConstrainedWindowGtk( + TabContents* owner, ConstrainedWindowGtkDelegate* delegate) + : owner_(owner), + delegate_(delegate) { + DCHECK(owner); + DCHECK(delegate); + GtkWidget* dialog = delegate->GetWidgetRoot(); + + // Unlike other users of CreateBorderBin, we need a dedicated frame around + // our "window". + GtkWidget* ebox = gtk_event_box_new(); + GtkWidget* frame = gtk_frame_new(NULL); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT); + GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), + kSmallPadding, kSmallPadding, kSmallPadding, kSmallPadding); + gtk_container_add(GTK_CONTAINER(alignment), dialog); + gtk_container_add(GTK_CONTAINER(frame), alignment); + gtk_container_add(GTK_CONTAINER(ebox), frame); + border_.Own(ebox); + + gtk_widget_show_all(border_.get()); + + // We collaborate with TabContentsViewGtk and stick ourselves in the + // TabContentsViewGtk's floating container. + ContainingView()->AttachConstrainedWindow(this); +} + +ConstrainedWindowGtk::~ConstrainedWindowGtk() { + border_.Destroy(); +} + +void ConstrainedWindowGtk::CloseConstrainedWindow() { + ContainingView()->RemoveConstrainedWindow(this); + delegate_->DeleteDelegate(); + owner_->WillClose(this); + + delete this; +} + +TabContentsViewGtk* ConstrainedWindowGtk::ContainingView() { + return static_cast<TabContentsViewGtk*>(owner_->view()); +} + +// static +ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog( + TabContents* parent, + ConstrainedWindowGtkDelegate* delegate) { + return new ConstrainedWindowGtk(parent, delegate); +} diff --git a/chrome/browser/gtk/constrained_window_gtk.h b/chrome/browser/gtk/constrained_window_gtk.h new file mode 100644 index 0000000..91fa9ac --- /dev/null +++ b/chrome/browser/gtk/constrained_window_gtk.h @@ -0,0 +1,64 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_GTK_CONSTRAINED_WINDOW_GTK_H_ +#define CHROME_BROWSER_GTK_CONSTRAINED_WINDOW_GTK_H_ + +#include "chrome/browser/tab_contents/constrained_window.h" + +#include "base/basictypes.h" +#include "chrome/common/owned_widget_gtk.h" + +class TabContents; +class TabContentsViewGtk; +typedef struct _GtkWidget GtkWidget; + +class ConstrainedWindowGtkDelegate { + public: + // Returns the widget that will be put in the constrained window's container. + virtual GtkWidget* GetWidgetRoot() = 0; + + // Tells the delegate to either delete itself or set up a task to delete + // itself later. + virtual void DeleteDelegate() = 0; +}; + +// Constrained window implementation for the GTK port. Unlike the Win32 system, +// ConstrainedWindowGtk doesn't draw draggable fake windows and instead just +// centers the dialog. It is thus an order of magnitude simpler. +class ConstrainedWindowGtk : public ConstrainedWindow { + public: + virtual ~ConstrainedWindowGtk(); + + // Overridden from ConstrainedWindow: + virtual void CloseConstrainedWindow(); + + // Returns the TabContents that constrains this Constrained Window. + TabContents* owner() const { return owner_; } + + // Returns the toplevel widget that displays this "window". + GtkWidget* widget() { return border_.get(); } + + // Returns the View that we collaborate with to position ourselves. + TabContentsViewGtk* ContainingView(); + + private: + friend class ConstrainedWindow; + + ConstrainedWindowGtk(TabContents* owner, + ConstrainedWindowGtkDelegate* delegate); + + // The TabContents that owns and constrains this ConstrainedWindow. + TabContents* owner_; + + // The top level widget container that exports to our TabContentsViewGtk. + OwnedWidgetGtk border_; + + // Delegate that provides the contents of this constrained window. + ConstrainedWindowGtkDelegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowGtk); +}; + +#endif // CHROME_BROWSER_GTK_CONSTRAINED_WINDOW_GTK_H_ diff --git a/chrome/browser/login_prompt_gtk.cc b/chrome/browser/login_prompt_gtk.cc new file mode 100644 index 0000000..f52f2ee --- /dev/null +++ b/chrome/browser/login_prompt_gtk.cc @@ -0,0 +1,312 @@ +// Copyright (c) 2009 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/login_prompt.h" + +#include <gtk/gtk.h> + +#include "app/l10n_util.h" +#include "base/message_loop.h" +#include "chrome/browser/gtk/constrained_window_gtk.h" +#include "chrome/browser/password_manager/password_manager.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/common/gtk_util.h" +#include "chrome/common/notification_service.h" +#include "grit/generated_resources.h" +#include "net/url_request/url_request.h" + +using webkit_glue::PasswordForm; + +// ---------------------------------------------------------------------------- +// LoginHandlerGtk + +// This class simply forwards the authentication from the LoginView (on +// the UI thread) to the URLRequest (on the I/O thread). +// This class uses ref counting to ensure that it lives until all InvokeLaters +// have been called. +class LoginHandlerGtk : public LoginHandler, + public base::RefCountedThreadSafe<LoginHandlerGtk>, + public ConstrainedWindowGtkDelegate { + public: + LoginHandlerGtk(URLRequest* request, MessageLoop* ui_loop) + : handled_auth_(false), + dialog_(NULL), + ui_loop_(ui_loop), + request_(request), + request_loop_(MessageLoop::current()), + password_manager_(NULL) { + DCHECK(request_) << "LoginHandlerGtk constructed with NULL request"; + + AddRef(); // matched by ReleaseLater. + if (!tab_util::GetTabContentsID(request_, &render_process_host_id_, + &tab_contents_id_)) { + NOTREACHED(); + } + } + + virtual ~LoginHandlerGtk() { + root_.Destroy(); + } + + // LoginHandler: + virtual void BuildViewForPasswordManager(PasswordManager* manager, + std::wstring explanation) { + DCHECK(MessageLoop::current() == ui_loop_); + + root_.Own(gtk_vbox_new(NULL, gtk_util::kContentAreaBorder)); + gtk_box_pack_start(GTK_BOX(root_.get()), + gtk_label_new(WideToUTF8(explanation).c_str()), + FALSE, FALSE, 0); + + username_entry_ = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(username_entry_), TRUE); + + password_entry_ = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(password_entry_), TRUE); + gtk_entry_set_visibility(GTK_ENTRY(password_entry_), FALSE); + + GtkWidget* table = gtk_util::CreateLabeledControlsGroup( + l10n_util::GetStringUTF8(IDS_LOGIN_DIALOG_USERNAME_FIELD).c_str(), + username_entry_, + l10n_util::GetStringUTF8(IDS_LOGIN_DIALOG_PASSWORD_FIELD).c_str(), + password_entry_, + NULL); + gtk_box_pack_start(GTK_BOX(root_.get()), table, FALSE, FALSE, 0); + + GtkWidget* hbox = gtk_hbox_new(FALSE, 12); + gtk_box_pack_start(GTK_BOX(root_.get()), hbox, FALSE, FALSE, 0); + + GtkWidget* ok = gtk_button_new_from_stock(GTK_STOCK_OK); + gtk_button_set_label( + GTK_BUTTON(ok), + l10n_util::GetStringUTF8(IDS_LOGIN_DIALOG_OK_BUTTON_LABEL).c_str()); + g_signal_connect(ok, "clicked", G_CALLBACK(OnOKClicked), this); + gtk_box_pack_end(GTK_BOX(hbox), ok, FALSE, FALSE, 0); + + GtkWidget* cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); + g_signal_connect(cancel, "clicked", G_CALLBACK(OnCancelClicked), this); + gtk_box_pack_end(GTK_BOX(hbox), cancel, FALSE, FALSE, 0); + + // Scary thread safety note: This can potentially be called *after* SetAuth + // or CancelAuth (say, if the request was cancelled before the UI thread got + // control). However, that's OK since any UI interaction in those functions + // will occur via an InvokeLater on the UI thread, which is guaranteed + // to happen after this is called (since this was InvokeLater'd first). + dialog_ = GetTabContentsForLogin()->CreateConstrainedDialog(this); + + // Now that we have attached ourself to the window, we can make our OK + // button the default action and mess with the focus. + GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT); + gtk_widget_grab_default(ok); + gtk_widget_grab_focus(username_entry_); + + SendNotifications(); + } + + virtual void SetPasswordForm(const webkit_glue::PasswordForm& form) { + password_form_ = form; + } + + virtual void SetPasswordManager(PasswordManager* password_manager) { + password_manager_ = password_manager; + } + + virtual TabContents* GetTabContentsForLogin() { + DCHECK(MessageLoop::current() == ui_loop_); + + return tab_util::GetTabContentsByID(render_process_host_id_, + tab_contents_id_); + } + + virtual void SetAuth(const std::wstring& username, + const std::wstring& password) { + if (WasAuthHandled(true)) + return; + + // Tell the password manager the credentials were submitted / accepted. + if (password_manager_) { + password_form_.username_value = username; + password_form_.password_value = password; + password_manager_->ProvisionallySavePassword(password_form_); + } + + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &LoginHandlerGtk::CloseContentsDeferred)); + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &LoginHandlerGtk::SendNotifications)); + request_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &LoginHandlerGtk::SetAuthDeferred, username, password)); + } + + virtual void CancelAuth() { + if (WasAuthHandled(true)) + return; + + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &LoginHandlerGtk::CloseContentsDeferred)); + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &LoginHandlerGtk::SendNotifications)); + request_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &LoginHandlerGtk::CancelAuthDeferred)); + } + + virtual void OnRequestCancelled() { + DCHECK(MessageLoop::current() == request_loop_) << + "Why is OnRequestCancelled called from the UI thread?"; + + // Reference is no longer valid. + request_ = NULL; + + // Give up on auth if the request was cancelled. + CancelAuth(); + } + + // Overridden from ConstrainedWindowGtkDelegate: + virtual GtkWidget* GetWidgetRoot() { + return root_.get(); + } + + virtual void DeleteDelegate() { + if (!WasAuthHandled(true)) { + request_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &LoginHandlerGtk::CancelAuthDeferred)); + SendNotifications(); + } + + // Delete this object once all InvokeLaters have been called. + request_loop_->ReleaseSoon(FROM_HERE, this); + } + + private: + friend class LoginPrompt; + + // Calls SetAuth from the request_loop. + void SetAuthDeferred(const std::wstring& username, + const std::wstring& password) { + DCHECK(MessageLoop::current() == request_loop_); + + if (request_) { + request_->SetAuth(username, password); + ResetLoginHandlerForRequest(request_); + } + } + + // Calls CancelAuth from the request_loop. + void CancelAuthDeferred() { + DCHECK(MessageLoop::current() == request_loop_); + + if (request_) { + request_->CancelAuth(); + // Verify that CancelAuth does destroy the request via our delegate. + DCHECK(request_ != NULL); + ResetLoginHandlerForRequest(request_); + } + } + + // Closes the view_contents from the UI loop. + void CloseContentsDeferred() { + DCHECK(MessageLoop::current() == ui_loop_); + + // The hosting ConstrainedWindow may have been freed. + if (dialog_) + dialog_->CloseConstrainedWindow(); + } + + // Returns whether authentication had been handled (SetAuth or CancelAuth). + // If |set_handled| is true, it will mark authentication as handled. + bool WasAuthHandled(bool set_handled) { + AutoLock lock(handled_auth_lock_); + bool was_handled = handled_auth_; + if (set_handled) + handled_auth_ = true; + return was_handled; + } + + // Notify observers that authentication is needed or received. The automation + // proxy uses this for testing. + void SendNotifications() { + DCHECK(MessageLoop::current() == ui_loop_); + + NotificationService* service = NotificationService::current(); + TabContents* requesting_contents = GetTabContentsForLogin(); + if (!requesting_contents) + return; + + NavigationController* controller = &requesting_contents->controller(); + + if (!WasAuthHandled(false)) { + LoginNotificationDetails details(this); + service->Notify(NotificationType::AUTH_NEEDED, + Source<NavigationController>(controller), + Details<LoginNotificationDetails>(&details)); + } else { + service->Notify(NotificationType::AUTH_SUPPLIED, + Source<NavigationController>(controller), + NotificationService::NoDetails()); + } + } + + static void OnOKClicked(GtkButton *button, LoginHandlerGtk* handler) { + DCHECK(MessageLoop::current() == handler->ui_loop_); + + handler->SetAuth( + UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(handler->username_entry_))), + UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(handler->password_entry_)))); + } + + static void OnCancelClicked(GtkButton *button, LoginHandlerGtk* handler) { + DCHECK(MessageLoop::current() == handler->ui_loop_); + handler->CancelAuth(); + } + + // True if we've handled auth (SetAuth or CancelAuth has been called). + bool handled_auth_; + Lock handled_auth_lock_; + + // The ConstrainedWindow that is hosting our LoginView. + // This should only be accessed on the ui_loop_. + ConstrainedWindow* dialog_; + + // The MessageLoop of the thread that the ChromeViewContents lives in. + MessageLoop* ui_loop_; + + // The request that wants login data. + // This should only be accessed on the request_loop_. + URLRequest* request_; + + // The MessageLoop of the thread that the URLRequest lives in. + MessageLoop* request_loop_; + + // The PasswordForm sent to the PasswordManager. This is so we can refer to it + // when later notifying the password manager if the credentials were accepted + // or rejected. + // This should only be accessed on the ui_loop_. + PasswordForm password_form_; + + // Points to the password manager owned by the TabContents requesting auth. + // Can be null if the TabContents is not a TabContents. + // This should only be accessed on the ui_loop_. + PasswordManager* password_manager_; + + // Cached from the URLRequest, in case it goes NULL on us. + int render_process_host_id_; + int tab_contents_id_; + + // The GtkWidgets that form our visual hierarchy: + // The root container we pass to our parent. + OwnedWidgetGtk root_; + + // GtkEntry widgets that the user types into. + GtkWidget* username_entry_; + GtkWidget* password_entry_; + + DISALLOW_COPY_AND_ASSIGN(LoginHandlerGtk); +}; + +// static +LoginHandler* LoginHandler::Create(URLRequest* request, MessageLoop* ui_loop) { + return new LoginHandlerGtk(request, ui_loop); +} diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index 32de83b..68e9a47 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -50,11 +50,14 @@ #if defined(OS_POSIX) #include "chrome/common/temp_scaffolding_stubs.h" #elif defined(OS_WIN) -#include "chrome/browser/login_prompt.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #endif +#if defined(OS_WIN) || defined(OS_LINUX) +#include "chrome/browser/login_prompt.h" +#endif + // Uncomment to enable logging of request traffic. // #define LOG_RESOURCE_DISPATCHER_REQUESTS diff --git a/chrome/browser/tab_contents/constrained_window.h b/chrome/browser/tab_contents/constrained_window.h index 35679a5..437f820b 100644 --- a/chrome/browser/tab_contents/constrained_window.h +++ b/chrome/browser/tab_contents/constrained_window.h @@ -8,16 +8,22 @@ #include "chrome/common/page_transition_types.h" #include "webkit/glue/window_open_disposition.h" -class ConstrainedWindow; +// The different platform specific subclasses use different delegates for their +// dialogs. +#if defined(OS_WIN) namespace views { -class View; class WindowDelegate; } -namespace gfx { -class Point; -class Rect; -} -class GURL; +typedef views::WindowDelegate ConstrainedWindowDelegate; +#elif defined(OS_LINUX) +class ConstrainedWindowGtkDelegate; +typedef ConstrainedWindowGtkDelegate ConstrainedWindowDelegate; +#elif defined(OS_MACOSX) +// TODO(port): Change this type when Mac gets ConstrainedWindows. It is here +// only to make things compile. There is no user or consumer of this type. +typedef void* ConstrainedWindowDelegate; +#endif + class TabContents; /////////////////////////////////////////////////////////////////////////////// @@ -28,18 +34,15 @@ class TabContents; // class ConstrainedWindow { public: - // Create a Constrained Window that contains a views::View subclass - // that provides the client area. Typical uses include the HTTP Basic Auth - // prompt. The caller must provide an object implementing - // views::WindowDelegate so that the Constrained Window can be properly - // configured. If |initial_bounds| is empty, the dialog will be centered - // within the constraining TabContents. + // Create a Constrained Window that contains a platform specific client + // area. Typical uses include the HTTP Basic Auth prompt. The caller must + // provide a delegate to describe the content area and to respond to events. static ConstrainedWindow* CreateConstrainedDialog( TabContents* owner, - views::WindowDelegate* window_delegate); + ConstrainedWindowDelegate* delegate); // Closes the Constrained Window. virtual void CloseConstrainedWindow() = 0; }; -#endif // #ifndef CHROME_TAB_CONTENTS_BROWSER_CONSTRAINED_WINDOW_H_ +#endif // CHROME_BROWSER_TAB_CONTENTS_CONSTRAINED_WINDOW_H_ diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index fe2ce0d..fe18cf2 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -735,12 +735,11 @@ void TabContents::CreateShortcut() { render_view_host()->GetApplicationInfo(pending_install_.page_id); } -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) ConstrainedWindow* TabContents::CreateConstrainedDialog( - views::WindowDelegate* window_delegate) { + ConstrainedWindowDelegate* delegate) { ConstrainedWindow* window = - ConstrainedWindow::CreateConstrainedDialog( - this, window_delegate); + ConstrainedWindow::CreateConstrainedDialog(this, delegate); child_windows_.push_back(window); return window; } diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index a94b6e1..04c61d5 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -323,14 +323,14 @@ class TabContents : public PageNavigator, // Window management --------------------------------------------------------- -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) // Create a new window constrained to this TabContents' clip and visibility. // The window is initialized by using the supplied delegate to obtain basic // window characteristics, and the supplied view for the content. The window // is sized according to the preferred size of the content_view, and centered // within the contents. ConstrainedWindow* CreateConstrainedDialog( - views::WindowDelegate* window_delegate); + ConstrainedWindowDelegate* delegate); #endif // Adds a new tab or window with the given already-created contents diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc index 3443b84..9b62e55 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc @@ -15,6 +15,7 @@ #include "chrome/browser/download/download_shelf.h" #include "chrome/browser/gtk/blocked_popup_container_view_gtk.h" #include "chrome/browser/gtk/browser_window_gtk.h" +#include "chrome/browser/gtk/constrained_window_gtk.h" #include "chrome/browser/gtk/gtk_floating_container.h" #include "chrome/browser/gtk/sad_tab_gtk.h" #include "chrome/browser/renderer_host/render_view_host.h" @@ -139,6 +140,28 @@ void TabContentsViewGtk::RemoveBlockedPopupView( popup_view_ = NULL; } +void TabContentsViewGtk::AttachConstrainedWindow( + ConstrainedWindowGtk* constrained_window) { + DCHECK(find(constrained_windows_.begin(), constrained_windows_.end(), + constrained_window) == constrained_windows_.end()); + + constrained_windows_.push_back(constrained_window); + gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()), + constrained_window->widget()); +} + +void TabContentsViewGtk::RemoveConstrainedWindow( + ConstrainedWindowGtk* constrained_window) { + std::vector<ConstrainedWindowGtk*>::iterator item = + find(constrained_windows_.begin(), constrained_windows_.end(), + constrained_window); + DCHECK(item != constrained_windows_.end()); + + gtk_container_remove(GTK_CONTAINER(floating_.get()), + constrained_window->widget()); + constrained_windows_.erase(item); +} + void TabContentsViewGtk::CreateView() { // Windows uses this to do initialization, but we do all our initialization // in the constructor. @@ -384,4 +407,33 @@ void TabContentsViewGtk::OnSetFloatingPosition( widget, "y", &value); g_value_unset(&value); } + + // Place each ConstrainedWindow in the center of the view. + int half_view_width = std::max((allocation->x + allocation->width) / 2, 0); + int half_view_height = std::max((allocation->y + allocation->height) / 2, 0); + std::vector<ConstrainedWindowGtk*>::iterator it = + tab_contents_view->constrained_windows_.begin(); + std::vector<ConstrainedWindowGtk*>::iterator end = + tab_contents_view->constrained_windows_.end(); + for (; it != end; ++it) { + GtkWidget* widget = (*it)->widget(); + DCHECK(widget->parent == tab_contents_view->floating_.get()); + + GtkRequisition requisition; + gtk_widget_size_request(widget, &requisition); + + GValue value = { 0, }; + g_value_init(&value, G_TYPE_INT); + + int child_x = std::max(half_view_width - (requisition.width / 2), 0); + g_value_set_int(&value, child_x); + gtk_container_child_set_property(GTK_CONTAINER(floating_container), + widget, "x", &value); + + int child_y = std::max(half_view_height - (requisition.height / 2), 0); + g_value_set_int(&value, child_y); + gtk_container_child_set_property(GTK_CONTAINER(floating_container), + widget, "y", &value); + g_value_unset(&value); + } } diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h index 8c85421..74de6dd 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.h +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h @@ -7,6 +7,8 @@ #include <gtk/gtk.h> +#include <vector> + #include "base/scoped_ptr.h" #include "chrome/browser/gtk/focus_store_gtk.h" #include "chrome/browser/tab_contents/tab_contents_view.h" @@ -15,6 +17,7 @@ #include "chrome/common/owned_widget_gtk.h" class BlockedPopupContainerViewGtk; +class ConstrainedWindowGtk; class RenderViewContextMenuGtk; class SadTabGtk; typedef struct _GtkFloatingContainer GtkFloatingContainer; @@ -33,6 +36,11 @@ class TabContentsViewGtk : public TabContentsView, void AttachBlockedPopupView(BlockedPopupContainerViewGtk* popup_view); void RemoveBlockedPopupView(BlockedPopupContainerViewGtk* popup_view); + // Unlike Windows, ConstrainedWindows need to collaborate with the + // TabContentsViewGtk to position the dialogs. + void AttachConstrainedWindow(ConstrainedWindowGtk* constrained_window); + void RemoveConstrainedWindow(ConstrainedWindowGtk* constrained_window); + // TabContentsView implementation -------------------------------------------- virtual void CreateView(); @@ -109,8 +117,14 @@ class TabContentsViewGtk : public TabContentsView, FocusStoreGtk focus_store_; + // Our UI for controlling popups (or NULL if no popup windows have been + // opened). |popup_view_| is owned by the TabContents, not the view. BlockedPopupContainerViewGtk* popup_view_; + // Each individual UI for constrained dialogs currently displayed. The + // objects in this vector are owned by the TabContents, not the view. + std::vector<ConstrainedWindowGtk*> constrained_windows_; + DISALLOW_COPY_AND_ASSIGN(TabContentsViewGtk); }; diff --git a/chrome/browser/views/constrained_window_impl.cc b/chrome/browser/views/constrained_window_win.cc index 75f3771..f641f6f 100644 --- a/chrome/browser/views/constrained_window_impl.cc +++ b/chrome/browser/views/constrained_window_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/views/constrained_window_impl.h" +#include "chrome/browser/views/constrained_window_win.h" #include "app/gfx/canvas.h" #include "app/gfx/font.h" @@ -16,7 +16,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/toolbar_model.h" #include "chrome/browser/views/frame/browser_view.h" @@ -160,7 +159,7 @@ class ConstrainedWindowFrameView : public views::NonClientFrameView, public views::ButtonListener { public: - explicit ConstrainedWindowFrameView(ConstrainedWindowImpl* container); + explicit ConstrainedWindowFrameView(ConstrainedWindowWin* container); virtual ~ConstrainedWindowFrameView(); void UpdateWindowTitle(); @@ -223,7 +222,7 @@ class ConstrainedWindowFrameView // Loads the appropriate set of WindowResources for the frame view. void InitWindowResources(); - ConstrainedWindowImpl* container_; + ConstrainedWindowWin* container_; scoped_ptr<views::WindowResources> resources_; @@ -275,7 +274,7 @@ const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); // ConstrainedWindowFrameView, public: ConstrainedWindowFrameView::ConstrainedWindowFrameView( - ConstrainedWindowImpl* container) + ConstrainedWindowWin* container) : NonClientFrameView(), container_(container), close_button_(new views::ImageButton(this)) { @@ -575,24 +574,24 @@ void ConstrainedWindowFrameView::InitClass() { } //////////////////////////////////////////////////////////////////////////////// -// ConstrainedWindowImpl, public: +// ConstrainedWindowWin, public: // The space (in pixels) between minimized pop-ups stacked horizontally and // vertically. static const int kPopupRepositionOffset = 5; static const int kConstrainedWindowEdgePadding = 10; -ConstrainedWindowImpl::~ConstrainedWindowImpl() { +ConstrainedWindowWin::~ConstrainedWindowWin() { } //////////////////////////////////////////////////////////////////////////////// -// ConstrainedWindowImpl, ConstrainedWindow implementation: +// ConstrainedWindowWin, ConstrainedWindow implementation: -views::NonClientFrameView* ConstrainedWindowImpl::CreateFrameViewForWindow() { +views::NonClientFrameView* ConstrainedWindowWin::CreateFrameViewForWindow() { return new ConstrainedWindowFrameView(this); } -void ConstrainedWindowImpl::CloseConstrainedWindow() { +void ConstrainedWindowWin::CloseConstrainedWindow() { // Broadcast to all observers of NOTIFY_CWINDOW_CLOSED. // One example of such an observer is AutomationCWindowTracker in the // automation component. @@ -603,7 +602,7 @@ void ConstrainedWindowImpl::CloseConstrainedWindow() { Close(); } -std::wstring ConstrainedWindowImpl::GetWindowTitle() const { +std::wstring ConstrainedWindowWin::GetWindowTitle() const { std::wstring display_title; if (GetDelegate()) display_title = GetDelegate()->GetWindowTitle(); @@ -613,14 +612,14 @@ std::wstring ConstrainedWindowImpl::GetWindowTitle() const { return display_title; } -const gfx::Rect& ConstrainedWindowImpl::GetCurrentBounds() const { +const gfx::Rect& ConstrainedWindowWin::GetCurrentBounds() const { return current_bounds_; } //////////////////////////////////////////////////////////////////////////////// -// ConstrainedWindowImpl, private: +// ConstrainedWindowWin, private: -ConstrainedWindowImpl::ConstrainedWindowImpl( +ConstrainedWindowWin::ConstrainedWindowWin( TabContents* owner, views::WindowDelegate* window_delegate) : WindowWin(window_delegate), @@ -636,7 +635,7 @@ ConstrainedWindowImpl::ConstrainedWindowImpl( ActivateConstrainedWindow(); } -void ConstrainedWindowImpl::ActivateConstrainedWindow() { +void ConstrainedWindowWin::ActivateConstrainedWindow() { // Other pop-ups are simply moved to the front of the z-order. SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); @@ -659,9 +658,9 @@ void ConstrainedWindowImpl::ActivateConstrainedWindow() { } //////////////////////////////////////////////////////////////////////////////// -// ConstrainedWindowImpl, views::WidgetWin overrides: +// ConstrainedWindowWin, views::WidgetWin overrides: -void ConstrainedWindowImpl::OnDestroy() { +void ConstrainedWindowWin::OnDestroy() { // We do this here, rather than |Close|, since the window may be destroyed in // a way other than by some other component calling Close, e.g. by the native // window hierarchy closing. We are guaranteed to receive a WM_DESTROY @@ -686,7 +685,7 @@ void ConstrainedWindowImpl::OnDestroy() { WindowWin::OnDestroy(); } -void ConstrainedWindowImpl::OnFinalMessage(HWND window) { +void ConstrainedWindowWin::OnFinalMessage(HWND window) { // Tell our constraining TabContents that we've gone so it can update its // list. owner_->WillClose(this); @@ -694,7 +693,7 @@ void ConstrainedWindowImpl::OnFinalMessage(HWND window) { WindowWin::OnFinalMessage(window); } -LRESULT ConstrainedWindowImpl::OnMouseActivate(HWND window, +LRESULT ConstrainedWindowWin::OnMouseActivate(HWND window, UINT hittest_code, UINT message) { // We only detach the window if the user clicked on the title bar. That @@ -708,7 +707,7 @@ LRESULT ConstrainedWindowImpl::OnMouseActivate(HWND window, return MA_ACTIVATE; } -void ConstrainedWindowImpl::OnWindowPosChanged(WINDOWPOS* window_pos) { +void ConstrainedWindowWin::OnWindowPosChanged(WINDOWPOS* window_pos) { // If the window was moved or sized, tell the owner. if (!(window_pos->flags & SWP_NOMOVE) || !(window_pos->flags & SWP_NOSIZE)) owner_->DidMoveOrResize(this); @@ -720,7 +719,7 @@ void ConstrainedWindowImpl::OnWindowPosChanged(WINDOWPOS* window_pos) { ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog( TabContents* parent, views::WindowDelegate* window_delegate) { - ConstrainedWindowImpl* window = new ConstrainedWindowImpl(parent, - window_delegate); + ConstrainedWindowWin* window = new ConstrainedWindowWin(parent, + window_delegate); return window; } diff --git a/chrome/browser/views/constrained_window_impl.h b/chrome/browser/views/constrained_window_win.h index 1afd658..a91a736 100644 --- a/chrome/browser/views/constrained_window_impl.h +++ b/chrome/browser/views/constrained_window_win.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CONSTRAINED_WINDOW_IMPL_H_ -#define CHROME_BROWSER_CONSTRAINED_WINDOW_IMPL_H_ +#ifndef CHROME_BROWSER_VIEWS_CONSTRAINED_WINDOW_WIN_H_ +#define CHROME_BROWSER_VIEWS_CONSTRAINED_WINDOW_WIN_H_ #include "base/gfx/rect.h" #include "chrome/browser/tab_contents/constrained_window.h" @@ -18,15 +18,15 @@ class WindowDelegate; } /////////////////////////////////////////////////////////////////////////////// -// ConstrainedWindowImpl +// ConstrainedWindowWin // // A ConstrainedWindow implementation that implements a Constrained Window as // a child HWND with a custom window frame. // -class ConstrainedWindowImpl : public ConstrainedWindow, +class ConstrainedWindowWin : public ConstrainedWindow, public views::WindowWin { public: - virtual ~ConstrainedWindowImpl(); + virtual ~ConstrainedWindowWin(); // Returns the TabContents that constrains this Constrained Window. TabContents* owner() const { return owner_; } @@ -51,8 +51,8 @@ class ConstrainedWindowImpl : public ConstrainedWindow, // Use the static factory methods on ConstrainedWindow to construct a // ConstrainedWindow. - ConstrainedWindowImpl(TabContents* owner, - views::WindowDelegate* window_delegate); + ConstrainedWindowWin(TabContents* owner, + views::WindowDelegate* window_delegate); // Moves this window to the front of the Z-order and registers us with the // focus manager. @@ -65,10 +65,6 @@ class ConstrainedWindowImpl : public ConstrainedWindow, // when this window is destroyed. bool focus_restoration_disabled_; - // true if this window is really a constrained dialog. This is set by - // InitAsDialog(). - bool is_dialog_; - // Current "anchor point", the lower right point at which we render // the constrained title bar. gfx::Point anchor_point_; @@ -76,7 +72,7 @@ class ConstrainedWindowImpl : public ConstrainedWindow, // Current display rectangle (relative to owner_'s visible area). gfx::Rect current_bounds_; - DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowImpl); + DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowWin); }; -#endif // #ifndef CHROME_BROWSER_CONSTRAINED_WINDOW_IMPL_H_ +#endif // #ifndef CHROME_BROWSER_VIEWS_CONSTRAINED_WINDOW_WIN_H_ |