[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / global_error_bubble_controller.mm
blobedfbff26da80c575df10a4c7171075daec23ea3d
1 // Copyright (c) 2012 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.
5 #import "chrome/browser/ui/cocoa/global_error_bubble_controller.h"
7 #include "base/logging.h"
8 #include "base/mac/scoped_nsobject.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/search_engines/util.h"
13 #import "chrome/browser/ui/browser.h"
14 #import "chrome/browser/ui/browser_window.h"
15 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
16 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
17 #import "chrome/browser/ui/cocoa/l10n_util.h"
18 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
19 #import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h"
20 #include "chrome/browser/ui/global_error/global_error.h"
21 #include "chrome/browser/ui/global_error/global_error_bubble_view_base.h"
22 #include "chrome/browser/ui/global_error/global_error_service.h"
23 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
24 #include "grit/generated_resources.h"
25 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/gfx/image/image.h"
29 namespace {
30 const CGFloat kParagraphSpacing = 6;
31 } // namespace
33 namespace GlobalErrorBubbleControllerInternal {
35 // This is the bridge to the C++ GlobalErrorBubbleViewBase object.
36 class Bridge : public GlobalErrorBubbleViewBase {
37  public:
38   Bridge(GlobalErrorBubbleController* controller) : controller_(controller) {
39   }
41  private:
42   virtual void CloseBubbleView() OVERRIDE {
43     [controller_ close];
44   }
46   GlobalErrorBubbleController* controller_;  // Weak, owns this.
49 }  // namespace GlobalErrorBubbleControllerInternal
51 @implementation GlobalErrorBubbleController
53 + (GlobalErrorBubbleViewBase*)showForBrowser:(Browser*)browser
54     error:(const base::WeakPtr<GlobalErrorWithStandardBubble>&)error {
55   NSWindow* parentWindow = browser->window()->GetNativeWindow();
56   BrowserWindowController* bwc = [BrowserWindowController
57       browserWindowControllerForWindow:parentWindow];
58   NSView* wrenchButton = [[bwc toolbarController] wrenchButton];
59   NSPoint offset = NSMakePoint(
60       NSMidX([wrenchButton bounds]),
61       wrench_menu_controller::kWrenchBubblePointOffsetY);
63   // The bubble will be automatically deleted when the window is closed.
64   GlobalErrorBubbleController* bubble = [[GlobalErrorBubbleController alloc]
65       initWithWindowNibPath:@"GlobalErrorBubble"
66              relativeToView:wrenchButton
67                      offset:offset];
68   bubble->error_ = error;
69   bubble->bridge_.reset(new GlobalErrorBubbleControllerInternal::Bridge(
70       bubble));
71   bubble->browser_ = browser;
72   [bubble showWindow:nil];
74   return bubble->bridge_.get();
77 - (void)awakeFromNib {
78   [super awakeFromNib];
80   DCHECK(error_);
82   gfx::Image image = error_->GetBubbleViewIcon();
83   DCHECK(!image.IsEmpty());
84   [iconView_ setImage:image.ToNSImage()];
86   [title_ setStringValue:SysUTF16ToNSString(error_->GetBubbleViewTitle())];
87   std::vector<base::string16> messages = error_->GetBubbleViewMessages();
88   base::string16 message = JoinString(messages, '\n');
90   base::scoped_nsobject<NSMutableAttributedString> messageValue(
91       [[NSMutableAttributedString alloc]
92           initWithString:SysUTF16ToNSString(message)]);
93   base::scoped_nsobject<NSMutableParagraphStyle> style(
94       [[NSMutableParagraphStyle alloc] init]);
95   [style setParagraphSpacing:kParagraphSpacing];
96   [messageValue addAttribute:NSParagraphStyleAttributeName
97                        value:style
98                        range:NSMakeRange(0, [messageValue length])];
100   [message_ setAttributedStringValue:messageValue];
102   [acceptButton_ setTitle:
103       SysUTF16ToNSString(error_->GetBubbleViewAcceptButtonLabel())];
104   base::string16 cancelLabel = error_->GetBubbleViewCancelButtonLabel();
105   if (cancelLabel.empty())
106     [cancelButton_ setHidden:YES];
107   else
108     [cancelButton_ setTitle:SysUTF16ToNSString(cancelLabel)];
110   // First make sure that the window is wide enough to accommodate the buttons.
111   NSRect frame = [[self window] frame];
112   [layoutTweaker_ tweakUI:buttonContainer_];
113   CGFloat delta =  NSWidth([buttonContainer_ frame]) - NSWidth(frame);
114   if (delta > 0) {
115     frame.size.width += delta;
116     [[self window] setFrame:frame display:NO];
117   }
119   // Adapt window height to bottom buttons. Do this before all other layouting.
120   NSArray* views = [NSArray arrayWithObjects:
121       title_, message_, buttonContainer_, nil];
122   NSSize ds = NSMakeSize(0, cocoa_l10n_util::VerticallyReflowGroup(views));
123   ds = [[self bubble] convertSize:ds toView:nil];
125   frame.origin.y -= ds.height;
126   frame.size.height += ds.height;
127   [[self window] setFrame:frame display:YES];
130 - (void)showWindow:(id)sender {
131   BrowserWindowController* bwc = [BrowserWindowController
132       browserWindowControllerForWindow:[self parentWindow]];
133   [bwc lockBarVisibilityForOwner:self withAnimation:NO delay:NO];
134   [super showWindow:sender];
137 - (void)close {
138   if (error_)
139     error_->BubbleViewDidClose(browser_);
140   bridge_.reset();
141   BrowserWindowController* bwc = [BrowserWindowController
142       browserWindowControllerForWindow:[self parentWindow]];
143   [bwc releaseBarVisibilityForOwner:self withAnimation:YES delay:NO];
144   [super close];
147 - (IBAction)onAccept:(id)sender {
148   if (error_)
149     error_->BubbleViewAcceptButtonPressed(browser_);
150   [self close];
153 - (IBAction)onCancel:(id)sender {
154   if (error_)
155     error_->BubbleViewCancelButtonPressed(browser_);
156   [self close];
159 @end
161 GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowStandardBubbleView(
162     Browser* browser,
163     const base::WeakPtr<GlobalErrorWithStandardBubble>& error) {
164   return [GlobalErrorBubbleController showForBrowser:browser error:error];