summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authordanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 06:54:09 +0000
committerdanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 06:54:09 +0000
commitd0edf4e5adf877515ff49a59f63600fd88a25b36 (patch)
treead789884b7918146fcbcddaf4f10284836ff3496 /chrome/browser
parent5fed0f1c5195ded63dfadadeb93c0b1d006f1fb4 (diff)
downloadchromium_src-d0edf4e5adf877515ff49a59f63600fd88a25b36.zip
chromium_src-d0edf4e5adf877515ff49a59f63600fd88a25b36.tar.gz
chromium_src-d0edf4e5adf877515ff49a59f63600fd88a25b36.tar.bz2
[Mac] augment modal cookie prompt on mac to include details pane
Added two new xibs. The first is a cookie info view that is shared between the tree that shows browser data and the cookie modal prompt to block accepting cookies. The second is a window to replace the NSAlert modal dialog for the cookie prompt. Modified cookie tree code and added cookie prompt code to use new xibs. Changed "hidden" handling of cookie detail view to use bindings rather than explicit code. TODOs for http://crbug.com/36948 not in this CL: - changing the expiration for cookies isn't implemented TEST=manually testing of modal cookie prompt, new unit tests BUG=http://crbug.com/36948 Review URL: http://codereview.chromium.org/669127 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41408 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/app_modal_dialog.cc4
-rw-r--r--chrome/browser/app_modal_dialog.h11
-rw-r--r--chrome/browser/app_modal_dialog_mac.mm5
-rw-r--r--chrome/browser/cocoa/cookie_details_view_controller.h40
-rw-r--r--chrome/browser/cocoa/cookie_details_view_controller.mm80
-rw-r--r--chrome/browser/cocoa/cookie_details_view_controller_unittest.mm142
-rw-r--r--chrome/browser/cocoa/cookie_prompt_window_controller.h61
-rw-r--r--chrome/browser/cocoa/cookie_prompt_window_controller.mm416
-rw-r--r--chrome/browser/cocoa/cookie_prompt_window_controller_unittest.mm50
-rw-r--r--chrome/browser/cocoa/cookie_tree_node.h6
-rw-r--r--chrome/browser/cocoa/cookie_tree_node.mm41
-rw-r--r--chrome/browser/cocoa/cookies_window_controller.h12
-rw-r--r--chrome/browser/cocoa/cookies_window_controller.mm42
-rw-r--r--chrome/browser/cocoa/cookies_window_controller_unittest.mm9
-rw-r--r--chrome/browser/cookie_modal_dialog.h17
-rw-r--r--chrome/browser/cookie_modal_dialog_mac.mm110
-rw-r--r--chrome/browser/js_modal_dialog.h16
-rw-r--r--chrome/browser/js_modal_dialog_mac.mm7
18 files changed, 910 insertions, 159 deletions
diff --git a/chrome/browser/app_modal_dialog.cc b/chrome/browser/app_modal_dialog.cc
index 2eea602..e8f306d 100644
--- a/chrome/browser/app_modal_dialog.cc
+++ b/chrome/browser/app_modal_dialog.cc
@@ -11,7 +11,11 @@
AppModalDialog::AppModalDialog(TabContents* tab_contents,
const std::wstring& title)
+#if defined(OS_WIN) || defined(OS_LINUX)
: dialog_(NULL),
+#elif defined(OS_MACOSX)
+ :
+#endif
tab_contents_(tab_contents),
title_(title),
skip_this_dialog_(false) {
diff --git a/chrome/browser/app_modal_dialog.h b/chrome/browser/app_modal_dialog.h
index 6567db8..92ac494 100644
--- a/chrome/browser/app_modal_dialog.h
+++ b/chrome/browser/app_modal_dialog.h
@@ -17,12 +17,7 @@
class ModalDialogDelegate;
typedef ModalDialogDelegate* NativeDialog;
#elif defined(OS_MACOSX)
-#if __OBJC__
-@class NSAlert;
-#else
-class NSAlert;
-#endif
-typedef NSAlert* NativeDialog;
+typedef void* NativeDialog;
#elif defined(TOOLKIT_USES_GTK)
typedef struct _GtkDialog GtkDialog;
typedef struct _GtkWidget GtkWidget;
@@ -71,7 +66,7 @@ class AppModalDialog {
#endif
// Close the dialog if it is showing.
- void CloseModalDialog();
+ virtual void CloseModalDialog();
// Called by the app modal window queue to activate the window.
void ActivateModalDialog();
@@ -97,7 +92,9 @@ class AppModalDialog {
virtual NativeDialog CreateNativeDialog() = 0;
// A reference to the platform native dialog box.
+#if defined(OS_LINUX) || defined(OS_WIN)
NativeDialog dialog_;
+#endif
// Parent tab contents.
TabContents* tab_contents_;
diff --git a/chrome/browser/app_modal_dialog_mac.mm b/chrome/browser/app_modal_dialog_mac.mm
index 2a21c1da..8d23387 100644
--- a/chrome/browser/app_modal_dialog_mac.mm
+++ b/chrome/browser/app_modal_dialog_mac.mm
@@ -20,8 +20,5 @@ void AppModalDialog::ActivateModalDialog() {
}
void AppModalDialog::CloseModalDialog() {
- NSAlert* alert = dialog_;
- DCHECK([alert isKindOfClass:[NSAlert class]]);
- [NSApp endSheet:[alert window]];
- dialog_ = nil;
+ NOTIMPLEMENTED();
}
diff --git a/chrome/browser/cocoa/cookie_details_view_controller.h b/chrome/browser/cocoa/cookie_details_view_controller.h
new file mode 100644
index 0000000..04b8db7
--- /dev/null
+++ b/chrome/browser/cocoa/cookie_details_view_controller.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2010 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/cocoa_protocols_mac.h"
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "net/base/cookie_monster.h"
+
+@class CocoaCookieTreeNode;
+
+// Controller for the view that displays the details of a cookie,
+// used both in the cookie prompt dialog as well as the
+// show cookies preference sheet of content settings preferences.
+@interface CookieDetailsViewController : NSViewController {
+ @private
+ // Allows direct access to the object controller for
+ // the displayed cookie information.
+ IBOutlet NSObjectController* objectController_;
+}
+
+- (id)init;
+
+// Configures the cookie detail view that is managed by the controller
+// to display the information about a single cookie, the information
+// for which is explicitly passed in the parameter |content|.
+- (void)setContentObject:(id)content;
+
+// Adjust the size of the view to exactly fix the information text fields
+// that are visible inside it.
+- (void)shrinkViewToFit;
+
+// Called by the cookie tree dialog to establish a binding between
+// the the detail view's object controller and the tree controller.
+// This binding allows the cookie tree to use the detail view unmodified.
+- (void)configureBindingsForTreeController:(NSTreeController*)controller;
+@end
+
diff --git a/chrome/browser/cocoa/cookie_details_view_controller.mm b/chrome/browser/cocoa/cookie_details_view_controller.mm
new file mode 100644
index 0000000..70da2a5
--- /dev/null
+++ b/chrome/browser/cocoa/cookie_details_view_controller.mm
@@ -0,0 +1,80 @@
+// Copyright (c) 2010 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.
+
+#import "chrome/browser/cocoa/cookie_details_view_controller.h"
+
+#include "app/l10n_util_mac.h"
+#include "app/resource_bundle.h"
+#import "base/mac_util.h"
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/cocoa/cookie_tree_node.h"
+#import "chrome/browser/cookie_modal_dialog.h"
+
+namespace {
+static const int kMinimalLabelOffsetFromViewBottom = 20;
+}
+
+#pragma mark View Controller
+
+@implementation CookieDetailsViewController
+
+- (id)init {
+ return [super initWithNibName:@"CookieDetailsView"
+ bundle:mac_util::MainAppBundle()];
+}
+
+- (void)awakeFromNib {
+ DCHECK(objectController_);
+}
+
+// Finds and returns the y offset of the lowest-most non-hidden
+// text field in the view. This is used to shrink the view
+// appropriately so that it just fits its visible content.
+- (void)getLowestLabelVerticalPosition:(NSView*)view
+ lowestLabelPosition:(float&)lowestLabelPosition {
+ if (![view isHidden]) {
+ if ([view isKindOfClass:[NSTextField class]]) {
+ NSRect frame = [view frame];
+ if (frame.origin.y < lowestLabelPosition) {
+ lowestLabelPosition = frame.origin.y;
+ }
+ }
+ for (NSView* subview in [view subviews]) {
+ [self getLowestLabelVerticalPosition:subview
+ lowestLabelPosition:lowestLabelPosition];
+ }
+ }
+}
+
+- (void)setContentObject:(id)content {
+ [objectController_ setValue:content forKey:@"content"];
+}
+
+- (void)shrinkViewToFit {
+ // Adjust the information pane to be exactly the right size
+ // to hold the visible text information fields.
+ NSView* view = [self view];
+ NSRect frame = [view frame];
+ float lowestLabelPosition = frame.origin.y + frame.size.height;
+ [self getLowestLabelVerticalPosition:view
+ lowestLabelPosition:lowestLabelPosition];
+ float verticalDelta = lowestLabelPosition - frame.origin.y -
+ kMinimalLabelOffsetFromViewBottom;
+ frame.origin.y += verticalDelta;
+ frame.size.height -= verticalDelta;
+ [[self view] setFrame:frame];
+}
+
+- (void)configureBindingsForTreeController:(NSTreeController*)treeController {
+ // There seems to be a bug in the binding logic that it's not possible
+ // to bind to the selection of the tree controller, the bind seems to
+ // require an additional path segment in the key, thus the use of
+ // selection.self rather than just selection below.
+ [objectController_ bind:@"contentObject"
+ toObject:treeController
+ withKeyPath:@"selection.self"
+ options:nil];
+}
+
+@end
diff --git a/chrome/browser/cocoa/cookie_details_view_controller_unittest.mm b/chrome/browser/cocoa/cookie_details_view_controller_unittest.mm
new file mode 100644
index 0000000..a1d6a67
--- /dev/null
+++ b/chrome/browser/cocoa/cookie_details_view_controller_unittest.mm
@@ -0,0 +1,142 @@
+// Copyright (c) 2010 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 "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/cocoa/cookie_details_view_controller.h"
+#include "chrome/browser/cookie_modal_dialog.h"
+
+// Mock apapter that returns dummy values for the details view
+@interface MockCookieDetailsViewContentAdapter : NSObject {
+ @private
+ // The type of fake cookie data to display
+ CookiePromptModalDialog::DialogType promptType_;
+}
+
+- (id)initWithType:(CookiePromptModalDialog::DialogType)type;
+
+// The following methods are all used in the bindings
+// inside the cookie detail view.
+@property (readonly) BOOL isFolderOrCookieTreeDetails;
+@property (readonly) BOOL isLocalStorageTreeDetails;
+@property (readonly) BOOL isDatabaseTreeDetails;
+@property (readonly) BOOL isDatabasePromptDetails;
+@property (readonly) BOOL isLocalStoragePromptDetails;
+@property (readonly) NSString* name;
+@property (readonly) NSString* content;
+@property (readonly) NSString* domain;
+@property (readonly) NSString* path;
+@property (readonly) NSString* sendFor;
+@property (readonly) NSString* created;
+@property (readonly) NSString* expires;
+@property (readonly) NSString* fileSize;
+@property (readonly) NSString* lastModified;
+@property (readonly) NSString* databaseDescription;
+@property (readonly) NSString* localStorageKey;
+@property (readonly) NSString* localStorageValue;
+
+@end
+
+@implementation MockCookieDetailsViewContentAdapter
+
+- (id)initWithType:(CookiePromptModalDialog::DialogType)type {
+ if ((self = [super init])) {
+ promptType_ = type;
+ }
+ return self;
+}
+
+- (BOOL)isFolderOrCookieTreeDetails {
+ return promptType_ == CookiePromptModalDialog::DIALOG_TYPE_COOKIE;
+}
+
+- (BOOL)isLocalStorageTreeDetails {
+ return false;
+}
+
+- (BOOL)isDatabaseTreeDetails {
+ return false;
+}
+
+- (BOOL) isDatabasePromptDetails {
+ return promptType_ == CookiePromptModalDialog::DIALOG_TYPE_DATABASE;
+}
+
+- (BOOL) isLocalStoragePromptDetails {
+ return promptType_ == CookiePromptModalDialog::DIALOG_TYPE_LOCAL_STORAGE;
+}
+
+- (NSString*)name {
+ return @"dummyName";
+}
+
+- (NSString*)content {
+ return @"dummyContent";
+}
+
+- (NSString*)domain {
+ return @"dummyDomain";
+}
+
+- (NSString*)path {
+ return @"dummyPath";
+}
+
+- (NSString*)sendFor {
+ return @"dummySendFor";
+}
+
+- (NSString*)created {
+ return @"dummyCreated";
+}
+
+- (NSString*)expires {
+ return @"dummyExpires";
+}
+
+- (NSString*)fileSize {
+ return @"dummyFileSize";
+}
+
+- (NSString*)lastModified {
+ return @"dummyLastModified";
+}
+
+- (NSString*)databaseDescription {
+ return @"dummyDatabaseDescription";
+}
+
+- (NSString*)localStorageKey {
+ return @"dummyLocalStorageKey";
+}
+
+- (NSString*)localStorageValue {
+ return @"dummyLocalStorageValue";
+}
+
+@end
+
+namespace {
+
+class CookieDetailsViewControllerTest : public CocoaTest {
+};
+
+TEST_F(CookieDetailsViewControllerTest, Create) {
+ scoped_nsobject<CookieDetailsViewController> detailsViewController;
+ detailsViewController.reset([[CookieDetailsViewController alloc] init]);
+}
+
+TEST_F(CookieDetailsViewControllerTest, ShrinkToFit) {
+ scoped_nsobject<CookieDetailsViewController> detailsViewController;
+ detailsViewController.reset([[CookieDetailsViewController alloc] init]);
+ scoped_nsobject<MockCookieDetailsViewContentAdapter> mockAdapter;
+ mockAdapter.reset([[MockCookieDetailsViewContentAdapter alloc]
+ initWithType:CookiePromptModalDialog::DIALOG_TYPE_DATABASE]);
+ [detailsViewController.get() setContentObject:mockAdapter.get()];
+ NSRect beforeFrame = [[detailsViewController.get() view] frame];
+ [detailsViewController.get() shrinkViewToFit];
+ NSRect afterFrame = [[detailsViewController.get() view] frame];
+ EXPECT_TRUE(afterFrame.size.height < beforeFrame.size.width);
+}
+
+} // namespace
diff --git a/chrome/browser/cocoa/cookie_prompt_window_controller.h b/chrome/browser/cocoa/cookie_prompt_window_controller.h
new file mode 100644
index 0000000..5276d5c
--- /dev/null
+++ b/chrome/browser/cocoa/cookie_prompt_window_controller.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2010 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/cocoa_protocols_mac.h"
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+
+class CookiePromptModalDialog;
+class CookieTreeNode;
+
+@class CookieDetailsViewController;
+@class CocoaCookieTreeNode;
+
+// This class is the controller for the window displayed
+// to the user as a modal dialog prompting them to accept or
+// block new cookies and other browser data.
+@interface CookiePromptWindowController : NSWindowController {
+ @private
+ // Provides access to platform independent information for
+ // the cookie prompt dialog.
+ CookiePromptModalDialog* dialog_; // weak;
+
+ // The controller managing the instances of the cookies details view
+ // embedded in the prompt window.
+ scoped_nsobject<CookieDetailsViewController> detailsViewController_;
+
+ // The adapter object that supplies the methods expected by
+ // the cookie details view.
+ scoped_nsobject<NSObject> selectionAdapterObject_;
+
+ // Outlets to provide quick access to subviews
+ // in the prompt window.
+ IBOutlet NSTextField* description_;
+ IBOutlet NSView* disclosedViewPlaceholder_;
+ IBOutlet NSButton* disclosureTriangle_;
+ IBOutlet NSView* disclosureTriangleSuperView_;
+ IBOutlet NSMatrix* radioGroupMatrix_;
+ IBOutlet NSButtonCell* rememberChoiceCell_;
+}
+
+// Designated initializer.
+- (id)initWithDialog:(CookiePromptModalDialog*)bridge;
+
+// Performs the modal dialog loop for the cookie prompt dialog
+// and processes the result.
+- (void)doModalDialog:(void*)context;
+
+// Handles the toggling of the disclosure triangle
+// to reveal cookie data
+- (IBAction)disclosureTrianglePressed:(id)sender;
+
+// Callback for "block" button.
+- (IBAction)block:(id)sender;
+
+// Callback for "accept" button.
+- (IBAction)accept:(id)sender;
+
+@end
diff --git a/chrome/browser/cocoa/cookie_prompt_window_controller.mm b/chrome/browser/cocoa/cookie_prompt_window_controller.mm
new file mode 100644
index 0000000..5b85397
--- /dev/null
+++ b/chrome/browser/cocoa/cookie_prompt_window_controller.mm
@@ -0,0 +1,416 @@
+// Copyright (c) 2010 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.
+
+#import "chrome/browser/cocoa/cookie_prompt_window_controller.h"
+
+#include <string>
+#include <vector>
+
+#include "app/l10n_util_mac.h"
+#include "app/resource_bundle.h"
+#import "base/i18n/time_formatting.h"
+#import "base/mac_util.h"
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/cocoa/cookie_details_view_controller.h"
+#include "chrome/browser/cocoa/cookie_tree_node.h"
+#include "chrome/browser/cookie_modal_dialog.h"
+#include "chrome/browser/cookies_tree_model.h"
+#include "grit/generated_resources.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+
+#pragma mark Window Controller
+
+// This class is an apapter allows the cookie details view to be shared
+// by the cookie prompt window and the cookie tree in the cookies and
+// other site data window. As instance of the class is set as the
+// content object of the object controller for the details view and
+// implements the methods expected by bindings inside that view.
+@interface CookiePromptSelectionAdapter : NSObject {
+ @private
+ // The type of the cookie prompt being displayed, used to
+ // determine which subview of the details view is visible
+ CookiePromptModalDialog::DialogType promptType_;
+
+ // The following members are used to hold information used in the
+ // cookie prompt detailed information for cookies and web databases.
+ scoped_nsobject<NSString> name_;
+ scoped_nsobject<NSString> domain_;
+ scoped_nsobject<NSString> content_;
+
+ // The following members are used to hold information used in the
+ // cookie prompt detailed information for cookies only.
+ scoped_nsobject<NSString> path_;
+ scoped_nsobject<NSString> sendFor_;
+ scoped_nsobject<NSString> created_;
+ scoped_nsobject<NSString> expires_;
+
+ // The following members are used to hold information used in the
+ // cookie prompt detailed information for local storage only.
+ scoped_nsobject<NSString> localStorageKey_;
+ scoped_nsobject<NSString> localStorageValue_;
+}
+
+// Creates and returns an instance approriate for displaying information
+// about a cookie.
+- (id)initWithCookie:(const std::string&)cookie_line
+ url:(const GURL&)url;
+
+// Creates and returns an instance approriate for displaying information
+// about a local storage.
+- (id)initWithLocalStorage:(const std::string&)domain
+ key:(const string16&)key
+ value:(const string16&)value;
+
+// Creates and returns an instance approriate for displaying information
+// about a web database.
+- (id)initWithDatabase:(const std::string&)domain
+ name:(const string16&)name;
+
+// The following methods are all used in the bindings inside the cookie
+// detail view.
+@property (readonly) BOOL isFolderOrCookieTreeDetails;
+@property (readonly) BOOL isLocalStorageTreeDetails;
+@property (readonly) BOOL isDatabaseTreeDetails;
+@property (readonly) BOOL isDatabasePromptDetails;
+@property (readonly) BOOL isLocalStoragePromptDetails;
+@property (readonly) NSString* name;
+@property (readonly) NSString* content;
+@property (readonly) NSString* domain;
+@property (readonly) NSString* path;
+@property (readonly) NSString* sendFor;
+@property (readonly) NSString* created;
+@property (readonly) NSString* expires;
+@property (readonly) NSString* fileSize;
+@property (readonly) NSString* lastModified;
+@property (readonly) NSString* databaseDescription;
+@property (readonly) NSString* localStorageKey;
+@property (readonly) NSString* localStorageValue;
+
+@end
+
+@implementation CookiePromptSelectionAdapter
+
+- (id)initWithCookie:(const std::string&)cookie_line
+ url:(const GURL&)url {
+ if ((self = [super init])) {
+ promptType_ = CookiePromptModalDialog::DIALOG_TYPE_COOKIE;
+ net::CookieMonster::ParsedCookie pc(cookie_line);
+ net::CookieMonster::CanonicalCookie cookie(url, pc);
+ const std::string& domain(pc.HasDomain() ? pc.Domain() : url.host());
+ domain_.reset([base::SysUTF8ToNSString(domain) retain]);
+ name_.reset([base::SysUTF8ToNSString(cookie.Name()) retain]);
+ content_.reset([base::SysUTF8ToNSString(cookie.Value()) retain]);
+ path_.reset([base::SysUTF8ToNSString(cookie.Path()) retain]);
+
+ if (cookie.DoesExpire()) {
+ expires_.reset([base::SysWideToNSString(
+ base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate()))
+ retain]);
+ } else {
+ expires_.reset([l10n_util::GetNSStringWithFixup(
+ IDS_COOKIES_COOKIE_EXPIRES_SESSION) retain]);
+ }
+
+ created_.reset([base::SysWideToNSString(
+ base::TimeFormatFriendlyDateAndTime(cookie.CreationDate()))
+ retain]);
+
+ if (cookie.IsSecure()) {
+ sendFor_.reset([l10n_util::GetNSStringWithFixup(
+ IDS_COOKIES_COOKIE_SENDFOR_SECURE) retain]);
+ } else {
+ sendFor_.reset([l10n_util::GetNSStringWithFixup(
+ IDS_COOKIES_COOKIE_SENDFOR_ANY) retain]);
+ }
+ }
+ return self;
+}
+
+- (id)initWithLocalStorage:(const std::string&)domain
+ key:(const string16&)key
+ value:(const string16&)value {
+ if ((self = [super init])) {
+ promptType_ = CookiePromptModalDialog::DIALOG_TYPE_LOCAL_STORAGE;
+ domain_.reset([base::SysUTF8ToNSString(domain) retain]);
+ localStorageKey_.reset([base::SysUTF16ToNSString(key) retain]);
+ localStorageValue_.reset([base::SysUTF16ToNSString(value) retain]);
+ }
+ return self;
+}
+
+- (id)initWithDatabase:(const std::string&)domain
+ name:(const string16&)name {
+ if ((self = [super init])) {
+ promptType_ = CookiePromptModalDialog::DIALOG_TYPE_DATABASE;
+ name_.reset([base::SysUTF16ToNSString(name) retain]);
+ domain_.reset([base::SysUTF8ToNSString(domain) retain]);
+ }
+ return self;
+}
+
+- (BOOL)isFolderOrCookieTreeDetails {
+ return promptType_ == CookiePromptModalDialog::DIALOG_TYPE_COOKIE;
+}
+
+- (BOOL)isLocalStorageTreeDetails {
+ return false;
+}
+
+- (BOOL)isDatabaseTreeDetails {
+ return false;
+}
+
+- (BOOL) isDatabasePromptDetails {
+ return promptType_ == CookiePromptModalDialog::DIALOG_TYPE_DATABASE;
+}
+
+- (BOOL) isLocalStoragePromptDetails {
+ return promptType_ == CookiePromptModalDialog::DIALOG_TYPE_LOCAL_STORAGE;
+}
+
+- (NSString*)name {
+ return name_;
+}
+
+- (NSString*)content {
+ return content_;
+}
+
+- (NSString*)domain {
+ return domain_;
+}
+
+- (NSString*)path {
+ return path_;
+}
+
+- (NSString*)sendFor {
+ return sendFor_;
+}
+
+- (NSString*)created {
+ return created_;
+}
+
+- (NSString*)expires {
+ return expires_;
+}
+
+- (NSString*)fileSize {
+ return nil;
+}
+
+- (NSString*)lastModified {
+ return nil;
+}
+
+- (NSString*)databaseDescription {
+ return nil;
+}
+
+- (NSString*)localStorageKey {
+ return localStorageKey_;
+}
+
+- (NSString*)localStorageValue {
+ return localStorageValue_;
+}
+
+@end
+
+@implementation CookiePromptWindowController
+
+- (id)initWithDialog:(CookiePromptModalDialog*)dialog {
+ NSString* nibpath = [mac_util::MainAppBundle()
+ pathForResource:@"CookiePrompt"
+ ofType:@"nib"];
+ if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+ dialog_ = dialog;
+ CookiePromptModalDialog::DialogType type(dialog_->dialog_type());
+ if (type == CookiePromptModalDialog::DIALOG_TYPE_COOKIE) {
+ selectionAdapterObject_.reset([[CookiePromptSelectionAdapter alloc]
+ initWithCookie:dialog_->cookie_line()
+ url:dialog_->origin()]);
+ } else if (type == CookiePromptModalDialog::DIALOG_TYPE_LOCAL_STORAGE) {
+ selectionAdapterObject_.reset([[CookiePromptSelectionAdapter alloc]
+ initWithLocalStorage:dialog_->origin().host()
+ key:dialog_->local_storage_key()
+ value:dialog_->local_storage_value()]);
+ } else if (type == CookiePromptModalDialog::DIALOG_TYPE_DATABASE) {
+ selectionAdapterObject_.reset([[CookiePromptSelectionAdapter alloc]
+ initWithDatabase:dialog_->origin().host()
+ name:dialog_->database_name()]);
+ } else {
+ NOTIMPLEMENTED();
+ }
+ }
+ return self;
+}
+
+// Ensures that all parameterized localized strings are filled in.
+- (void)doLocalizationTweaks {
+ int descriptionStringId = 0;
+ switch (dialog_->dialog_type()) {
+ case CookiePromptModalDialog::DIALOG_TYPE_COOKIE:
+ descriptionStringId = IDS_COOKIE_ALERT_LABEL;
+ break;
+ case CookiePromptModalDialog::DIALOG_TYPE_LOCAL_STORAGE:
+ descriptionStringId = IDS_DATA_ALERT_LABEL;
+ break;
+ case CookiePromptModalDialog::DIALOG_TYPE_DATABASE:
+ descriptionStringId = IDS_DATA_ALERT_LABEL;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ string16 displayHost = UTF8ToUTF16(dialog_->origin().host());
+ NSString* description = l10n_util::GetNSStringF(
+ descriptionStringId, displayHost);
+ [description_ setStringValue:description];
+
+ // Add the host to the "remember for future prompts" radio button.
+ NSString* allowText = l10n_util::GetNSStringWithFixup(
+ IDS_COOKIE_ALERT_REMEMBER_RADIO);
+ NSString* replacedCellText = base::SysUTF16ToNSString(
+ ReplaceStringPlaceholders(base::SysNSStringToUTF16(allowText),
+ displayHost, NULL));
+ [rememberChoiceCell_ setTitle:replacedCellText];
+}
+
+// Adjust the vertical layout of the views in the window so that
+// they are spaced correctly with their fully localized contents.
+- (void)doLayoutTweaks {
+ // Wrap the description text.
+ CGFloat sizeDelta = [GTMUILocalizerAndLayoutTweaker
+ sizeToFitFixedWidthTextField:description_];
+ NSRect descriptionFrame = [description_ frame];
+ descriptionFrame.origin.y -= sizeDelta;
+ [description_ setFrame:descriptionFrame];
+
+ // Wrap the radio buttons to fit if necessary.
+ [GTMUILocalizerAndLayoutTweaker
+ wrapRadioGroupForWidth:radioGroupMatrix_];
+ sizeDelta += [GTMUILocalizerAndLayoutTweaker
+ sizeToFitView:radioGroupMatrix_].height;
+ NSRect radioGroupFrame = [radioGroupMatrix_ frame];
+ radioGroupFrame.origin.y -= sizeDelta;
+ [radioGroupMatrix_ setFrame:radioGroupFrame];
+
+ // Adjust views location, they may have moved through the
+ // expansion of the radio buttons and description text.
+ NSRect disclosureViewFrame = [disclosureTriangleSuperView_ frame];
+ disclosureViewFrame.origin.y -= sizeDelta;
+ [disclosureTriangleSuperView_ setFrame:disclosureViewFrame];
+
+ // Adjust the final window size by the size of the cookie details
+ // view, since it will be initially hidden.
+ NSRect detailsViewRect = [disclosedViewPlaceholder_ frame];
+ sizeDelta -= detailsViewRect.size.height;
+
+ // Final resize the window to fit all of the adjustments
+ NSRect frame = [[self window] frame];
+ frame.origin.y -= sizeDelta;
+ frame.size.height += sizeDelta;
+ [[self window] setFrame:frame display:NO animate:NO];
+}
+
+- (void)replaceCookieDetailsView {
+ detailsViewController_.reset([[CookieDetailsViewController alloc] init]);
+
+ NSRect viewFrameRect = [disclosedViewPlaceholder_ frame];
+ [[disclosedViewPlaceholder_ superview]
+ replaceSubview:disclosedViewPlaceholder_
+ with:[detailsViewController_.get() view]];
+}
+
+- (void)awakeFromNib {
+ DCHECK(disclosureTriangle_);
+ DCHECK(radioGroupMatrix_);
+ DCHECK(disclosedViewPlaceholder_);
+ DCHECK(disclosureTriangleSuperView_);
+
+ [self doLocalizationTweaks];
+ [self doLayoutTweaks];
+ [self replaceCookieDetailsView];
+
+ [detailsViewController_ setContentObject:selectionAdapterObject_.get()];
+ [detailsViewController_ shrinkViewToFit];
+
+ [[detailsViewController_ view] setHidden:YES];
+}
+
+- (void)windowWillClose:(NSNotification*)notif {
+ [self autorelease];
+}
+
+// |contextInfo| is the bridge back to the C++ CookiePromptModalDialog.
+- (void)processModalDialogResult:(void*)contextInfo
+ returnCode:(int)returnCode {
+ CookiePromptModalDialog* bridge =
+ reinterpret_cast<CookiePromptModalDialog*>(contextInfo);
+ bool remember = [radioGroupMatrix_ selectedRow] == 0;
+ switch (returnCode) {
+ case NSAlertFirstButtonReturn: { // OK
+ bool sessionExpire = false;
+ bridge->AllowSiteData(remember, sessionExpire);
+ break;
+ }
+ case NSAlertSecondButtonReturn: { // Cancel
+ bridge->BlockSiteData(remember);
+ break;
+ }
+ default: {
+ NOTREACHED();
+ remember = false;
+ bridge->BlockSiteData(remember);
+ }
+ }
+}
+
+- (void)doModalDialog:(void*)context {
+ NSInteger returnCode = [NSApp runModalForWindow:[self window]];
+ [self processModalDialogResult:context returnCode:returnCode];
+}
+
+- (IBAction)disclosureTrianglePressed:(id)sender {
+ NSWindow* window = [self window];
+ NSRect frame = [[self window] frame];
+ CGFloat sizeChange = [[detailsViewController_.get() view] frame].size.height;
+ switch ([sender state]) {
+ case NSOnState:
+ frame.size.height += sizeChange;
+ frame.origin.y -= sizeChange;
+ break;
+ case NSOffState:
+ frame.size.height -= sizeChange;
+ frame.origin.y += sizeChange;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ if ([sender state] == NSOffState) {
+ [[detailsViewController_ view] setHidden:YES];
+ }
+ [window setFrame:frame display:YES animate:YES];
+ if ([sender state] == NSOnState) {
+ [[detailsViewController_ view] setHidden:NO];
+ }
+}
+
+// Callback for "accept" button.
+- (IBAction)accept:(id)sender {
+ [[self window] close];
+ [NSApp stopModalWithCode:NSAlertFirstButtonReturn];
+}
+
+// Callback for "block" button.
+- (IBAction)block:(id)sender {
+ [[self window] close];
+ [NSApp stopModalWithCode:NSAlertSecondButtonReturn];
+}
+
+@end
diff --git a/chrome/browser/cocoa/cookie_prompt_window_controller_unittest.mm b/chrome/browser/cocoa/cookie_prompt_window_controller_unittest.mm
new file mode 100644
index 0000000..8c9da0d
--- /dev/null
+++ b/chrome/browser/cocoa/cookie_prompt_window_controller_unittest.mm
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 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 "base/sys_string_conversions.h"
+#include "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/cocoa/cookie_prompt_window_controller.h"
+#include "chrome/browser/cookie_modal_dialog.h"
+
+namespace {
+
+class CookiePromptWindowControllerTest : public CocoaTest {
+};
+
+TEST_F(CookiePromptWindowControllerTest, CreateForCookie) {
+ GURL url("http://chromium.org");
+ std::string cookieLine(
+ "PHPSESSID=0123456789abcdef0123456789abcdef; path=/");
+ scoped_ptr<CookiePromptModalDialog> dialog(
+ new CookiePromptModalDialog(NULL, NULL, url, cookieLine, NULL));
+ scoped_nsobject<CookiePromptWindowController> controller(
+ [[CookiePromptWindowController alloc] initWithDialog:dialog.get()]);
+ EXPECT_TRUE(controller.get());
+ EXPECT_TRUE([controller.get() window]);
+}
+
+TEST_F(CookiePromptWindowControllerTest, CreateForDatabase) {
+ GURL url("http://google.com");
+ string16 databaseName(base::SysNSStringToUTF16(@"some database"));
+ scoped_ptr<CookiePromptModalDialog> dialog(
+ new CookiePromptModalDialog(NULL, NULL, url, databaseName, NULL));
+ scoped_nsobject<CookiePromptWindowController> controller(
+ [[CookiePromptWindowController alloc] initWithDialog:dialog.get()]);
+ EXPECT_TRUE(controller.get());
+ EXPECT_TRUE([controller.get() window]);
+}
+
+TEST_F(CookiePromptWindowControllerTest, CreateForLocalStorage) {
+ GURL url("http://chromium.org");
+ string16 key(base::SysNSStringToUTF16(@"key"));
+ string16 value(base::SysNSStringToUTF16(@"value"));
+ scoped_ptr<CookiePromptModalDialog> dialog(
+ new CookiePromptModalDialog(NULL, NULL, url, key, value, NULL));
+ scoped_nsobject<CookiePromptWindowController> controller(
+ [[CookiePromptWindowController alloc] initWithDialog:dialog.get()]);
+ EXPECT_TRUE(controller.get());
+ EXPECT_TRUE([controller.get() window]);
+}
+
+} // namespace
diff --git a/chrome/browser/cocoa/cookie_tree_node.h b/chrome/browser/cocoa/cookie_tree_node.h
index 5101157..66f5851 100644
--- a/chrome/browser/cocoa/cookie_tree_node.h
+++ b/chrome/browser/cocoa/cookie_tree_node.h
@@ -75,6 +75,12 @@ enum CocoaCookieTreeNodeType {
- (NSArray*)children;
- (BOOL)isLeaf;
+- (BOOL)isFolderOrCookieTreeDetails;
+- (BOOL)isLocalStorageTreeDetails;
+- (BOOL)isDatabaseTreeDetails;
+- (BOOL)isLocalStoragePromptDetails;
+- (BOOL)isDatabasePromptDetails;
+
// Used only by kCocoaCookieTreeNodeTypeCookie. Nil for other types.
- (NSString*)name;
- (NSString*)content;
diff --git a/chrome/browser/cocoa/cookie_tree_node.mm b/chrome/browser/cocoa/cookie_tree_node.mm
index 3d9eeaa..376df82 100644
--- a/chrome/browser/cocoa/cookie_tree_node.mm
+++ b/chrome/browser/cocoa/cookie_tree_node.mm
@@ -121,6 +121,27 @@
[self nodeType], [[self children] count]];
}
+- (BOOL)isFolderOrCookieTreeDetails {
+ return [self nodeType] == kCocoaCookieTreeNodeTypeFolder ||
+ [self nodeType] == kCocoaCookieTreeNodeTypeCookie;
+}
+
+- (BOOL)isDatabaseTreeDetails {
+ return [self nodeType] == kCocoaCookieTreeNodeTypeDatabaseStorage;
+}
+
+- (BOOL)isLocalStorageTreeDetails {
+ return [self nodeType] == kCocoaCookieTreeNodeTypeLocalStorage;
+}
+
+- (BOOL)isDatabasePromptDetails {
+ return false;
+}
+
+- (BOOL)isLocalStoragePromptDetails {
+ return false;
+}
+
#pragma mark Cookie Accessors
- (NSString*)name {
@@ -167,4 +188,24 @@
return databaseDescription_.get();
}
+#pragma mark Unused Accessors
+
+// This method is never called for the cookie tree, it is only
+// only included because the Cocoa bindings for the shared view
+// used to display browser data details always expects the method
+// even though it is only used in the cookie prompt window.
+- (id)localStorageKey {
+ NOTIMPLEMENTED();
+ return nil;
+}
+
+// This method is never called for the cookie tree, it is only
+// only included because the Cocoa bindings for the shared view
+// used to display browser data details always expects the method
+// even though it is only used in the cookie prompt window.
+- (id)localStorageValue {
+ NOTIMPLEMENTED();
+ return nil;
+}
+
@end
diff --git a/chrome/browser/cocoa/cookies_window_controller.h b/chrome/browser/cocoa/cookies_window_controller.h
index 8f85285..be38fb5 100644
--- a/chrome/browser/cocoa/cookies_window_controller.h
+++ b/chrome/browser/cocoa/cookies_window_controller.h
@@ -13,6 +13,7 @@
#include "net/base/cookie_monster.h"
@class CookiesWindowController;
+@class CookieDetailsViewController;
class Profile;
namespace {
@@ -101,13 +102,9 @@ class CookiesTreeModelObserverBridge : public CookiesTreeModel::Observer {
IBOutlet NSTreeController* treeController_;
IBOutlet NSOutlineView* outlineView_;
IBOutlet NSSearchField* searchField_;
+ IBOutlet NSView* cookieDetailsViewPlaceholder_;
- // These views are laid out inside a NSBox and are shown/hidden to detail
- // information about the selected node.
- IBOutlet NSView* cookieInfo_;
- IBOutlet NSView* databaseInfo_;
- IBOutlet NSView* localStorageInfo_;
-
+ scoped_nsobject<CookieDetailsViewController> detailsViewController_;
Profile* profile_; // weak
BrowsingDataDatabaseHelper* databaseHelper_; // weak
BrowsingDataLocalStorageHelper* storageHelper_; // weak
@@ -146,8 +143,5 @@ class CookiesTreeModelObserverBridge : public CookiesTreeModel::Observer {
- (void)clearBrowsingDataNotification:(NSNotification*)notif;
- (CookiesTreeModelObserverBridge*)modelObserver;
- (NSArray*)icons;
-- (NSView*)cookieInfoView;
-- (NSView*)localStorageInfoView;
-- (NSView*)databaseInfoInfoView;
- (void)loadTreeModelFromProfile;
@end
diff --git a/chrome/browser/cocoa/cookies_window_controller.mm b/chrome/browser/cocoa/cookies_window_controller.mm
index e2f53c5..d3b6035 100644
--- a/chrome/browser/cocoa/cookies_window_controller.mm
+++ b/chrome/browser/cocoa/cookies_window_controller.mm
@@ -14,6 +14,7 @@
#include "base/sys_string_conversions.h"
#include "chrome/browser/browsing_data_remover.h"
#include "chrome/browser/cocoa/clear_browsing_data_controller.h"
+#include "chrome/browser/cocoa/cookie_details_view_controller.h"
#include "chrome/browser/profile.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -226,6 +227,17 @@ bool CookiesTreeModelObserverBridge::HasCocoaModel() {
- (void)awakeFromNib {
DCHECK([self window]);
DCHECK_EQ(self, [[self window] delegate]);
+
+ detailsViewController_.reset([[CookieDetailsViewController alloc] init]);
+
+ NSView* detailView = [detailsViewController_.get() view];
+ NSRect viewFrameRect = [cookieDetailsViewPlaceholder_ frame];
+ [[detailsViewController_.get() view] setFrame:viewFrameRect];
+ [[cookieDetailsViewPlaceholder_ superview]
+ replaceSubview:cookieDetailsViewPlaceholder_
+ with:detailView];
+
+ [detailsViewController_ configureBindingsForTreeController:treeController_];
}
- (void)windowWillClose:(NSNotification*)notif {
@@ -356,12 +368,6 @@ bool CookiesTreeModelObserverBridge::HasCocoaModel() {
if (count != 1U) {
DCHECK_LT(count, 1U) << "User was able to select more than 1 cookie node!";
[self setRemoveButtonEnabled:NO];
-
- // Make sure that the cookie info pane is shown when there is no selection.
- // That's what windows does.
- [cookieInfo_ setHidden:NO];
- [localStorageInfo_ setHidden:YES];
- [databaseInfo_ setHidden:YES];
return;
}
@@ -378,18 +384,6 @@ bool CookiesTreeModelObserverBridge::HasCocoaModel() {
}
node = [[node children] objectAtIndex:childIndex];
}
-
- [self setRemoveButtonEnabled:YES];
- CocoaCookieTreeNodeType nodeType = [[selectedObjects lastObject] nodeType];
- bool hideCookieInfoView = nodeType != kCocoaCookieTreeNodeTypeCookie &&
- nodeType != kCocoaCookieTreeNodeTypeFolder;
- bool hideLocaStorageInfoView =
- nodeType != kCocoaCookieTreeNodeTypeLocalStorage;
- bool hideDatabaseInfoView =
- nodeType != kCocoaCookieTreeNodeTypeDatabaseStorage;
- [cookieInfo_ setHidden:hideCookieInfoView];
- [localStorageInfo_ setHidden:hideLocaStorageInfoView];
- [databaseInfo_ setHidden:hideDatabaseInfoView];
}
#pragma mark Unit Testing
@@ -402,18 +396,6 @@ bool CookiesTreeModelObserverBridge::HasCocoaModel() {
return icons_.get();
}
-- (NSView*)cookieInfoView {
- return cookieInfo_;
-}
-
-- (NSView*)localStorageInfoView {
- return localStorageInfo_;
-}
-
-- (NSView*)databaseInfoView {
- return databaseInfo_;
-}
-
// Re-initializes the |treeModel_|, creates a new observer for it, and re-
// builds the |cocoaTreeModel_|. We use this to initialize the controller and
// to rebuild after the user clears browsing data. Because the models get
diff --git a/chrome/browser/cocoa/cookies_window_controller_unittest.mm b/chrome/browser/cocoa/cookies_window_controller_unittest.mm
index b58c584..fb19db3 100644
--- a/chrome/browser/cocoa/cookies_window_controller_unittest.mm
+++ b/chrome/browser/cocoa/cookies_window_controller_unittest.mm
@@ -480,8 +480,6 @@ TEST_F(CookiesWindowControllerTest, FLAKY_RemoveButtonEnabled) {
[[controller treeController] setSelectionIndexPath:indexPath];
[controller outlineViewSelectionDidChange:nil];
EXPECT_TRUE([controller removeButtonEnabled]);
- EXPECT_FALSE([[controller cookieInfoView] isHidden]);
- EXPECT_TRUE([[controller localStorageInfoView] isHidden]);
}
{
@@ -491,8 +489,6 @@ TEST_F(CookiesWindowControllerTest, FLAKY_RemoveButtonEnabled) {
[[controller treeController] setSelectionIndexPath:indexPath];
[controller outlineViewSelectionDidChange:nil];
EXPECT_TRUE([controller removeButtonEnabled]);
- EXPECT_FALSE([[controller cookieInfoView] isHidden]);
- EXPECT_TRUE([[controller localStorageInfoView] isHidden]);
}
{
@@ -502,8 +498,6 @@ TEST_F(CookiesWindowControllerTest, FLAKY_RemoveButtonEnabled) {
[[controller treeController] setSelectionIndexPath:indexPath];
[controller outlineViewSelectionDidChange:nil];
EXPECT_TRUE([controller removeButtonEnabled]);
- EXPECT_TRUE([[controller cookieInfoView] isHidden]);
- EXPECT_FALSE([[controller localStorageInfoView] isHidden]);
}
{
@@ -527,8 +521,7 @@ TEST_F(CookiesWindowControllerTest, FLAKY_RemoveButtonEnabled) {
[controller closeSheet:nil];
}
-TEST_F(CookiesWindowControllerTest, UpdateFilter)
-{
+TEST_F(CookiesWindowControllerTest, UpdateFilter) {
const GURL url = GURL("http://foo.com");
TestingProfile* profile = browser_helper_.profile();
net::CookieMonster* cm = profile->GetCookieMonster();
diff --git a/chrome/browser/cookie_modal_dialog.h b/chrome/browser/cookie_modal_dialog.h
index 7a6ae50..997dd7f 100644
--- a/chrome/browser/cookie_modal_dialog.h
+++ b/chrome/browser/cookie_modal_dialog.h
@@ -13,6 +13,14 @@
#include "chrome/browser/cookie_prompt_modal_dialog_delegate.h"
#include "googleurl/src/gurl.h"
+#if defined(OS_MACOSX)
+#if __OBJC__
+@class NSWindow;
+#else
+class NSWindow;
+#endif
+#endif
+
class HostContentSettingsMap;
class PrefService;
@@ -58,6 +66,10 @@ class CookiePromptModalDialog : public AppModalDialog {
virtual void CancelWindow();
virtual bool IsValid();
+#if defined(OS_MACOSX)
+ virtual void CloseModalDialog();
+#endif
+
DialogType dialog_type() const { return dialog_type_; }
const GURL& origin() const { return origin_; }
const std::string& cookie_line() const { return cookie_line_; }
@@ -78,6 +90,11 @@ class CookiePromptModalDialog : public AppModalDialog {
#endif
private:
+
+#if defined(OS_MACOSX)
+ NSWindow* dialog_;
+#endif
+
// Used to verify our request is still necessary and when the response should
// persist.
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
diff --git a/chrome/browser/cookie_modal_dialog_mac.mm b/chrome/browser/cookie_modal_dialog_mac.mm
index e80c2d6..35a54e0 100644
--- a/chrome/browser/cookie_modal_dialog_mac.mm
+++ b/chrome/browser/cookie_modal_dialog_mac.mm
@@ -3,118 +3,22 @@
// found in the LICENSE file.
#include "chrome/browser/cookie_modal_dialog.h"
+#import "chrome/browser/cocoa/cookie_prompt_window_controller.h"
#import <Cocoa/Cocoa.h>
#include "app/l10n_util_mac.h"
#import "base/cocoa_protocols_mac.h"
+#include "base/mac_util.h"
#include "base/scoped_nsobject.h"
#include "base/logging.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "grit/generated_resources.h"
-// Helper object that will become a real NSWindowController in the future.
-@interface CookiePromptModalDialogHelper : NSObject<NSAlertDelegate> {
- @private
- scoped_nsobject<NSAlert> alert_;
- scoped_nsobject<NSMatrix> matrix_;
-}
-
-- (id)initWithBridge:(CookiePromptModalDialog*)bridge;
-- (NSAlert*)alert;
-- (void)alertDidEnd:(NSAlert*)alert
- returnCode:(int)returnCode
- contextInfo:(void*)contextInfo;
-@end
-
-@implementation CookiePromptModalDialogHelper
-
-- (id)initWithBridge:(CookiePromptModalDialog*)bridge {
- // The cookie confirmation dialog needs both a radio group and a disclosure
- // triangle, so it's too complex to be shown as an NSAlert -- a custom window
- // is required. However, that requires small modifications to the parent class
- // AppModalDialog, so I'll do that in another CL.
- if ((self = [super init])) {
- alert_.reset([[NSAlert alloc] init]);
-
- string16 displayHost = UTF8ToUTF16(bridge->origin().host());
- int descriptionStringId =
- bridge->dialog_type() == CookiePromptModalDialog::DIALOG_TYPE_COOKIE ?
- IDS_COOKIE_ALERT_LABEL : IDS_DATA_ALERT_LABEL;
- NSString* description = l10n_util::GetNSStringF(
- descriptionStringId, displayHost);
- NSString* allow =
- l10n_util::GetNSStringWithFixup(IDS_COOKIE_ALERT_ALLOW_BUTTON);
- NSString* block =
- l10n_util::GetNSStringWithFixup(IDS_COOKIE_ALERT_BLOCK_BUTTON);
-
- NSString* remember = l10n_util::GetNSStringF(
- IDS_COOKIE_ALERT_REMEMBER_RADIO, displayHost);
- NSString* ask = l10n_util::GetNSStringWithFixup(IDS_COOKIE_ALERT_ASK_RADIO);
-
- scoped_nsobject<NSButtonCell> prototype([[NSButtonCell alloc] init]);
- [prototype.get() setButtonType:NSRadioButton];
- matrix_.reset(
- [[NSMatrix alloc] initWithFrame:NSZeroRect
- mode:NSRadioModeMatrix
- prototype:prototype
- numberOfRows:2
- numberOfColumns:1]);
- NSArray *cellArray = [matrix_.get() cells];
- [[cellArray objectAtIndex:0] setTitle:remember];
- [[cellArray objectAtIndex:1] setTitle:ask];
- [matrix_.get() sizeToFit];
- [alert_.get() setAccessoryView:matrix_.get()];
-
- [alert_.get() setMessageText:description];
- [alert_.get() addButtonWithTitle:allow];
- [alert_.get() addButtonWithTitle:block];
- }
- return self;
-}
-
-- (NSAlert*)alert {
- return alert_.get();
-}
-
-// |contextInfo| is the bridge back to the C++ CookiePromptModalDialog.
-- (void)alertDidEnd:(NSAlert*)alert
- returnCode:(int)returnCode
- contextInfo:(void*)contextInfo {
- CookiePromptModalDialog* bridge =
- reinterpret_cast<CookiePromptModalDialog*>(contextInfo);
- bool remember = [matrix_.get() selectedRow] == 0;
- switch (returnCode) {
- case NSAlertFirstButtonReturn: { // OK
- bool sessionExpire = false;
- bridge->AllowSiteData(remember, sessionExpire);
- break;
- }
- case NSAlertSecondButtonReturn: { // Cancel
- bridge->BlockSiteData(remember);
- break;
- }
- case NSRunStoppedResponse: { // Window was closed underneath us
- bridge->BlockSiteData(remember);
- break;
- }
- default: {
- NOTREACHED();
- remember = false;
- bridge->BlockSiteData(remember);
- }
- }
-}
-@end
-
void CookiePromptModalDialog::CreateAndShowDialog() {
- scoped_nsobject<CookiePromptModalDialogHelper> helper(
- [[CookiePromptModalDialogHelper alloc] initWithBridge:this]);
- NSAlert* alert = [helper alert];
- DCHECK(alert);
-
- NSInteger result = [alert runModal];
- [helper.get() alertDidEnd:alert returnCode:result contextInfo:this];
+ scoped_nsobject<CookiePromptWindowController> controller(
+ [[CookiePromptWindowController alloc] initWithDialog:this]);
+ [controller.get() doModalDialog:this];
// Other than JavaScriptAppModalDialog, the cross-platform part of this class
// does not call |CompleteDialog()|, an explicit call is required.
@@ -133,6 +37,10 @@ void CookiePromptModalDialog::CancelWindow() {
NOTIMPLEMENTED();
}
+void CookiePromptModalDialog::CloseModalDialog() {
+ dialog_ = nil;
+}
+
// This is only used by the app-modal dialog machinery on windows.
NativeDialog CookiePromptModalDialog::CreateNativeDialog() {
NOTIMPLEMENTED();
diff --git a/chrome/browser/js_modal_dialog.h b/chrome/browser/js_modal_dialog.h
index 51b9c81..65ed1ae 100644
--- a/chrome/browser/js_modal_dialog.h
+++ b/chrome/browser/js_modal_dialog.h
@@ -13,6 +13,14 @@
#include "chrome/common/notification_registrar.h"
#include "net/base/cookie_monster.h"
+#if defined(OS_MACOSX)
+#if __OBJC__
+@class NSAlert;
+#else
+class NSAlert;
+#endif
+#endif
+
class ExtensionHost;
class JavaScriptMessageBoxClient;
@@ -56,6 +64,10 @@ class JavaScriptAppModalDialog : public AppModalDialog,
return is_before_unload_dialog_;
}
+#if defined(OS_MACOSX)
+ virtual void CloseModalDialog();
+#endif
+
// Callbacks from NativeDialog when the user accepts or cancels the dialog.
void OnCancel();
void OnAccept(const std::wstring& prompt_text, bool suppress_js_messages);
@@ -75,6 +87,10 @@ class JavaScriptAppModalDialog : public AppModalDialog,
// Initializes for notifications to listen.
void InitNotifications();
+#if defined(OS_MACOSX)
+ NSAlert* dialog_;
+#endif
+
NotificationRegistrar registrar_;
// An implementation of the client interface to provide supporting methods
diff --git a/chrome/browser/js_modal_dialog_mac.mm b/chrome/browser/js_modal_dialog_mac.mm
index 44eb86e..3bdc9aa 100644
--- a/chrome/browser/js_modal_dialog_mac.mm
+++ b/chrome/browser/js_modal_dialog_mac.mm
@@ -172,3 +172,10 @@ NativeDialog JavaScriptAppModalDialog::CreateNativeDialog() {
NOTIMPLEMENTED();
return nil;
}
+
+void JavaScriptAppModalDialog::CloseModalDialog() {
+ NSAlert* alert = dialog_;
+ DCHECK([alert isKindOfClass:[NSAlert class]]);
+ [NSApp endSheet:[alert window]];
+ dialog_ = nil;
+}