Commit cafd0add authored by wittman@chromium.org's avatar wittman@chromium.org

Implement WebContentsModalDialogManagerDelegate for ShellWindow

Use the web contents modal dialog positioning abstraction for app shell
windows. Implement support for Views and Gtk, stubs for Cocoa.

This abstraction will support the use of WebContents in code outside of
src/chrome/browser by allowing dialogs modal to web contents to be hosted on any
window containing a WebContents and giving the host control over the
positioning, without the host having to know the type of the dialog and vice
versa. The interface has already been implemented for the browser window; this
implements it for the other window that currently hosts WebContents,
ShellWindow.


BUG=157161, 225945


Review URL: https://chromiumcodereview.appspot.com/13588007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192878 0039d316-1c4b-4281-b951-d872f2087c98
parent 8b1058bb
...@@ -113,6 +113,13 @@ class NativeAppWindowCocoa : public NativeAppWindow { ...@@ -113,6 +113,13 @@ class NativeAppWindowCocoa : public NativeAppWindow {
virtual void RenderViewHostChanged() OVERRIDE; virtual void RenderViewHostChanged() OVERRIDE;
virtual gfx::Insets GetFrameInsets() const OVERRIDE; virtual gfx::Insets GetFrameInsets() const OVERRIDE;
// WebContentsModalDialogHost implementation.
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual void AddObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE;
private: private:
virtual ~NativeAppWindowCocoa(); virtual ~NativeAppWindowCocoa();
......
...@@ -693,6 +693,21 @@ gfx::Insets NativeAppWindowCocoa::GetFrameInsets() const { ...@@ -693,6 +693,21 @@ gfx::Insets NativeAppWindowCocoa::GetFrameInsets() const {
return frame_rect.InsetsFrom(content_rect); return frame_rect.InsetsFrom(content_rect);
} }
gfx::Point NativeAppWindowCocoa::GetDialogPosition(const gfx::Size& size) {
NOTIMPLEMENTED();
return gfx::Point();
}
void NativeAppWindowCocoa::AddObserver(
WebContentsModalDialogHostObserver* observer) {
NOTIMPLEMENTED();
}
void NativeAppWindowCocoa::RemoveObserver(
WebContentsModalDialogHostObserver* observer) {
NOTIMPLEMENTED();
}
void NativeAppWindowCocoa::WindowWillClose() { void NativeAppWindowCocoa::WindowWillClose() {
[window_controller_ setAppWindow:NULL]; [window_controller_ setAppWindow:NULL];
shell_window_->OnNativeWindowChanged(); shell_window_->OnNativeWindowChanged();
......
...@@ -7,12 +7,13 @@ ...@@ -7,12 +7,13 @@
#include "chrome/browser/ui/base_window.h" #include "chrome/browser/ui/base_window.h"
#include "chrome/browser/ui/extensions/shell_window.h" #include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/browser/ui/web_contents_modal_dialog_host.h"
#include "ui/gfx/insets.h" #include "ui/gfx/insets.h"
// This is an interface to a native implementation of a shell window, used for // This is an interface to a native implementation of a shell window, used for
// new-style packaged apps. Shell windows contain a web contents, but no tabs // new-style packaged apps. Shell windows contain a web contents, but no tabs
// or URL bar. // or URL bar.
class NativeAppWindow : public BaseWindow { class NativeAppWindow : public BaseWindow, public WebContentsModalDialogHost {
public: public:
// Used by ShellWindow to instantiate the platform-specific ShellWindow code. // Used by ShellWindow to instantiate the platform-specific ShellWindow code.
static NativeAppWindow* Create(ShellWindow* window, static NativeAppWindow* Create(ShellWindow* window,
......
...@@ -109,6 +109,8 @@ void ShellWindow::Init(const GURL& url, ...@@ -109,6 +109,8 @@ void ShellWindow::Init(const GURL& url,
FaviconTabHelper::CreateForWebContents(web_contents); FaviconTabHelper::CreateForWebContents(web_contents);
web_contents->SetDelegate(this); web_contents->SetDelegate(this);
WebContentsModalDialogManager::FromWebContents(web_contents)->
set_delegate(this);
extensions::SetViewType(web_contents, extensions::VIEW_TYPE_APP_SHELL); extensions::SetViewType(web_contents, extensions::VIEW_TYPE_APP_SHELL);
// Initialize the window // Initialize the window
...@@ -500,6 +502,14 @@ extensions::ActiveTabPermissionGranter* ...@@ -500,6 +502,14 @@ extensions::ActiveTabPermissionGranter*
return NULL; return NULL;
} }
void ShellWindow::SetWebContentsBlocked(content::WebContents* web_contents,
bool blocked) {
}
WebContentsModalDialogHost* ShellWindow::GetWebContentsModalDialogHost() {
return native_app_window_.get();
}
void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level, void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level,
const std::string& message) { const std::string& message) {
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "chrome/browser/extensions/extension_keybinding_registry.h" #include "chrome/browser/extensions/extension_keybinding_registry.h"
#include "chrome/browser/sessions/session_id.h" #include "chrome/browser/sessions/session_id.h"
#include "chrome/browser/ui/base_window.h" #include "chrome/browser/ui/base_window.h"
#include "chrome/browser/ui/web_contents_modal_dialog_manager_delegate.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_delegate.h"
...@@ -64,7 +65,8 @@ class ShellWindowContents { ...@@ -64,7 +65,8 @@ class ShellWindowContents {
// have a WebContents but none of the chrome of normal browser windows. // have a WebContents but none of the chrome of normal browser windows.
class ShellWindow : public content::NotificationObserver, class ShellWindow : public content::NotificationObserver,
public content::WebContentsDelegate, public content::WebContentsDelegate,
public extensions::ExtensionKeybindingRegistry::Delegate { public extensions::ExtensionKeybindingRegistry::Delegate,
public WebContentsModalDialogManagerDelegate {
public: public:
enum WindowType { enum WindowType {
WINDOW_TYPE_DEFAULT = 1 << 0, // Default shell window. WINDOW_TYPE_DEFAULT = 1 << 0, // Default shell window.
...@@ -247,6 +249,12 @@ class ShellWindow : public content::NotificationObserver, ...@@ -247,6 +249,12 @@ class ShellWindow : public content::NotificationObserver,
virtual extensions::ActiveTabPermissionGranter* virtual extensions::ActiveTabPermissionGranter*
GetActiveTabPermissionGranter() OVERRIDE; GetActiveTabPermissionGranter() OVERRIDE;
// WebContentsModalDialogManagerDelegate implementation.
virtual void SetWebContentsBlocked(content::WebContents* web_contents,
bool blocked) OVERRIDE;
virtual WebContentsModalDialogHost* GetWebContentsModalDialogHost() OVERRIDE;
// Callback from web_contents()->DownloadFavicon. // Callback from web_contents()->DownloadFavicon.
void DidDownloadFavicon(int id, void DidDownloadFavicon(int id,
const GURL& image_url, const GURL& image_url,
......
...@@ -287,6 +287,24 @@ gfx::Insets NativeAppWindowGtk::GetFrameInsets() const { ...@@ -287,6 +287,24 @@ gfx::Insets NativeAppWindowGtk::GetFrameInsets() const {
rect_with_decorations.width - current_width - left_inset); rect_with_decorations.width - current_width - left_inset);
} }
gfx::Point NativeAppWindowGtk::GetDialogPosition(const gfx::Size& size) {
gint current_width = 0;
gint current_height = 0;
gtk_window_get_size(window_, &current_width, &current_height);
return gfx::Point(current_width / 2 - size.width() / 2,
current_height / 2 - size.height() / 2);
}
void NativeAppWindowGtk::AddObserver(
WebContentsModalDialogHostObserver* observer) {
observer_list_.AddObserver(observer);
}
void NativeAppWindowGtk::RemoveObserver(
WebContentsModalDialogHostObserver* observer) {
observer_list_.RemoveObserver(observer);
}
void NativeAppWindowGtk::ActiveWindowChanged(GdkWindow* active_window) { void NativeAppWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
// Do nothing if we're in the process of closing the browser window. // Do nothing if we're in the process of closing the browser window.
if (!window_) if (!window_)
...@@ -336,6 +354,10 @@ gboolean NativeAppWindowGtk::OnConfigure(GtkWidget* widget, ...@@ -336,6 +354,10 @@ gboolean NativeAppWindowGtk::OnConfigure(GtkWidget* widget,
void NativeAppWindowGtk::OnDebouncedBoundsChanged() { void NativeAppWindowGtk::OnDebouncedBoundsChanged() {
gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_); gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_);
shell_window_->OnNativeWindowChanged(); shell_window_->OnNativeWindowChanged();
FOR_EACH_OBSERVER(WebContentsModalDialogHostObserver,
observer_list_,
OnPositionRequiresUpdate());
} }
gboolean NativeAppWindowGtk::OnWindowState(GtkWidget* sender, gboolean NativeAppWindowGtk::OnWindowState(GtkWidget* sender,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "base/observer_list.h"
#include "base/timer.h" #include "base/timer.h"
#include "chrome/browser/ui/extensions/native_app_window.h" #include "chrome/browser/ui/extensions/native_app_window.h"
#include "chrome/browser/ui/extensions/shell_window.h" #include "chrome/browser/ui/extensions/shell_window.h"
...@@ -67,6 +68,13 @@ class NativeAppWindowGtk : public NativeAppWindow, ...@@ -67,6 +68,13 @@ class NativeAppWindowGtk : public NativeAppWindow,
virtual void RenderViewHostChanged() OVERRIDE; virtual void RenderViewHostChanged() OVERRIDE;
virtual gfx::Insets GetFrameInsets() const OVERRIDE; virtual gfx::Insets GetFrameInsets() const OVERRIDE;
// WebContentsModalDialogHost implementation.
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual void AddObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE;
content::WebContents* web_contents() const { content::WebContents* web_contents() const {
return shell_window_->web_contents(); return shell_window_->web_contents();
} }
...@@ -140,6 +148,10 @@ class NativeAppWindowGtk : public NativeAppWindow, ...@@ -140,6 +148,10 @@ class NativeAppWindowGtk : public NativeAppWindow,
// into events and sent to the extension. // into events and sent to the extension.
scoped_ptr<ExtensionKeybindingRegistryGtk> extension_keybinding_registry_; scoped_ptr<ExtensionKeybindingRegistryGtk> extension_keybinding_registry_;
// Observers to be notified when any web contents modal dialog requires
// updating its dimensions.
ObserverList<WebContentsModalDialogHostObserver> observer_list_;
DISALLOW_COPY_AND_ASSIGN(NativeAppWindowGtk); DISALLOW_COPY_AND_ASSIGN(NativeAppWindowGtk);
}; };
......
...@@ -92,6 +92,8 @@ class WebContentsModalDialogHostObserverViews ...@@ -92,6 +92,8 @@ class WebContentsModalDialogHostObserverViews
: host_(host), : host_(host),
target_widget_(target_widget), target_widget_(target_widget),
native_window_property_(native_window_property) { native_window_property_(native_window_property) {
DCHECK(host_);
DCHECK(target_widget_);
host_->AddObserver(this); host_->AddObserver(this);
target_widget_->AddObserver(this); target_widget_->AddObserver(this);
} }
......
...@@ -383,6 +383,21 @@ gfx::Insets NativeAppWindowViews::GetFrameInsets() const { ...@@ -383,6 +383,21 @@ gfx::Insets NativeAppWindowViews::GetFrameInsets() const {
return window_bounds.InsetsFrom(client_bounds); return window_bounds.InsetsFrom(client_bounds);
} }
gfx::Point NativeAppWindowViews::GetDialogPosition(const gfx::Size& size) {
gfx::Size shell_window_size = window_->GetWindowBoundsInScreen().size();
return gfx::Point(shell_window_size.width() / 2 - size.width() / 2,
shell_window_size.height() / 2 - size.height() / 2);
}
void NativeAppWindowViews::AddObserver(
WebContentsModalDialogHostObserver* observer) {
observer_list_.AddObserver(observer);
}
void NativeAppWindowViews::RemoveObserver(
WebContentsModalDialogHostObserver* observer) {
observer_list_.RemoveObserver(observer);
}
// Private method. TODO(stevenjb): Move this below InitializePanelWindow() // Private method. TODO(stevenjb): Move this below InitializePanelWindow()
// to match declaration order. // to match declaration order.
void NativeAppWindowViews::OnViewWasResized() { void NativeAppWindowViews::OnViewWasResized() {
...@@ -436,6 +451,10 @@ void NativeAppWindowViews::OnViewWasResized() { ...@@ -436,6 +451,10 @@ void NativeAppWindowViews::OnViewWasResized() {
if (web_contents()->GetRenderViewHost()->GetView()) if (web_contents()->GetRenderViewHost()->GetView())
web_contents()->GetRenderViewHost()->GetView()->SetClickthroughRegion(rgn); web_contents()->GetRenderViewHost()->GetView()->SetClickthroughRegion(rgn);
#endif #endif
FOR_EACH_OBSERVER(WebContentsModalDialogHostObserver,
observer_list_,
OnPositionRequiresUpdate());
} }
// WidgetDelegate implementation. // WidgetDelegate implementation.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_NATIVE_APP_WINDOW_VIEWS_H_ #ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_NATIVE_APP_WINDOW_VIEWS_H_
#define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_NATIVE_APP_WINDOW_VIEWS_H_ #define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_NATIVE_APP_WINDOW_VIEWS_H_
#include "base/observer_list.h"
#include "chrome/browser/ui/base_window.h" #include "chrome/browser/ui/base_window.h"
#include "chrome/browser/ui/extensions/native_app_window.h" #include "chrome/browser/ui/extensions/native_app_window.h"
#include "chrome/browser/ui/extensions/shell_window.h" #include "chrome/browser/ui/extensions/shell_window.h"
...@@ -135,6 +136,13 @@ class NativeAppWindowViews : public NativeAppWindow, ...@@ -135,6 +136,13 @@ class NativeAppWindowViews : public NativeAppWindow,
virtual void RenderViewHostChanged() OVERRIDE; virtual void RenderViewHostChanged() OVERRIDE;
virtual gfx::Insets GetFrameInsets() const OVERRIDE; virtual gfx::Insets GetFrameInsets() const OVERRIDE;
// WebContentsModalDialogHost implementation.
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual void AddObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE;
Profile* profile() { return shell_window_->profile(); } Profile* profile() { return shell_window_->profile(); }
content::WebContents* web_contents() { content::WebContents* web_contents() {
return shell_window_->web_contents(); return shell_window_->web_contents();
...@@ -164,6 +172,8 @@ class NativeAppWindowViews : public NativeAppWindow, ...@@ -164,6 +172,8 @@ class NativeAppWindowViews : public NativeAppWindow,
base::WeakPtrFactory<NativeAppWindowViews> weak_ptr_factory_; base::WeakPtrFactory<NativeAppWindowViews> weak_ptr_factory_;
ObserverList<WebContentsModalDialogHostObserver> observer_list_;
DISALLOW_COPY_AND_ASSIGN(NativeAppWindowViews); DISALLOW_COPY_AND_ASSIGN(NativeAppWindowViews);
}; };
......
...@@ -104,7 +104,31 @@ class NativeWebContentsModalDialogManagerViews ...@@ -104,7 +104,31 @@ class NativeWebContentsModalDialogManagerViews
} }
// views::WidgetObserver overrides // views::WidgetObserver overrides
// NOTE(wittman): OnWidgetClosing is overriden to ensure that, when the widget
// is explicitly closed, the destruction occurs within the same call
// stack. This avoids event races that lead to non-deterministic destruction
// ordering in e.g. the print preview dialog. OnWidgetDestroying is overridden
// because OnWidgetClosing is *only* invoked on explicit close, not when the
// widget is implicitly destroyed due to its parent being closed. This
// situation occurs with app windows. WidgetClosing removes the observer, so
// only one of these two functions is ever invoked for a given widget.
virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE { virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE {
WidgetClosing(widget);
}
virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
WidgetClosing(widget);
}
private:
static views::Widget* GetWidget(NativeWebContentsModalDialog dialog) {
views::Widget* widget = views::Widget::GetWidgetForNativeWindow(dialog);
DCHECK(widget);
return widget;
}
void WidgetClosing(views::Widget* widget) {
#if defined(USE_ASH) #if defined(USE_ASH)
gfx::NativeView view = platform_util::GetParent(widget->GetNativeView()); gfx::NativeView view = platform_util::GetParent(widget->GetNativeView());
// Allow the parent to animate again. // Allow the parent to animate again.
...@@ -116,13 +140,6 @@ class NativeWebContentsModalDialogManagerViews ...@@ -116,13 +140,6 @@ class NativeWebContentsModalDialogManagerViews
observed_widgets_.erase(widget); observed_widgets_.erase(widget);
} }
private:
static views::Widget* GetWidget(NativeWebContentsModalDialog dialog) {
views::Widget* widget = views::Widget::GetWidgetForNativeWindow(dialog);
DCHECK(widget);
return widget;
}
NativeWebContentsModalDialogManagerDelegate* native_delegate_; NativeWebContentsModalDialogManagerDelegate* native_delegate_;
std::set<views::Widget*> observed_widgets_; std::set<views::Widget*> observed_widgets_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment