1 // Copyright 2013 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 "content/shell/browser/shell_javascript_dialog_manager.h"
6 
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "build/build_config.h"
11 #include "components/url_formatter/url_formatter.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/shell/browser/shell_javascript_dialog.h"
15 #include "content/shell/common/shell_switches.h"
16 
17 namespace content {
18 
ShellJavaScriptDialogManager()19 ShellJavaScriptDialogManager::ShellJavaScriptDialogManager()
20     : should_proceed_on_beforeunload_(true), beforeunload_success_(true) {}
21 
~ShellJavaScriptDialogManager()22 ShellJavaScriptDialogManager::~ShellJavaScriptDialogManager() {
23 }
24 
RunJavaScriptDialog(WebContents * web_contents,RenderFrameHost * render_frame_host,JavaScriptDialogType dialog_type,const base::string16 & message_text,const base::string16 & default_prompt_text,DialogClosedCallback callback,bool * did_suppress_message)25 void ShellJavaScriptDialogManager::RunJavaScriptDialog(
26     WebContents* web_contents,
27     RenderFrameHost* render_frame_host,
28     JavaScriptDialogType dialog_type,
29     const base::string16& message_text,
30     const base::string16& default_prompt_text,
31     DialogClosedCallback callback,
32     bool* did_suppress_message) {
33   if (dialog_request_callback_) {
34     std::move(dialog_request_callback_).Run();
35     std::move(callback).Run(true, base::string16());
36     return;
37   }
38 
39 #if defined(OS_MAC) || defined(OS_WIN)
40   *did_suppress_message = false;
41 
42   if (dialog_) {
43     // One dialog at a time, please.
44     *did_suppress_message = true;
45     return;
46   }
47 
48   base::string16 new_message_text =
49       url_formatter::FormatUrl(render_frame_host->GetLastCommittedURL()) +
50       base::ASCIIToUTF16("\n\n") + message_text;
51   gfx::NativeWindow parent_window = web_contents->GetTopLevelNativeWindow();
52 
53   dialog_.reset(new ShellJavaScriptDialog(this, parent_window, dialog_type,
54                                           new_message_text, default_prompt_text,
55                                           std::move(callback)));
56 #else
57   // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if
58   *did_suppress_message = true;
59   return;
60 #endif
61 }
62 
RunBeforeUnloadDialog(WebContents * web_contents,RenderFrameHost * render_frame_host,bool is_reload,DialogClosedCallback callback)63 void ShellJavaScriptDialogManager::RunBeforeUnloadDialog(
64     WebContents* web_contents,
65     RenderFrameHost* render_frame_host,
66     bool is_reload,
67     DialogClosedCallback callback) {
68   // During tests, if the BeforeUnload should not proceed automatically, store
69   // the callback and return.
70   if (dialog_request_callback_) {
71     std::move(dialog_request_callback_).Run();
72 
73     if (should_proceed_on_beforeunload_)
74       std::move(callback).Run(beforeunload_success_, base::string16());
75     else
76       before_unload_callback_ = std::move(callback);
77     return;
78   }
79 
80 #if defined(OS_MAC) || defined(OS_WIN)
81   if (dialog_) {
82     // Seriously!?
83     std::move(callback).Run(true, base::string16());
84     return;
85   }
86 
87   base::string16 message_text =
88       base::ASCIIToUTF16("Is it OK to leave/reload this page?");
89 
90   gfx::NativeWindow parent_window = web_contents->GetTopLevelNativeWindow();
91 
92   dialog_.reset(new ShellJavaScriptDialog(
93       this, parent_window, JAVASCRIPT_DIALOG_TYPE_CONFIRM, message_text,
94       base::string16(),  // default
95       std::move(callback)));
96 #else
97   // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if
98   std::move(callback).Run(true, base::string16());
99   return;
100 #endif
101 }
102 
CancelDialogs(WebContents * web_contents,bool reset_state)103 void ShellJavaScriptDialogManager::CancelDialogs(WebContents* web_contents,
104                                                  bool reset_state) {
105 #if defined(OS_MAC) || defined(OS_WIN)
106   if (dialog_) {
107     dialog_->Cancel();
108     dialog_.reset();
109   }
110 #else
111   // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if
112 #endif
113 
114   if (before_unload_callback_.is_null())
115     return;
116 
117   if (reset_state)
118     std::move(before_unload_callback_).Run(false, base::string16());
119 }
120 
DialogClosed(ShellJavaScriptDialog * dialog)121 void ShellJavaScriptDialogManager::DialogClosed(ShellJavaScriptDialog* dialog) {
122 #if defined(OS_MAC) || defined(OS_WIN)
123   DCHECK_EQ(dialog, dialog_.get());
124   dialog_.reset();
125 #else
126   // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if
127 #endif
128 }
129 
130 }  // namespace content
131