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

Side by Side Diff: ios/chrome/browser/ui/reader_mode/reader_mode_controller.mm

Issue 2589583003: Upstream Chrome on iOS source code [7/11]. (Closed)
Patch Set: Created 4 years 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
OLDNEW
(Empty)
1 // Copyright 2015 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 #import "ios/chrome/browser/ui/reader_mode/reader_mode_controller.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/ios/weak_nsobject.h"
11 #include "base/mac/bind_objc_block.h"
12 #include "base/mac/scoped_nsobject.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "components/infobars/core/infobar.h"
16 #include "components/infobars/core/infobar_manager.h"
17 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
18 #include "ios/chrome/browser/dom_distiller/distiller_viewer.h"
19 #include "ios/chrome/browser/dom_distiller/dom_distiller_service_factory.h"
20 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
21 #import "ios/chrome/browser/ui/reader_mode/reader_mode_checker.h"
22 #import "ios/chrome/browser/ui/reader_mode/reader_mode_infobar_delegate.h"
23 #import "ios/chrome/browser/ui/reader_mode/reader_mode_view.h"
24 #include "ios/web/public/browser_state.h"
25 #include "ios/web/public/web_state/web_state.h"
26
27 @protocol ReaderModeCheckerObserverBridgeProtocol
28 - (void)pageIsDistillable;
29 @end
30
31 @protocol InfoBarManagerObserverBridgeProtocol
32 - (void)infoBarRemoved:(infobars::InfoBar*)infobar;
33 @end
34
35 namespace {
36 // Used to find the ReaderModeView in the view hierarchy.
37 const NSInteger kReaderModeViewTag = 42;
38 const CGFloat kReaderModeAnimationDuration = .5;
39
40 class ReaderModeCheckerObserverBridge : ReaderModeCheckerObserver {
41 public:
42 ReaderModeCheckerObserverBridge(
43 ReaderModeChecker* readerModeChecker,
44 id<ReaderModeCheckerObserverBridgeProtocol> observer)
45 : ReaderModeCheckerObserver(readerModeChecker), observer_(observer) {
46 DCHECK(observer);
47 };
48
49 void PageIsDistillable() override { [observer_ pageIsDistillable]; };
50
51 private:
52 id<ReaderModeCheckerObserverBridgeProtocol> observer_;
53 };
54
55 class InfoBarManagerObserverBridge : infobars::InfoBarManager::Observer {
56 public:
57 InfoBarManagerObserverBridge(
58 infobars::InfoBarManager* infoBarManager,
59 id<InfoBarManagerObserverBridgeProtocol> observer)
60 : infobars::InfoBarManager::Observer(),
61 manager_(infoBarManager),
62 observer_(observer) {
63 DCHECK(infoBarManager);
64 DCHECK(observer);
65 manager_->AddObserver(this);
66 };
67
68 ~InfoBarManagerObserverBridge() override {
69 if (manager_)
70 manager_->RemoveObserver(this);
71 }
72
73 void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override {
74 [observer_ infoBarRemoved:infobar];
75 }
76
77 void OnManagerShuttingDown(infobars::InfoBarManager* manager) override {
78 manager_->RemoveObserver(this);
79 manager_ = nullptr;
80 }
81
82 private:
83 infobars::InfoBarManager* manager_;
84 id<InfoBarManagerObserverBridgeProtocol> observer_;
85 };
86 } // namespace
87
88 @interface ReaderModeController ()<ReaderModeViewDelegate,
89 ReaderModeCheckerObserverBridgeProtocol,
90 InfoBarManagerObserverBridgeProtocol> {
91 std::unique_ptr<ReaderModeChecker> _checker;
92 std::unique_ptr<ReaderModeCheckerObserverBridge> _checkerBridge;
93 std::unique_ptr<InfoBarManagerObserverBridge> _infoBarBridge;
94 std::unique_ptr<dom_distiller::DistillerViewer> _viewer;
95 // The currently displayed infobar.
96 infobars::InfoBar* infobar_;
97 web::WebState* _webState;
98 }
99 @property(readonly, nonatomic) id<ReaderModeControllerDelegate> delegate;
100
101 // Triggers a distillation and returns a DistillerViewer to keep as a handle to
102 // the running distillation.
103 - (std::unique_ptr<dom_distiller::DistillerViewer>)startDistillation
104 WARN_UNUSED_RESULT;
105 - (void)distillationFinished:(const std::string&)html forURL:(const GURL&)url;
106
107 // Returns a ReaderModeView that presents a waiting UI while the distillation
108 // is taking place. Releasing this view will stop the distillation in progress.
109 - (ReaderModeView*)readerModeViewWithFrame:(CGRect)frame;
110
111 - (void)showInfoBar:(const std::string&)html forURL:(const GURL&)url;
112 - (void)removeInfoBar;
113
114 @end
115
116 @implementation ReaderModeController
117 @synthesize delegate = _delegate;
118
119 - (instancetype)initWithWebState:(web::WebState*)webState
120 delegate:(id<ReaderModeControllerDelegate>)delegate {
121 DCHECK(webState);
122 self = [super init];
123 if (self) {
124 _webState = webState;
125 _checker = base::MakeUnique<ReaderModeChecker>(_webState);
126 _delegate = delegate;
127 _checkerBridge =
128 base::MakeUnique<ReaderModeCheckerObserverBridge>(_checker.get(), self);
129 infobars::InfoBarManager* infobar_manager =
130 InfoBarManagerImpl::FromWebState(_webState);
131 _infoBarBridge =
132 base::MakeUnique<InfoBarManagerObserverBridge>(infobar_manager, self);
133 }
134 return self;
135 }
136
137 - (instancetype)init {
138 NOTREACHED();
139 return nil;
140 }
141
142 - (void)dealloc {
143 if (_webState)
144 [self detachFromWebState];
145 [super dealloc];
146 }
147
148 - (void)detachFromWebState {
149 [self removeInfoBar];
150 _webState = nullptr;
151 }
152
153 // Property accessor.
154 - (ReaderModeChecker*)checker {
155 return _checker.get();
156 }
157
158 #pragma mark - Private methods.
159 #pragma mark distillation
160
161 - (std::unique_ptr<dom_distiller::DistillerViewer>)startDistillation {
162 DCHECK(_webState);
163 base::WeakNSObject<ReaderModeController> weakSelf(self);
164 GURL pageURL = _webState->GetLastCommittedURL();
165 ios::ChromeBrowserState* browserState =
166 ios::ChromeBrowserState::FromBrowserState(_webState->GetBrowserState());
167 return base::MakeUnique<dom_distiller::DistillerViewer>(
168 dom_distiller::DomDistillerServiceFactory::GetForBrowserState(
169 browserState),
170 browserState->GetPrefs(), pageURL,
171 base::BindBlock(^(
172 const GURL& pageURL, const std::string& html,
173 const std::vector<dom_distiller::DistillerViewer::ImageInfo>& images,
174 const std::string& title) {
175 [weakSelf distillationFinished:html forURL:pageURL];
176 }));
177 }
178
179 - (void)distillationFinished:(const std::string&)html forURL:(const GURL&)url {
180 UIView* superview = [self.delegate superviewForReaderModePanel];
181 DCHECK(_viewer || [superview viewWithTag:kReaderModeViewTag]);
182 if ([superview viewWithTag:kReaderModeViewTag]) {
183 [self.delegate loadReaderModeHTML:base::SysUTF8ToNSString(html) forURL:url];
184 } else if (_viewer) {
185 [self showInfoBar:html forURL:url];
186 }
187 }
188
189 #pragma mark view creation
190
191 - (ReaderModeView*)readerModeViewWithFrame:(CGRect)frame {
192 DCHECK(_checker->CanSwitchToReaderMode());
193 ReaderModeView* view =
194 [[[ReaderModeView alloc] initWithFrame:frame delegate:self] autorelease];
195 [view assignDistillerViewer:[self startDistillation]];
196 return view;
197 }
198
199 #pragma mark infobar.
200
201 - (void)showInfoBar:(const std::string&)html forURL:(const GURL&)url {
202 DCHECK(_webState);
203 base::WeakNSProtocol<id<ReaderModeControllerDelegate>> weakDelegate(
204 self.delegate);
205
206 // Non reference version of the variables needed.
207 const std::string html_non_ref(html);
208 const GURL url_non_ref(url);
209 auto infoBarDelegate =
210 base::MakeUnique<ReaderModeInfoBarDelegate>(base::BindBlock(^{
211 [weakDelegate loadReaderModeHTML:base::SysUTF8ToNSString(html_non_ref)
212 forURL:url_non_ref];
213 }));
214
215 infobars::InfoBarManager* infobar_manager =
216 InfoBarManagerImpl::FromWebState(_webState);
217
218 std::unique_ptr<infobars::InfoBar> infobar =
219 infobar_manager->CreateConfirmInfoBar(std::move(infoBarDelegate));
220 if (infobar_)
221 infobar_ = infobar_manager->ReplaceInfoBar(infobar_, std::move(infobar));
222 else
223 infobar_ = infobar_manager->AddInfoBar(std::move(infobar));
224 }
225
226 - (void)removeInfoBar {
227 DCHECK(_webState);
228 if (infobar_) {
229 infobars::InfoBarManager* infobar_manager =
230 InfoBarManagerImpl::FromWebState(_webState);
231 infobar_manager->RemoveInfoBar(infobar_);
232 infobar_ = nullptr;
233 }
234 }
235
236 #pragma mark - public methods.
237
238 - (void)switchToReaderMode {
239 UIView* superview = [self.delegate superviewForReaderModePanel];
240 if ([superview viewWithTag:kReaderModeViewTag])
241 return; // There is already a reader mode waiting view visible.
242
243 [self removeInfoBar];
244
245 // Get the view.
246 ReaderModeView* readerView = [self readerModeViewWithFrame:superview.bounds];
247 readerView.tag = kReaderModeViewTag;
248 [superview addSubview:readerView];
249
250 // Animate the view in. First the view is animated in (via transparency) and
251 // the the animation on the view itself is started.
252 readerView.alpha = 0.0;
253
254 [UIView animateWithDuration:kReaderModeAnimationDuration
255 delay:0.0
256 options:UIViewAnimationOptionCurveEaseIn
257 animations:^{
258 readerView.alpha = 1.0;
259 }
260 completion:^(BOOL finished) {
261 if (finished)
262 [readerView start]; // Starts the waiting animation on the view.
263 }];
264 }
265
266 #pragma mark - ReaderModeViewDelegate.
267
268 - (void)exitReaderMode {
269 UIView* superview = [self.delegate superviewForReaderModePanel];
270 if (![superview viewWithTag:kReaderModeViewTag]) {
271 DCHECK(_viewer);
272 return;
273 }
274
275 ReaderModeView* readerView =
276 static_cast<ReaderModeView*>([superview viewWithTag:kReaderModeViewTag]);
277 if (!readerView)
278 return;
279
280 // First stop the view waiting animation (if any) and then remove the view.
281 [readerView stopWaitingWithCompletion:^{
282 [UIView animateWithDuration:kReaderModeAnimationDuration
283 delay:0.0
284 options:UIViewAnimationOptionCurveEaseIn
285 animations:^{
286 readerView.alpha = 0.0;
287 }
288 completion:^(BOOL finished) {
289 [readerView removeFromSuperview];
290 }];
291 }];
292 }
293
294 #pragma mark - ReaderModeCheckerObserverBridgeProtocol
295
296 - (void)pageIsDistillable {
297 _viewer = [self startDistillation];
298 }
299
300 #pragma mark - InfoBarManagerObserverBridgeProtocol.
301
302 - (void)infoBarRemoved:(infobars::InfoBar*)infobar {
303 if (infobar == infobar_) {
304 _viewer.reset();
305 infobar_ = nullptr;
306 }
307 }
308
309 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698