blob: eae6359fb1310663812db77a3596c4540c9787a0 [file] [log] [blame]
[email protected]12f74a92010-02-05 22:32:141// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/js_modal_dialog.h"
6
7#include "chrome/browser/extensions/extension_host.h"
8#include "chrome/browser/tab_contents/tab_contents.h"
9#include "chrome/common/notification_service.h"
10#include "chrome/common/notification_type.h"
11#include "ipc/ipc_message.h"
12
13JavaScriptAppModalDialog::JavaScriptAppModalDialog(
14 JavaScriptMessageBoxClient* client,
15 const std::wstring& title,
16 int dialog_flags,
17 const std::wstring& message_text,
18 const std::wstring& default_prompt_text,
19 bool display_suppress_checkbox,
20 bool is_before_unload_dialog,
21 IPC::Message* reply_msg)
22 : AppModalDialog(client->AsTabContents(), title),
23 client_(client),
24 extension_host_(client->AsExtensionHost()),
25 dialog_flags_(dialog_flags),
26 message_text_(message_text),
27 default_prompt_text_(default_prompt_text),
28 display_suppress_checkbox_(display_suppress_checkbox),
29 is_before_unload_dialog_(is_before_unload_dialog),
30 reply_msg_(reply_msg) {
31 DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL));
32}
33
34JavaScriptAppModalDialog::~JavaScriptAppModalDialog() {
35}
36
37void JavaScriptAppModalDialog::Observe(NotificationType type,
38 const NotificationSource& source,
39 const NotificationDetails& details) {
40 if (skip_this_dialog_)
41 return;
42
43 if (NotificationType::EXTENSION_HOST_DESTROYED == type &&
44 Details<ExtensionHost>(extension_host_) != details)
45 return;
46
47 // If we reach here, we know the notification is relevant to us, either
48 // because we're only observing applicable sources or because we passed the
49 // check above. Both of those indicate that we should ignore this dialog.
50 // Also clear the client, since it's now invalid.
51 skip_this_dialog_ = true;
52 client_ = NULL;
53 CloseModalDialog();
54}
55
56void JavaScriptAppModalDialog::InitNotifications() {
57 // Make sure we get relevant navigation notifications so we know when our
58 // parent contents will disappear or navigate to a different page.
59 if (tab_contents_) {
60 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
61 Source<NavigationController>(&tab_contents_->controller()));
62 registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
63 Source<TabContents>(tab_contents_));
64 } else if (extension_host_) {
65 // EXTENSION_HOST_DESTROYED uses the Profile as its source, but we care
66 // about the ExtensionHost (which is passed in the details).
67 registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED,
68 NotificationService::AllSources());
69 } else {
70 NOTREACHED();
71 }
72}
73
74void JavaScriptAppModalDialog::OnCancel() {
75 // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
76 // will receive its activation messages before this dialog receives
77 // WM_DESTROY. The parent frame would then try to activate any modal dialogs
78 // that were still open in the ModalDialogQueue, which would send activation
79 // back to this one. The framework should be improved to handle this, so this
80 // is a temporary workaround.
81 CompleteDialog();
82
83 if (!skip_this_dialog_) {
84 client_->OnMessageBoxClosed(reply_msg_, false, std::wstring());
85 }
86
87 Cleanup();
88}
89
90void JavaScriptAppModalDialog::OnAccept(const std::wstring& prompt_text,
91 bool suppress_js_messages) {
92 CompleteDialog();
93
94 if (!skip_this_dialog_) {
95 client_->OnMessageBoxClosed(reply_msg_, true, prompt_text);
96 if (suppress_js_messages)
97 client_->SetSuppressMessageBoxes(true);
98 }
99
100 Cleanup();
101}
102
103void JavaScriptAppModalDialog::OnClose() {
104 Cleanup();
105}
106
107void JavaScriptAppModalDialog::Cleanup() {
108 if (skip_this_dialog_) {
109 // We can't use the client_, because we might be in the process of
110 // destroying it.
111 if (tab_contents_)
112 tab_contents_->OnMessageBoxClosed(reply_msg_, false, L"");
113// The extension_host_ will always be a dirty pointer on OS X because the alert
114// window will cause the extension popup to close since it is resigning its key
115// state, destroying the host. http://crbug.com/29355
116#if !defined(OS_MACOSX)
117 else if (extension_host_)
118 extension_host_->OnMessageBoxClosed(reply_msg_, false, L"");
119 else
120 NOTREACHED();
121#endif
122 }
123 AppModalDialog::Cleanup();
124}
125