Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: chrome/browser/ui/certificate_viewer_mac.mm

Issue 2356113002: Mac: Hack around Sierra autolayout bug in the certificate viewer. (Closed)
Patch Set: self nits Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/certificate_viewer_mac.h" 5 #import "chrome/browser/ui/certificate_viewer_mac.h"
6 6
7 #import <objc/runtime.h>
8
7 #include "base/mac/foundation_util.h" 9 #include "base/mac/foundation_util.h"
10 #include "base/mac/mac_util.h"
8 #include "base/mac/scoped_cftyperef.h" 11 #include "base/mac/scoped_cftyperef.h"
9 #import "base/mac/scoped_nsobject.h" 12 #import "base/mac/scoped_nsobject.h"
10 #include "content/public/browser/web_contents.h" 13 #include "content/public/browser/web_contents.h"
11 #include "net/cert/x509_certificate.h" 14 #include "net/cert/x509_certificate.h"
12 #include "net/cert/x509_util_mac.h" 15 #include "net/cert/x509_util_mac.h"
13 16
17 namespace {
18
19 // The maximum height of the certificate panel. Imposed whenever Sierra's buggy
20 // autolayout algorithm tries to change it. Doesn't affect user resizes.
21 const CGFloat kMaxPanelSetFrameHeight = 400;
22
23 // Pointer to the real implementation of -[SFCertificatePanel setFrame:..]. This
24 // is cached so a correct lookup is performed before we add the override.
25 IMP g_real_certificate_panel_setframe = nullptr;
26
27 // Provide a workaround for a buggy autolayout algorithm in macOS Sierra when
28 // running Chrome linked against the 10.10 SDK on macOS 10.12.
29 // See http://crbug.com/643123 for more details.
30 // Note it's not possible to inherit from SFCertificatePanel without triggering
31 // *** Assertion failure in -[BrowserCrApplication
32 // _commonBeginModalSessionForWindow:relativeToWindow:modalDelegate:
33 // didEndSelector:contextInfo:], .../AppKit.subproj/NSApplication.m:4077
34 // After that assertion, the sheet simply refuses to continue loading.
35 // It's also not possible to swizzle the -setFrame: method because
36 // SFCertificatePanel doesn't define it. Attempting to swizzle that would
37 // replace the implementation on NSWindow and constrain all dialogs.
38 // So, provide a regular C method and append it to the SFCertificatePanel
39 // implementation using the objc runtime.
40 // TODO(tapted): Remove all of this when Chrome's SDK target gets bumped.
41 id SFCertificatePanelSetFrameOverride(id self,
42 SEL _cmd,
43 NSRect frame,
44 BOOL display,
45 BOOL animate) {
46 if (frame.size.height > kMaxPanelSetFrameHeight)
47 frame.size.height = kMaxPanelSetFrameHeight;
48
49 DCHECK(g_real_certificate_panel_setframe);
50 return g_real_certificate_panel_setframe(self, _cmd, frame, display, animate);
51 }
52
53 void MaybeConstrainPanelSizeForSierraBug() {
54 #if defined(MAC_OS_X_VERSION_10_11) && \
55 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11
56 // This is known not to be required when linking against the 10.11 SDK. Early
57 // exit in that case but assume anything earlier is broken.
58 return;
59 #endif
60
61 // It's also not required when running on El Capitan or earlier.
62 if (base::mac::IsAtMostOS10_11() || g_real_certificate_panel_setframe)
63 return;
64
65 const SEL kSetFrame = @selector(setFrame:display:animate:);
66 Method real_method =
67 class_getInstanceMethod([SFCertificatePanel class], kSetFrame);
68 const char* type_encoding = method_getTypeEncoding(real_method);
69 g_real_certificate_panel_setframe = method_getImplementation(real_method);
70 DCHECK(g_real_certificate_panel_setframe);
71 IMP method = reinterpret_cast<IMP>(&SFCertificatePanelSetFrameOverride);
72 class_addMethod([SFCertificatePanel class], kSetFrame, method, type_encoding);
Mark Mentovai 2016/09/21 12:30:16 Check the return value, at least via a DCHECK. Thi
tapted 2016/09/21 13:07:04 Done.
73 }
74
75 } // namespace
76
14 @interface SFCertificatePanel (SystemPrivate) 77 @interface SFCertificatePanel (SystemPrivate)
15 // A system-private interface that dismisses a panel whose sheet was started by 78 // A system-private interface that dismisses a panel whose sheet was started by
16 // -beginSheetForWindow: 79 // -beginSheetForWindow:
17 // modalDelegate: 80 // modalDelegate:
18 // didEndSelector: 81 // didEndSelector:
19 // contextInfo: 82 // contextInfo:
20 // certificates: 83 // certificates:
21 // showGroup: 84 // showGroup:
22 // as though the user clicked the button identified by returnCode. Verified 85 // as though the user clicked the button identified by returnCode. Verified
23 // present in 10.8. 86 // present in 10.8.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 return self; 144 return self;
82 } 145 }
83 146
84 - (void)sheetDidEnd:(NSWindow*)parent 147 - (void)sheetDidEnd:(NSWindow*)parent
85 returnCode:(NSInteger)returnCode 148 returnCode:(NSInteger)returnCode
86 context:(void*)context { 149 context:(void*)context {
87 NOTREACHED(); // Subclasses must implement this. 150 NOTREACHED(); // Subclasses must implement this.
88 } 151 }
89 152
90 - (void)showCertificateSheet:(NSWindow*)window { 153 - (void)showCertificateSheet:(NSWindow*)window {
154 MaybeConstrainPanelSizeForSierraBug();
155
91 [panel_ beginSheetForWindow:window 156 [panel_ beginSheetForWindow:window
92 modalDelegate:self 157 modalDelegate:self
93 didEndSelector:@selector(sheetDidEnd:returnCode:context:) 158 didEndSelector:@selector(sheetDidEnd:returnCode:context:)
94 contextInfo:nil 159 contextInfo:nil
95 certificates:certificates_ 160 certificates:certificates_
96 showGroup:YES]; 161 showGroup:YES];
97 } 162 }
98 163
99 - (void)closeCertificateSheet { 164 - (void)closeCertificateSheet {
100 // Closing the sheet using -[NSApp endSheet:] doesn't work so use the private 165 // Closing the sheet using -[NSApp endSheet:] doesn't work so use the private
101 // method. 166 // method.
102 [panel_ _dismissWithCode:NSFileHandlingPanelCancelButton]; 167 [panel_ _dismissWithCode:NSFileHandlingPanelCancelButton];
103 certificates_.reset(); 168 certificates_.reset();
104 } 169 }
105 170
106 - (void)releaseSheetWindow { 171 - (void)releaseSheetWindow {
107 panel_.reset(); 172 panel_.reset();
108 } 173 }
109 174
110 - (NSWindow*)certificatePanel { 175 - (NSWindow*)certificatePanel {
111 return panel_; 176 return panel_;
112 } 177 }
113 178
114 @end 179 @end
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698