diff options
author | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-29 00:36:08 +0000 |
---|---|---|
committer | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-29 00:36:08 +0000 |
commit | f221002832abe2c21f8b7c6a94da313b07957f50 (patch) | |
tree | 9b707ab21a3326fd9288853ef6abb3afb6d95dc2 /content | |
parent | bae5beebbaccc8b6a6f338015784d27e5bc77929 (diff) | |
download | chromium_src-f221002832abe2c21f8b7c6a94da313b07957f50.zip chromium_src-f221002832abe2c21f8b7c6a94da313b07957f50.tar.gz chromium_src-f221002832abe2c21f8b7c6a94da313b07957f50.tar.bz2 |
Content shell: Javascript dialogs, first pass, just Mac for now.
BUG=120155
TEST=javascript dialogs work on the Mac
Review URL: http://codereview.chromium.org/9836127
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129537 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/content_shell.gypi | 4 | ||||
-rw-r--r-- | content/shell/shell.cc | 10 | ||||
-rw-r--r-- | content/shell/shell.h | 5 | ||||
-rw-r--r-- | content/shell/shell_javascript_dialog.h | 52 | ||||
-rw-r--r-- | content/shell/shell_javascript_dialog_creator.cc | 103 | ||||
-rw-r--r-- | content/shell/shell_javascript_dialog_creator.h | 57 | ||||
-rw-r--r-- | content/shell/shell_javascript_dialog_mac.mm | 140 |
7 files changed, 371 insertions, 0 deletions
diff --git a/content/content_shell.gypi b/content/content_shell.gypi index aeecdff..49fdafb 100644 --- a/content/content_shell.gypi +++ b/content/content_shell.gypi @@ -79,6 +79,10 @@ 'shell/shell_devtools_delegate.h', 'shell/shell_download_manager_delegate.cc', 'shell/shell_download_manager_delegate.h', + 'shell/shell_javascript_dialog_creator.cc', + 'shell/shell_javascript_dialog_creator.h', + 'shell/shell_javascript_dialog_mac.mm', + 'shell/shell_javascript_dialog.h', 'shell/shell_main_delegate.cc', 'shell/shell_main_delegate.h', 'shell/shell_messages.cc', diff --git a/content/shell/shell.cc b/content/shell/shell.cc index 49097bc..dff406f 100644 --- a/content/shell/shell.cc +++ b/content/shell/shell.cc @@ -11,6 +11,7 @@ #include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" +#include "content/shell/shell_javascript_dialog_creator.h" #include "content/shell/shell_messages.h" #include "content/shell/shell_switches.h" #include "ui/gfx/size.h" @@ -141,6 +142,15 @@ void Shell::DidNavigateMainFramePostCommit(WebContents* tab) { PlatformSetAddressBarURL(tab->GetURL()); } +JavaScriptDialogCreator* Shell::GetJavaScriptDialogCreator() { + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) + return NULL; + + if (!dialog_creator_.get()) + dialog_creator_.reset(new ShellJavaScriptDialogCreator()); + return dialog_creator_.get(); +} + void Shell::DidFinishLoad(int64 frame_id, const GURL& validated_url, bool is_main_frame) { diff --git a/content/shell/shell.h b/content/shell/shell.h index 93499114..0beb6dd 100644 --- a/content/shell/shell.h +++ b/content/shell/shell.h @@ -27,7 +27,9 @@ class GURL; class WebContents; namespace content { + class BrowserContext; +class ShellJavaScriptDialogCreator; class SiteInstance; // This represents one window of the Content Shell, i.e. all the UI including @@ -115,6 +117,7 @@ class Shell : public WebContentsDelegate, const GURL& target_url, WebContents* new_contents) OVERRIDE; virtual void DidNavigateMainFramePostCommit(WebContents* tab) OVERRIDE; + virtual JavaScriptDialogCreator* GetJavaScriptDialogCreator() OVERRIDE; #if defined(OS_MACOSX) virtual void HandleKeyboardEvent( const NativeWebKeyboardEvent& event) OVERRIDE; @@ -143,6 +146,8 @@ class Shell : public WebContentsDelegate, GObject*, guint, GdkModifierType); #endif + scoped_ptr<ShellJavaScriptDialogCreator> dialog_creator_; + scoped_ptr<WebContents> web_contents_; // layoutTestController related variables. diff --git a/content/shell/shell_javascript_dialog.h b/content/shell/shell_javascript_dialog.h new file mode 100644 index 0000000..32d425d --- /dev/null +++ b/content/shell/shell_javascript_dialog.h @@ -0,0 +1,52 @@ +// Copyright (c) 2012 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 CONTENT_SHELL_SHELL_JAVASCRIPT_DIALOG_H_ +#define CONTENT_SHELL_SHELL_JAVASCRIPT_DIALOG_H_ +#pragma once + +#include "content/public/browser/javascript_dialogs.h" + +#if defined(OS_MACOSX) +#if __OBJC__ +@class NSAlert; +@class ShellJavaScriptDialogHelper; +#else +class NSAlert; +class ShellJavaScriptDialogHelper; +#endif // __OBJC__ +#endif // defined(OS_MACOSX) + +namespace content { + +class ShellJavaScriptDialogCreator; + +class ShellJavaScriptDialog { + public: + ShellJavaScriptDialog( + ShellJavaScriptDialogCreator* creator, + ui::JavascriptMessageType javascript_message_type, + const string16& message_text, + const string16& default_prompt_text, + const JavaScriptDialogCreator::DialogClosedCallback& callback); + ~ShellJavaScriptDialog(); + + // Called to cancel a dialog mid-flight. + void Cancel(); + + private: + ShellJavaScriptDialogCreator* creator_; + JavaScriptDialogCreator::DialogClosedCallback callback_; + +#if defined(OS_MACOSX) + ShellJavaScriptDialogHelper* helper_; // owned + NSAlert* alert_; // weak, owned by |helper_|. +#endif // defined(OS_MACOSX) + + DISALLOW_COPY_AND_ASSIGN(ShellJavaScriptDialog); +}; + +} // namespace content + +#endif // CONTENT_SHELL_SHELL_JAVASCRIPT_DIALOG_H_ diff --git a/content/shell/shell_javascript_dialog_creator.cc b/content/shell/shell_javascript_dialog_creator.cc new file mode 100644 index 0000000..d6b100c --- /dev/null +++ b/content/shell/shell_javascript_dialog_creator.cc @@ -0,0 +1,103 @@ +// Copyright (c) 2012 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 "content/shell/shell_javascript_dialog_creator.h" + +#include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "content/shell/shell_javascript_dialog.h" +#include "net/base/net_util.h" + +namespace content { + +ShellJavaScriptDialogCreator::ShellJavaScriptDialogCreator() { +} + +ShellJavaScriptDialogCreator::~ShellJavaScriptDialogCreator() { +} + +void ShellJavaScriptDialogCreator::RunJavaScriptDialog( + WebContents* web_contents, + const GURL& origin_url, + const std::string& accept_lang, + ui::JavascriptMessageType javascript_message_type, + const string16& message_text, + const string16& default_prompt_text, + const DialogClosedCallback& callback, + bool* did_suppress_message) { +#if defined(OS_MACOSX) + *did_suppress_message = false; + + if (dialog_.get()) { + // One dialog at a time, please. + *did_suppress_message = true; + return; + } + + string16 new_message_text = net::FormatUrl(origin_url, accept_lang) + + ASCIIToUTF16("\n\n") + + message_text; + + dialog_.reset(new ShellJavaScriptDialog(this, + javascript_message_type, + new_message_text, + default_prompt_text, + callback)); +#else + // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if + *did_suppress_message = true; + return; +#endif +} + +void ShellJavaScriptDialogCreator::RunBeforeUnloadDialog( + WebContents* web_contents, + const string16& message_text, + bool is_reload, + const DialogClosedCallback& callback) { +#if defined(OS_MACOSX) + if (dialog_.get()) { + // Seriously!? + callback.Run(true, string16()); + return; + } + + string16 new_message_text = + message_text + + ASCIIToUTF16("\n\nIs it OK to leave/reload this page?"); + + dialog_.reset(new ShellJavaScriptDialog(this, + ui::JAVASCRIPT_MESSAGE_TYPE_CONFIRM, + new_message_text, + string16(), // default_prompt_text + callback)); +#else + // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if + callback.Run(true, string16()); + return; +#endif +} + +void ShellJavaScriptDialogCreator::ResetJavaScriptState( + WebContents* web_contents) { +#if defined(OS_MACOSX) + if (dialog_.get()) { + dialog_->Cancel(); + dialog_.reset(); + } +#else + // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if +#endif +} + +void ShellJavaScriptDialogCreator::DialogClosed(ShellJavaScriptDialog* dialog) { +#if defined(OS_MACOSX) + DCHECK_EQ(dialog, dialog_.get()); + dialog_.reset(); +#else + // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if +#endif +} + +} // namespace content diff --git a/content/shell/shell_javascript_dialog_creator.h b/content/shell/shell_javascript_dialog_creator.h new file mode 100644 index 0000000..88e5db6 --- /dev/null +++ b/content/shell/shell_javascript_dialog_creator.h @@ -0,0 +1,57 @@ +// Copyright (c) 2012 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 CONTENT_SHELL_SHELL_JAVASCRIPT_DIALOG_CREATOR_H_ +#define CONTENT_SHELL_SHELL_JAVASCRIPT_DIALOG_CREATOR_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/javascript_dialogs.h" + +namespace content { + +class ShellJavaScriptDialog; + +class ShellJavaScriptDialogCreator : public JavaScriptDialogCreator { + public: + ShellJavaScriptDialogCreator(); + virtual ~ShellJavaScriptDialogCreator(); + + // JavaScriptDialogCreator: + virtual void RunJavaScriptDialog( + WebContents* web_contents, + const GURL& origin_url, + const std::string& accept_lang, + ui::JavascriptMessageType javascript_message_type, + const string16& message_text, + const string16& default_prompt_text, + const DialogClosedCallback& callback, + bool* did_suppress_message) OVERRIDE; + + virtual void RunBeforeUnloadDialog( + WebContents* web_contents, + const string16& message_text, + bool is_reload, + const DialogClosedCallback& callback) OVERRIDE; + + virtual void ResetJavaScriptState(WebContents* web_contents) OVERRIDE; + + // Called by the ShellJavaScriptDialog when it closes. + void DialogClosed(ShellJavaScriptDialog* dialog); + + private: +#if defined(OS_MACOSX) + // The dialog being shown. No queueing. + scoped_ptr<ShellJavaScriptDialog> dialog_; +#else + // TODO: implement ShellJavaScriptDialog for other platforms, drop this #if +#endif + + DISALLOW_COPY_AND_ASSIGN(ShellJavaScriptDialogCreator); +}; + +} // namespace content + +#endif // CONTENT_SHELL_SHELL_JAVASCRIPT_DIALOG_CREATOR_H_ diff --git a/content/shell/shell_javascript_dialog_mac.mm b/content/shell/shell_javascript_dialog_mac.mm new file mode 100644 index 0000000..543bb55 --- /dev/null +++ b/content/shell/shell_javascript_dialog_mac.mm @@ -0,0 +1,140 @@ +// Copyright (c) 2012 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 "content/shell/shell_javascript_dialog.h" + +#import <Cocoa/Cocoa.h> + +#import "base/mac/cocoa_protocols.h" +#import "base/memory/scoped_nsobject.h" +#include "base/sys_string_conversions.h" +#include "content/shell/shell_javascript_dialog_creator.h" + +// Helper object that receives the notification that the dialog/sheet is +// going away. Is responsible for cleaning itself up. +@interface ShellJavaScriptDialogHelper : NSObject<NSAlertDelegate> { + @private + scoped_nsobject<NSAlert> alert_; + NSTextField* textField_; // WEAK; owned by alert_ + + // Copies of the fields in ShellJavaScriptDialog because they're private. + content::ShellJavaScriptDialogCreator* creator_; + content::JavaScriptDialogCreator::DialogClosedCallback callback_; +} + +- (id)initHelperWithCreator:(content::ShellJavaScriptDialogCreator*)creator + andCallback:(content::JavaScriptDialogCreator::DialogClosedCallback)callback; +- (NSAlert*)alert; +- (NSTextField*)textField; +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo; +- (void)cancel; + +@end + +@implementation ShellJavaScriptDialogHelper + +- (id)initHelperWithCreator:(content::ShellJavaScriptDialogCreator*)creator + andCallback:(content::JavaScriptDialogCreator::DialogClosedCallback)callback { + if (self = [super init]) { + creator_ = creator; + callback_ = callback; + } + + return self; +} + +- (NSAlert*)alert { + alert_.reset([[NSAlert alloc] init]); + return alert_; +} + +- (NSTextField*)textField { + textField_ = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]; + [[textField_ cell] setLineBreakMode:NSLineBreakByTruncatingTail]; + [alert_ setAccessoryView:textField_]; + [textField_ release]; + + return textField_; +} + +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo { + if (returnCode == NSRunStoppedResponse) + return; + + bool success = returnCode == NSAlertFirstButtonReturn; + string16 input; + if (textField_) + input = base::SysNSStringToUTF16([textField_ stringValue]); + + content::ShellJavaScriptDialog* native_dialog = + reinterpret_cast<content::ShellJavaScriptDialog*>(contextInfo); + callback_.Run(success, input); + creator_->DialogClosed(native_dialog); +} + +- (void)cancel { + [NSApp endSheet:[alert_ window]]; + alert_.reset(); +} + +@end + +namespace content { + +ShellJavaScriptDialog::ShellJavaScriptDialog( + ShellJavaScriptDialogCreator* creator, + ui::JavascriptMessageType javascript_message_type, + const string16& message_text, + const string16& default_prompt_text, + const JavaScriptDialogCreator::DialogClosedCallback& callback) + : creator_(creator), + callback_(callback) { + bool text_field = + javascript_message_type == ui::JAVASCRIPT_MESSAGE_TYPE_PROMPT; + bool one_button = + javascript_message_type == ui::JAVASCRIPT_MESSAGE_TYPE_ALERT; + + helper_ = + [[ShellJavaScriptDialogHelper alloc] initHelperWithCreator:creator + andCallback:callback]; + + // Show the modal dialog. + alert_ = [helper_ alert]; + NSTextField* field = nil; + if (text_field) { + field = [helper_ textField]; + [field setStringValue:base::SysUTF16ToNSString(default_prompt_text)]; + } + [alert_ setDelegate:helper_]; + [alert_ setInformativeText:base::SysUTF16ToNSString(message_text)]; + [alert_ setMessageText:@"Javascript alert"]; + [alert_ addButtonWithTitle:@"OK"]; + if (!one_button) { + NSButton* other = [alert_ addButtonWithTitle:@"Cancel"]; + [other setKeyEquivalent:@"\e"]; + } + + [alert_ + beginSheetModalForWindow:nil // nil here makes it app-modal + modalDelegate:helper_ + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:this]; + + if ([alert_ accessoryView]) + [[alert_ window] makeFirstResponder:[alert_ accessoryView]]; +} + +ShellJavaScriptDialog::~ShellJavaScriptDialog() { + [helper_ release]; +} + +void ShellJavaScriptDialog::Cancel() { + [helper_ cancel]; +} + +} // namespace content |