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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/reader_mode/reader_mode_controller.mm
diff --git a/ios/chrome/browser/ui/reader_mode/reader_mode_controller.mm b/ios/chrome/browser/ui/reader_mode/reader_mode_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..f04917f4ca09773eacf1ab08739aa0b30269fae7
--- /dev/null
+++ b/ios/chrome/browser/ui/reader_mode/reader_mode_controller.mm
@@ -0,0 +1,309 @@
+// Copyright 2015 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 "ios/chrome/browser/ui/reader_mode/reader_mode_controller.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/ios/weak_nsobject.h"
+#include "base/mac/bind_objc_block.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobar_manager.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/dom_distiller/distiller_viewer.h"
+#include "ios/chrome/browser/dom_distiller/dom_distiller_service_factory.h"
+#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
+#import "ios/chrome/browser/ui/reader_mode/reader_mode_checker.h"
+#import "ios/chrome/browser/ui/reader_mode/reader_mode_infobar_delegate.h"
+#import "ios/chrome/browser/ui/reader_mode/reader_mode_view.h"
+#include "ios/web/public/browser_state.h"
+#include "ios/web/public/web_state/web_state.h"
+
+@protocol ReaderModeCheckerObserverBridgeProtocol
+- (void)pageIsDistillable;
+@end
+
+@protocol InfoBarManagerObserverBridgeProtocol
+- (void)infoBarRemoved:(infobars::InfoBar*)infobar;
+@end
+
+namespace {
+// Used to find the ReaderModeView in the view hierarchy.
+const NSInteger kReaderModeViewTag = 42;
+const CGFloat kReaderModeAnimationDuration = .5;
+
+class ReaderModeCheckerObserverBridge : ReaderModeCheckerObserver {
+ public:
+ ReaderModeCheckerObserverBridge(
+ ReaderModeChecker* readerModeChecker,
+ id<ReaderModeCheckerObserverBridgeProtocol> observer)
+ : ReaderModeCheckerObserver(readerModeChecker), observer_(observer) {
+ DCHECK(observer);
+ };
+
+ void PageIsDistillable() override { [observer_ pageIsDistillable]; };
+
+ private:
+ id<ReaderModeCheckerObserverBridgeProtocol> observer_;
+};
+
+class InfoBarManagerObserverBridge : infobars::InfoBarManager::Observer {
+ public:
+ InfoBarManagerObserverBridge(
+ infobars::InfoBarManager* infoBarManager,
+ id<InfoBarManagerObserverBridgeProtocol> observer)
+ : infobars::InfoBarManager::Observer(),
+ manager_(infoBarManager),
+ observer_(observer) {
+ DCHECK(infoBarManager);
+ DCHECK(observer);
+ manager_->AddObserver(this);
+ };
+
+ ~InfoBarManagerObserverBridge() override {
+ if (manager_)
+ manager_->RemoveObserver(this);
+ }
+
+ void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override {
+ [observer_ infoBarRemoved:infobar];
+ }
+
+ void OnManagerShuttingDown(infobars::InfoBarManager* manager) override {
+ manager_->RemoveObserver(this);
+ manager_ = nullptr;
+ }
+
+ private:
+ infobars::InfoBarManager* manager_;
+ id<InfoBarManagerObserverBridgeProtocol> observer_;
+};
+} // namespace
+
+@interface ReaderModeController ()<ReaderModeViewDelegate,
+ ReaderModeCheckerObserverBridgeProtocol,
+ InfoBarManagerObserverBridgeProtocol> {
+ std::unique_ptr<ReaderModeChecker> _checker;
+ std::unique_ptr<ReaderModeCheckerObserverBridge> _checkerBridge;
+ std::unique_ptr<InfoBarManagerObserverBridge> _infoBarBridge;
+ std::unique_ptr<dom_distiller::DistillerViewer> _viewer;
+ // The currently displayed infobar.
+ infobars::InfoBar* infobar_;
+ web::WebState* _webState;
+}
+@property(readonly, nonatomic) id<ReaderModeControllerDelegate> delegate;
+
+// Triggers a distillation and returns a DistillerViewer to keep as a handle to
+// the running distillation.
+- (std::unique_ptr<dom_distiller::DistillerViewer>)startDistillation
+ WARN_UNUSED_RESULT;
+- (void)distillationFinished:(const std::string&)html forURL:(const GURL&)url;
+
+// Returns a ReaderModeView that presents a waiting UI while the distillation
+// is taking place. Releasing this view will stop the distillation in progress.
+- (ReaderModeView*)readerModeViewWithFrame:(CGRect)frame;
+
+- (void)showInfoBar:(const std::string&)html forURL:(const GURL&)url;
+- (void)removeInfoBar;
+
+@end
+
+@implementation ReaderModeController
+@synthesize delegate = _delegate;
+
+- (instancetype)initWithWebState:(web::WebState*)webState
+ delegate:(id<ReaderModeControllerDelegate>)delegate {
+ DCHECK(webState);
+ self = [super init];
+ if (self) {
+ _webState = webState;
+ _checker = base::MakeUnique<ReaderModeChecker>(_webState);
+ _delegate = delegate;
+ _checkerBridge =
+ base::MakeUnique<ReaderModeCheckerObserverBridge>(_checker.get(), self);
+ infobars::InfoBarManager* infobar_manager =
+ InfoBarManagerImpl::FromWebState(_webState);
+ _infoBarBridge =
+ base::MakeUnique<InfoBarManagerObserverBridge>(infobar_manager, self);
+ }
+ return self;
+}
+
+- (instancetype)init {
+ NOTREACHED();
+ return nil;
+}
+
+- (void)dealloc {
+ if (_webState)
+ [self detachFromWebState];
+ [super dealloc];
+}
+
+- (void)detachFromWebState {
+ [self removeInfoBar];
+ _webState = nullptr;
+}
+
+// Property accessor.
+- (ReaderModeChecker*)checker {
+ return _checker.get();
+}
+
+#pragma mark - Private methods.
+#pragma mark distillation
+
+- (std::unique_ptr<dom_distiller::DistillerViewer>)startDistillation {
+ DCHECK(_webState);
+ base::WeakNSObject<ReaderModeController> weakSelf(self);
+ GURL pageURL = _webState->GetLastCommittedURL();
+ ios::ChromeBrowserState* browserState =
+ ios::ChromeBrowserState::FromBrowserState(_webState->GetBrowserState());
+ return base::MakeUnique<dom_distiller::DistillerViewer>(
+ dom_distiller::DomDistillerServiceFactory::GetForBrowserState(
+ browserState),
+ browserState->GetPrefs(), pageURL,
+ base::BindBlock(^(
+ const GURL& pageURL, const std::string& html,
+ const std::vector<dom_distiller::DistillerViewer::ImageInfo>& images,
+ const std::string& title) {
+ [weakSelf distillationFinished:html forURL:pageURL];
+ }));
+}
+
+- (void)distillationFinished:(const std::string&)html forURL:(const GURL&)url {
+ UIView* superview = [self.delegate superviewForReaderModePanel];
+ DCHECK(_viewer || [superview viewWithTag:kReaderModeViewTag]);
+ if ([superview viewWithTag:kReaderModeViewTag]) {
+ [self.delegate loadReaderModeHTML:base::SysUTF8ToNSString(html) forURL:url];
+ } else if (_viewer) {
+ [self showInfoBar:html forURL:url];
+ }
+}
+
+#pragma mark view creation
+
+- (ReaderModeView*)readerModeViewWithFrame:(CGRect)frame {
+ DCHECK(_checker->CanSwitchToReaderMode());
+ ReaderModeView* view =
+ [[[ReaderModeView alloc] initWithFrame:frame delegate:self] autorelease];
+ [view assignDistillerViewer:[self startDistillation]];
+ return view;
+}
+
+#pragma mark infobar.
+
+- (void)showInfoBar:(const std::string&)html forURL:(const GURL&)url {
+ DCHECK(_webState);
+ base::WeakNSProtocol<id<ReaderModeControllerDelegate>> weakDelegate(
+ self.delegate);
+
+ // Non reference version of the variables needed.
+ const std::string html_non_ref(html);
+ const GURL url_non_ref(url);
+ auto infoBarDelegate =
+ base::MakeUnique<ReaderModeInfoBarDelegate>(base::BindBlock(^{
+ [weakDelegate loadReaderModeHTML:base::SysUTF8ToNSString(html_non_ref)
+ forURL:url_non_ref];
+ }));
+
+ infobars::InfoBarManager* infobar_manager =
+ InfoBarManagerImpl::FromWebState(_webState);
+
+ std::unique_ptr<infobars::InfoBar> infobar =
+ infobar_manager->CreateConfirmInfoBar(std::move(infoBarDelegate));
+ if (infobar_)
+ infobar_ = infobar_manager->ReplaceInfoBar(infobar_, std::move(infobar));
+ else
+ infobar_ = infobar_manager->AddInfoBar(std::move(infobar));
+}
+
+- (void)removeInfoBar {
+ DCHECK(_webState);
+ if (infobar_) {
+ infobars::InfoBarManager* infobar_manager =
+ InfoBarManagerImpl::FromWebState(_webState);
+ infobar_manager->RemoveInfoBar(infobar_);
+ infobar_ = nullptr;
+ }
+}
+
+#pragma mark - public methods.
+
+- (void)switchToReaderMode {
+ UIView* superview = [self.delegate superviewForReaderModePanel];
+ if ([superview viewWithTag:kReaderModeViewTag])
+ return; // There is already a reader mode waiting view visible.
+
+ [self removeInfoBar];
+
+ // Get the view.
+ ReaderModeView* readerView = [self readerModeViewWithFrame:superview.bounds];
+ readerView.tag = kReaderModeViewTag;
+ [superview addSubview:readerView];
+
+ // Animate the view in. First the view is animated in (via transparency) and
+ // the the animation on the view itself is started.
+ readerView.alpha = 0.0;
+
+ [UIView animateWithDuration:kReaderModeAnimationDuration
+ delay:0.0
+ options:UIViewAnimationOptionCurveEaseIn
+ animations:^{
+ readerView.alpha = 1.0;
+ }
+ completion:^(BOOL finished) {
+ if (finished)
+ [readerView start]; // Starts the waiting animation on the view.
+ }];
+}
+
+#pragma mark - ReaderModeViewDelegate.
+
+- (void)exitReaderMode {
+ UIView* superview = [self.delegate superviewForReaderModePanel];
+ if (![superview viewWithTag:kReaderModeViewTag]) {
+ DCHECK(_viewer);
+ return;
+ }
+
+ ReaderModeView* readerView =
+ static_cast<ReaderModeView*>([superview viewWithTag:kReaderModeViewTag]);
+ if (!readerView)
+ return;
+
+ // First stop the view waiting animation (if any) and then remove the view.
+ [readerView stopWaitingWithCompletion:^{
+ [UIView animateWithDuration:kReaderModeAnimationDuration
+ delay:0.0
+ options:UIViewAnimationOptionCurveEaseIn
+ animations:^{
+ readerView.alpha = 0.0;
+ }
+ completion:^(BOOL finished) {
+ [readerView removeFromSuperview];
+ }];
+ }];
+}
+
+#pragma mark - ReaderModeCheckerObserverBridgeProtocol
+
+- (void)pageIsDistillable {
+ _viewer = [self startDistillation];
+}
+
+#pragma mark - InfoBarManagerObserverBridgeProtocol.
+
+- (void)infoBarRemoved:(infobars::InfoBar*)infobar {
+ if (infobar == infobar_) {
+ _viewer.reset();
+ infobar_ = nullptr;
+ }
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698