diff options
14 files changed, 98 insertions, 134 deletions
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 6eeb05f..88f6b93 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -478,14 +478,6 @@ gfx::NativeWindow ExtensionHost::GetDialogRootWindow() { return NULL; } -TabContents* ExtensionHost::AsTabContents() { - return NULL; -} - -ExtensionHost* ExtensionHost::AsExtensionHost() { - return this; -} - void ExtensionHost::OnDialogClosed(IPC::Message* reply_msg, bool success, const string16& user_input) { diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index b7c597a..b78895d 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -192,8 +192,6 @@ class ExtensionHost : public RenderViewHostDelegate, bool success, const string16& user_input) OVERRIDE; virtual gfx::NativeWindow GetDialogRootWindow() OVERRIDE; - virtual TabContents* AsTabContents() OVERRIDE; - virtual ExtensionHost* AsExtensionHost() OVERRIDE; protected: // Internal functions used to support the CreateNewWidget() method. If a diff --git a/chrome/browser/tab_contents/background_contents.cc b/chrome/browser/tab_contents/background_contents.cc index 5898b55..b7fa507 100644 --- a/chrome/browser/tab_contents/background_contents.cc +++ b/chrome/browser/tab_contents/background_contents.cc @@ -150,14 +150,6 @@ gfx::NativeWindow BackgroundContents::GetDialogRootWindow() { return NULL; } -TabContents* BackgroundContents::AsTabContents() { - return NULL; -} - -ExtensionHost* BackgroundContents::AsExtensionHost() { - return NULL; -} - void BackgroundContents::UpdateInspectorSetting(const std::string& key, const std::string& value) { Profile* profile = render_view_host_->process()->profile(); diff --git a/chrome/browser/tab_contents/background_contents.h b/chrome/browser/tab_contents/background_contents.h index 84349dd..6552632 100644 --- a/chrome/browser/tab_contents/background_contents.h +++ b/chrome/browser/tab_contents/background_contents.h @@ -129,8 +129,6 @@ class BackgroundContents : public RenderViewHostDelegate, bool success, const string16& user_input) OVERRIDE; virtual gfx::NativeWindow GetDialogRootWindow() OVERRIDE; - virtual TabContents* AsTabContents() OVERRIDE; - virtual ExtensionHost* AsExtensionHost() OVERRIDE; virtual void UpdateInspectorSetting(const std::string& key, const std::string& value); diff --git a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.cc b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.cc index 257def3..9c54657 100644 --- a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.cc +++ b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.cc @@ -6,14 +6,15 @@ #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h" #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" +#include "content/browser/javascript_dialogs.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/common/notification_service.h" #include "content/common/notification_type.h" -AppModalDialog::AppModalDialog(TabContents* tab_contents, +AppModalDialog::AppModalDialog(content::DialogDelegate* delegate, const string16& title) - : skip_this_dialog_(false), - tab_contents_(tab_contents), + : valid_(true), + delegate_(delegate), native_dialog_(NULL), title_(title) { } @@ -22,8 +23,8 @@ AppModalDialog::~AppModalDialog() { } void AppModalDialog::ShowModalDialog() { - if (tab_contents_) - tab_contents_->Activate(); + if (delegate_) + delegate_->OnDialogShown(); CreateAndShowDialog(); @@ -39,13 +40,21 @@ void AppModalDialog::CreateAndShowDialog() { } bool AppModalDialog::IsValid() { - return !skip_this_dialog_; + return valid_; +} + +void AppModalDialog::Invalidate() { + valid_ = false; } bool AppModalDialog::IsJavaScriptModalDialog() { return false; } +content::DialogDelegate* AppModalDialog::delegate() const { + return delegate_; +} + void AppModalDialog::ActivateModalDialog() { DCHECK(native_dialog_); native_dialog_->ActivateAppModalDialog(); diff --git a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h index 8d09d48..54c1487 100644 --- a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h +++ b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h @@ -13,7 +13,10 @@ #include "build/build_config.h" class NativeAppModalDialog; -class TabContents; + +namespace content { +class DialogDelegate; +} // A controller+model base class for modal dialogs. class AppModalDialog { @@ -21,7 +24,7 @@ class AppModalDialog { // A union of data necessary to determine the type of message box to // show. |tab_contents| parameter is optional, if provided that tab will be // activated before the modal dialog is displayed. - AppModalDialog(TabContents* tab_contents, const string16& title); + AppModalDialog(content::DialogDelegate* delegate, const string16& title); virtual ~AppModalDialog(); // Called by the AppModalDialogQueue to show this dialog. @@ -42,35 +45,41 @@ class AppModalDialog { NativeAppModalDialog* native_dialog() const { return native_dialog_; } - // Methods overridable by AppModalDialog subclasses: - // Creates an implementation of NativeAppModalDialog and shows it. // When the native dialog is closed, the implementation of // NativeAppModalDialog should call OnAccept or OnCancel to notify the // renderer of the user's action. The NativeAppModalDialog is also // expected to delete the AppModalDialog associated with it. - virtual void CreateAndShowDialog(); + void CreateAndShowDialog(); // Returns true if the dialog is still valid. As dialogs are created they are // added to the AppModalDialogQueue. When the current modal dialog finishes // and it's time to show the next dialog in the queue IsValid is invoked. // If IsValid returns false the dialog is deleted and not shown. - virtual bool IsValid(); + bool IsValid(); + + // Methods overridable by AppModalDialog subclasses: + + // Invalidates the dialog, therefore causing it to not be shown when its turn + // to be shown comes around. + virtual void Invalidate(); // Used only for testing. Returns whether the dialog is a JavaScript modal // dialog. virtual bool IsJavaScriptModalDialog(); + virtual content::DialogDelegate* delegate() const; + protected: // Overridden by subclasses to create the feature-specific native dialog box. virtual NativeAppModalDialog* CreateNativeDialog() = 0; - // True if the dialog should no longer be shown, e.g. because the underlying + // False if the dialog should no longer be shown, e.g. because the underlying // tab navigated away while the dialog was queued. - bool skip_this_dialog_; + bool valid_; - // Parent tab contents. - TabContents* tab_contents_; + // The owner of this dialog. + content::DialogDelegate* delegate_; // The toolkit-specific implementation of the app modal dialog box. NativeAppModalDialog* native_dialog_; diff --git a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.cc b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.cc index fe0ee43..1d09850 100644 --- a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.cc +++ b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.cc @@ -11,7 +11,7 @@ void AppModalDialogQueue::AddDialog(AppModalDialog* dialog) { ShowModalDialog(dialog); return; } - app_modal_dialog_queue_.push(dialog); + app_modal_dialog_queue_.push_back(dialog); } void AppModalDialogQueue::ShowNextDialog() { @@ -60,7 +60,7 @@ void AppModalDialogQueue::ShowModalDialog(AppModalDialog* dialog) { AppModalDialog* AppModalDialogQueue::GetNextDialog() { while (!app_modal_dialog_queue_.empty()) { AppModalDialog* dialog = app_modal_dialog_queue_.front(); - app_modal_dialog_queue_.pop(); + app_modal_dialog_queue_.pop_front(); if (dialog->IsValid()) return dialog; delete dialog; diff --git a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h index be24a74..52510ef 100644 --- a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h +++ b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -6,7 +6,7 @@ #define CHROME_BROWSER_UI_APP_MODAL_DIALOGS_APP_MODAL_DIALOG_QUEUE_H_ #pragma once -#include <queue> +#include <deque> #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" @@ -56,6 +56,16 @@ class AppModalDialogQueue { return active_dialog_; } + // Iterators to walk the queue. + typedef std::deque<AppModalDialog*>::iterator iterator; + iterator begin() { + return app_modal_dialog_queue_.begin(); + } + + iterator end() { + return app_modal_dialog_queue_.end(); + } + private: friend struct DefaultSingletonTraits<AppModalDialogQueue>; @@ -73,7 +83,7 @@ class AppModalDialogQueue { // Contains all app modal dialogs which are waiting to be shown, with the // currently modal dialog at the front of the queue. - std::queue<AppModalDialog*> app_modal_dialog_queue_; + std::deque<AppModalDialog*> app_modal_dialog_queue_; // The currently active app-modal dialog box's delegate. NULL if there is no // active app-modal dialog box. diff --git a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc index 2714272..be579cd 100644 --- a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc +++ b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc @@ -4,14 +4,8 @@ #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" #include "chrome/browser/browser_shutdown.h" -#include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" -#include "content/browser/tab_contents/tab_contents.h" -#include "content/common/notification_service.h" -#include "content/common/notification_type.h" #include "ui/base/text/text_elider.h" namespace { @@ -62,10 +56,8 @@ JavaScriptAppModalDialog::JavaScriptAppModalDialog( bool display_suppress_checkbox, bool is_before_unload_dialog, IPC::Message* reply_msg) - : AppModalDialog(delegate->AsTabContents(), title), - delegate_(delegate), + : AppModalDialog(delegate, title), extra_data_(extra_data), - extension_host_(delegate->AsExtensionHost()), dialog_flags_(dialog_flags), display_suppress_checkbox_(display_suppress_checkbox), is_before_unload_dialog_(is_before_unload_dialog), @@ -73,9 +65,6 @@ JavaScriptAppModalDialog::JavaScriptAppModalDialog( use_override_prompt_text_(false) { EnforceMaxTextSize(message_text, &message_text_); EnforceMaxPromptSize(default_prompt_text, &default_prompt_text_); - - DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL)); - InitNotifications(); } JavaScriptAppModalDialog::~JavaScriptAppModalDialog() { @@ -91,42 +80,18 @@ bool JavaScriptAppModalDialog::IsJavaScriptModalDialog() { return true; } -void JavaScriptAppModalDialog::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (skip_this_dialog_) - return; - - if (NotificationType::EXTENSION_HOST_DESTROYED == type && - Details<ExtensionHost>(extension_host_) != details) +void JavaScriptAppModalDialog::Invalidate() { + if (!valid_) return; - // If we reach here, we know the notification is relevant to us, either - // because we're only observing applicable sources or because we passed the - // check above. Both of those indicate that we should ignore this dialog. - // Also clear the delegate, since it's now invalid. - skip_this_dialog_ = true; + valid_ = false; delegate_ = NULL; if (native_dialog_) CloseModalDialog(); } -void JavaScriptAppModalDialog::InitNotifications() { - // Make sure we get relevant navigation notifications so we know when our - // parent contents will disappear or navigate to a different page. - if (tab_contents_) { - registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(&tab_contents_->controller())); - registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(tab_contents_)); - } else if (extension_host_) { - // EXTENSION_HOST_DESTROYED uses the Profile as its source, but we care - // about the ExtensionHost (which is passed in the details). - registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED, - NotificationService::AllSources()); - } else { - NOTREACHED(); - } +content::JavaScriptDialogDelegate* JavaScriptAppModalDialog::delegate() const { + return static_cast<content::JavaScriptDialogDelegate*>(delegate_); } void JavaScriptAppModalDialog::OnCancel(bool suppress_js_messages) { @@ -170,15 +135,15 @@ void JavaScriptAppModalDialog::SetOverridePromptText( void JavaScriptAppModalDialog::NotifyDelegate(bool success, const string16& user_input, bool suppress_js_messages) { - if (skip_this_dialog_) + if (!valid_) return; - delegate_->OnDialogClosed(reply_msg_, success, user_input); + delegate()->OnDialogClosed(reply_msg_, success, user_input); extra_data_->last_javascript_message_dismissal_ = base::TimeTicks::Now(); extra_data_->suppress_javascript_messages_ = suppress_js_messages; // On Views, we can end up coming through this code path twice :(. // See crbug.com/63732. - skip_this_dialog_ = true; + valid_ = false; } diff --git a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h index 6a05b8e..44e012e 100644 --- a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h +++ b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h @@ -8,16 +8,15 @@ #include <string> +#include "base/compiler_specific.h" #include "base/time.h" #include "build/build_config.h" #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" #include "content/browser/javascript_dialogs.h" -#include "content/common/notification_observer.h" -#include "content/common/notification_registrar.h" -class ExtensionHost; -class NativeAppModalDialog; -class TabContents; +namespace content { +class JavaScriptDialogDelegate; +} namespace IPC { class Message; @@ -37,8 +36,7 @@ class ChromeJavaScriptDialogExtraData { // A controller + model class for JavaScript alert, confirm, prompt, and // onbeforeunload dialog boxes. -class JavaScriptAppModalDialog : public AppModalDialog, - public NotificationObserver { +class JavaScriptAppModalDialog : public AppModalDialog { public: JavaScriptAppModalDialog(content::JavaScriptDialogDelegate* delegate, ChromeJavaScriptDialogExtraData* extra_data, @@ -52,10 +50,10 @@ class JavaScriptAppModalDialog : public AppModalDialog, virtual ~JavaScriptAppModalDialog(); // Overridden from AppModalDialog: - virtual NativeAppModalDialog* CreateNativeDialog(); - virtual bool IsJavaScriptModalDialog(); - - content::JavaScriptDialogDelegate* delegate() const { return delegate_; } + virtual NativeAppModalDialog* CreateNativeDialog() OVERRIDE; + virtual bool IsJavaScriptModalDialog() OVERRIDE; + virtual void Invalidate() OVERRIDE; + virtual content::JavaScriptDialogDelegate* delegate() const OVERRIDE; // Callbacks from NativeDialog when the user accepts or cancels the dialog. void OnCancel(bool suppress_js_messages); @@ -77,24 +75,10 @@ class JavaScriptAppModalDialog : public AppModalDialog, bool is_before_unload_dialog() const { return is_before_unload_dialog_; } private: - // Overridden from NotificationObserver: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Initializes for notifications to listen. - void InitNotifications(); - // Notifies the delegate with the result of the dialog. void NotifyDelegate(bool success, const string16& prompt_text, bool suppress_js_messages); - NotificationRegistrar registrar_; - - // An implementation of the client interface to provide supporting methods - // and receive results. - content::JavaScriptDialogDelegate* delegate_; - // The extra Chrome-only data associated with the delegate_. ChromeJavaScriptDialogExtraData* extra_data_; diff --git a/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc b/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc index 09870d4..861d073 100644 --- a/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc +++ b/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc @@ -49,6 +49,8 @@ class ChromeJavaScriptDialogCreator : public content::JavaScriptDialogCreator { const string16& title, bool is_alert); + void CancelPendingDialogs(content::DialogDelegate* delegate); + // Mapping between the JavaScriptDialogDelegates and their extra data. The key // is a void* because the pointer is just a cookie and is never dereferenced. typedef std::map<void*, ChromeJavaScriptDialogExtraData> @@ -138,6 +140,7 @@ void ChromeJavaScriptDialogCreator::RunBeforeUnloadDialog( void ChromeJavaScriptDialogCreator::ResetJavaScriptState( content::JavaScriptDialogDelegate* delegate) { + CancelPendingDialogs(delegate); javascript_dialog_extra_data_.erase(delegate); } @@ -168,6 +171,16 @@ string16 ChromeJavaScriptDialogCreator::GetTitle(TitleType title_type, return string16(); } +void ChromeJavaScriptDialogCreator::CancelPendingDialogs( + content::DialogDelegate* delegate) { + AppModalDialogQueue* queue = AppModalDialogQueue::GetInstance(); + for (AppModalDialogQueue::iterator i = queue->begin(); + i != queue->end(); ++i) { + if ((*i)->delegate() == delegate) + (*i)->Invalidate(); + } +} + //------------------------------------------------------------------------------ content::JavaScriptDialogCreator* GetJavaScriptDialogCreatorInstance() { diff --git a/content/browser/javascript_dialogs.h b/content/browser/javascript_dialogs.h index 20de44b..74297b4 100644 --- a/content/browser/javascript_dialogs.h +++ b/content/browser/javascript_dialogs.h @@ -20,33 +20,31 @@ class Message; namespace content { +class DialogDelegate { + public: + // Returns the root native window with which to associate the dialog. + virtual gfx::NativeWindow GetDialogRootWindow() = 0; + + // Called right before the dialog is shown. + virtual void OnDialogShown() {} + + protected: + virtual ~DialogDelegate() {} +}; + // A class that invokes a JavaScript dialog must implement this interface to // allow the dialog implementation to get needed information and return results. -class JavaScriptDialogDelegate { +class JavaScriptDialogDelegate : public DialogDelegate { public: // This callback is invoked when the dialog is closed. virtual void OnDialogClosed(IPC::Message* reply_msg, bool success, const string16& user_input) = 0; - // Returns the root native window with which to associate the dialog. - virtual gfx::NativeWindow GetDialogRootWindow() = 0; - - // Returns the TabContents implementing this delegate, or NULL if there is - // none. TODO(avi): This breaks encapsulation and in general sucks; figure out - // a better way of doing this. - virtual TabContents* AsTabContents() = 0; - - // Returns the ExtensionHost implementing this delegate, or NULL if there is - // none. TODO(avi): This is even suckier than AsTabContents above as it breaks - // layering; figure out a better way of doing this. http://crbug.com/84604 - virtual ExtensionHost* AsExtensionHost() = 0; - protected: virtual ~JavaScriptDialogDelegate() {} }; - // An interface consisting of methods that can be called to produce JavaScript // dialogs. class JavaScriptDialogCreator { @@ -73,7 +71,8 @@ class JavaScriptDialogCreator { const string16& message_text, IPC::Message* reply_message) = 0; - // Resets any saved JavaScript dialog state for the delegate. + // Cancels all pending dialogs and resets any saved JavaScript dialog state + // for the delegate. virtual void ResetJavaScriptState(JavaScriptDialogDelegate* delegate) = 0; protected: diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index 792a7eb..b043686 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -1834,12 +1834,8 @@ gfx::NativeWindow TabContents::GetDialogRootWindow() { return view_->GetTopLevelNativeWindow(); } -TabContents* TabContents::AsTabContents() { - return this; -} - -ExtensionHost* TabContents::AsExtensionHost() { - return NULL; +void TabContents::OnDialogShown() { + Activate(); } void TabContents::set_encoding(const std::string& encoding) { diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h index ebda7a4..bc2bdd3 100644 --- a/content/browser/tab_contents/tab_contents.h +++ b/content/browser/tab_contents/tab_contents.h @@ -444,8 +444,7 @@ class TabContents : public PageNavigator, bool success, const string16& user_input) OVERRIDE; virtual gfx::NativeWindow GetDialogRootWindow() OVERRIDE; - virtual TabContents* AsTabContents() OVERRIDE; - virtual ExtensionHost* AsExtensionHost() OVERRIDE; + virtual void OnDialogShown() OVERRIDE; // The BookmarkDragDelegate is used to forward bookmark drag and drop events // to extensions. |