| Index: ios/chrome/browser/tabs/tab.mm
|
| diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
|
| index 6b9e2b968fc28dea2370a6bf17034ba833727568..fe6b85467c6750529995709bcb6de808aa801ee6 100644
|
| --- a/ios/chrome/browser/tabs/tab.mm
|
| +++ b/ios/chrome/browser/tabs/tab.mm
|
| @@ -12,11 +12,13 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/ios/block_types.h"
|
| +#import "base/ios/weak_nsobject.h"
|
| #include "base/json/string_escape.h"
|
| #include "base/logging.h"
|
| #include "base/mac/bind_objc_block.h"
|
| #include "base/mac/foundation_util.h"
|
| -#include "base/memory/ptr_util.h"
|
| +#include "base/mac/objc_property_releaser.h"
|
| +#include "base/mac/scoped_nsobject.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/metrics/user_metrics.h"
|
| #include "base/metrics/user_metrics_action.h"
|
| @@ -136,9 +138,9 @@
|
| #include "ui/base/page_transition_types.h"
|
| #include "url/origin.h"
|
|
|
| -#if !defined(__has_feature) || !__has_feature(objc_arc)
|
| -#error "This file requires ARC support."
|
| -#endif
|
| +using base::UserMetricsAction;
|
| +using web::NavigationManagerImpl;
|
| +using net::RequestTracker;
|
|
|
| NSString* const kTabUrlStartedLoadingNotificationForCrashReporting =
|
| @"kTabUrlStartedLoadingNotificationForCrashReporting";
|
| @@ -196,7 +198,162 @@
|
| return (ui::PageTransition::PAGE_TRANSITION_IS_REDIRECT_MASK &
|
| item->GetTransitionType()) == 0;
|
| }
|
| -
|
| +} // namespace
|
| +
|
| +@interface Tab ()<CRWWebStateObserver,
|
| + CRWWebControllerObserver,
|
| + FindInPageControllerDelegate,
|
| + ReaderModeControllerDelegate> {
|
| + TabModel* parentTabModel_; // weak
|
| + ios::ChromeBrowserState* browserState_; // weak
|
| +
|
| + base::scoped_nsobject<OpenInController> openInController_;
|
| + base::WeakNSProtocol<id<PassKitDialogProvider>> passKitDialogProvider_;
|
| +
|
| + // Whether or not this tab is currently being displayed.
|
| + BOOL visible_;
|
| +
|
| + // Holds entries that need to be added to the history DB. Prerender tabs do
|
| + // not write navigation data to the history DB. Instead, they cache history
|
| + // data in this vector and add it to the DB when the prerender status is
|
| + // removed (when the Tab is swapped in as a real Tab).
|
| + std::vector<history::HistoryAddPageArgs> addPageVector_;
|
| +
|
| + // YES if this Tab is being prerendered.
|
| + BOOL isPrerenderTab_;
|
| +
|
| + // YES if this Tab was initiated from a voice search.
|
| + BOOL isVoiceSearchResultsTab_;
|
| +
|
| + // YES if the Tab needs to be reloaded after the app becomes active.
|
| + BOOL requireReloadAfterBecomingActive_;
|
| +
|
| + // Last visited timestamp.
|
| + double lastVisitedTimestamp_;
|
| +
|
| + base::mac::ObjCPropertyReleaser propertyReleaser_Tab_;
|
| +
|
| + id<TabDelegate> delegate_; // weak
|
| + base::WeakNSProtocol<id<TabDialogDelegate>> dialogDelegate_;
|
| + base::WeakNSProtocol<id<SnapshotOverlayProvider>> snapshotOverlayProvider_;
|
| +
|
| + // Delegate used for snapshotting geometry.
|
| + id<TabSnapshottingDelegate> tabSnapshottingDelegate_; // weak
|
| +
|
| + // The Full Screen Controller responsible for hiding/showing the toolbar.
|
| + base::scoped_nsobject<FullScreenController> fullScreenController_;
|
| +
|
| + // The delegate responsible for headers over the tab.
|
| + id<TabHeadersDelegate> tabHeadersDelegate_; // weak
|
| +
|
| + base::WeakNSProtocol<id<FullScreenControllerDelegate>>
|
| + fullScreenControllerDelegate_;
|
| +
|
| + // The Overscroll controller responsible for displaying the
|
| + // overscrollActionsView above the toolbar.
|
| + base::scoped_nsobject<OverscrollActionsController>
|
| + overscrollActionsController_;
|
| + base::WeakNSProtocol<id<OverscrollActionsControllerDelegate>>
|
| + overscrollActionsControllerDelegate_;
|
| +
|
| + base::scoped_nsobject<NSString> tabId_;
|
| +
|
| + // Lightweight object dealing with various different UI behaviours when
|
| + // opening a URL in an external application.
|
| + base::scoped_nsobject<ExternalAppLauncher> externalAppLauncher_;
|
| +
|
| + // Handles suggestions for form entry.
|
| + base::scoped_nsobject<FormSuggestionController> suggestionController_;
|
| +
|
| + // Manages the input accessory view during form input.
|
| + base::scoped_nsobject<FormInputAccessoryViewController>
|
| + inputAccessoryViewController_;
|
| +
|
| + // TODO(crbug.com/661665): move the WebContentsObservers into their own
|
| + // container.
|
| + // Handles saving and autofill of passwords.
|
| + base::scoped_nsobject<PasswordController> passwordController_;
|
| +
|
| + // Handles autofill.
|
| + base::scoped_nsobject<AutofillController> autofillController_;
|
| +
|
| + // Handles caching and retrieving of snapshots.
|
| + base::scoped_nsobject<SnapshotManager> snapshotManager_;
|
| +
|
| + // Handles retrieving, generating and updating snapshots of CRWWebController's
|
| + // web page.
|
| + base::scoped_nsobject<WebControllerSnapshotHelper>
|
| + webControllerSnapshotHelper_;
|
| +
|
| + // Handles support for window.print JavaScript calls.
|
| + std::unique_ptr<PrintObserver> printObserver_;
|
| +
|
| + // AutoReloadBridge for this tab.
|
| + base::scoped_nsobject<AutoReloadBridge> autoReloadBridge_;
|
| +
|
| + // WebStateImpl for this tab.
|
| + web::WebStateImpl* webStateImpl_;
|
| +
|
| + // Allows Tab to conform CRWWebStateDelegate protocol.
|
| + std::unique_ptr<web::WebStateObserverBridge> webStateObserver_;
|
| +
|
| + // Context used by history to scope the lifetime of navigation entry
|
| + // references to Tab.
|
| + std::unique_ptr<TabHistoryContext> tabHistoryContext_;
|
| +
|
| + // The controller for everything related to reader mode.
|
| + base::scoped_nsobject<ReaderModeController> readerModeController_;
|
| +
|
| + // C++ bridge that receives notifications from the FaviconDriver.
|
| + std::unique_ptr<FaviconDriverObserverBridge> faviconDriverObserverBridge_;
|
| +
|
| + // U2F call controller object.
|
| + base::scoped_nsobject<U2FController> U2FController_;
|
| +
|
| + // C++ observer used to trigger snapshots after the removal of InfoBars.
|
| + std::unique_ptr<TabInfoBarObserver> tabInfoBarObserver_;
|
| +}
|
| +
|
| +// Returns the tab's reader mode controller. May contain nil if the feature is
|
| +// disabled.
|
| +@property(nonatomic, readonly) ReaderModeController* readerModeController;
|
| +
|
| +// Returns a list of FormSuggestionProviders to be queried for suggestions
|
| +// in order of priority.
|
| +- (NSArray*)suggestionProviders;
|
| +
|
| +// Returns a list of FormInputAccessoryViewProviders to be queried for an input
|
| +// accessory view in order of priority.
|
| +- (NSArray*)accessoryViewProviders;
|
| +
|
| +// Sets the favicon on the current NavigationItem.
|
| +- (void)setFavicon:(const gfx::Image*)image;
|
| +
|
| +// Saves the current title to the history database.
|
| +- (void)saveTitleToHistoryDB;
|
| +
|
| +// Adds the current session entry to this history database.
|
| +- (void)addCurrentEntryToHistoryDB;
|
| +
|
| +// Adds any cached entries from |addPageVector_| to the history DB.
|
| +- (void)commitCachedEntriesToHistoryDB;
|
| +
|
| +// Returns the OpenInController for this tab.
|
| +- (OpenInController*)openInController;
|
| +
|
| +// Handles exportable files if possible.
|
| +- (void)handleExportableFile:(net::HttpResponseHeaders*)headers;
|
| +
|
| +// Called after the session history is replaced, useful for updating members
|
| +// with new sessionID.
|
| +- (void)didReplaceSessionHistory;
|
| +
|
| +// Called when the UIApplication's state becomes active.
|
| +- (void)applicationDidBecomeActive;
|
| +
|
| +@end
|
| +
|
| +namespace {
|
| // TabHistoryContext is used by history to scope the lifetime of navigation
|
| // entry references to Tab.
|
| class TabHistoryContext : public history::Context {
|
| @@ -207,131 +364,7 @@
|
| private:
|
| DISALLOW_COPY_AND_ASSIGN(TabHistoryContext);
|
| };
|
| -} // namespace
|
| -
|
| -@interface Tab ()<CRWWebStateObserver,
|
| - CRWWebControllerObserver,
|
| - FindInPageControllerDelegate,
|
| - ReaderModeControllerDelegate> {
|
| - __weak TabModel* parentTabModel_;
|
| - ios::ChromeBrowserState* browserState_;
|
| -
|
| - OpenInController* openInController_;
|
| -
|
| - // Whether or not this tab is currently being displayed.
|
| - BOOL visible_;
|
| -
|
| - // Holds entries that need to be added to the history DB. Prerender tabs do
|
| - // not write navigation data to the history DB. Instead, they cache history
|
| - // data in this vector and add it to the DB when the prerender status is
|
| - // removed (when the Tab is swapped in as a real Tab).
|
| - std::vector<history::HistoryAddPageArgs> addPageVector_;
|
| -
|
| - // YES if this Tab is being prerendered.
|
| - BOOL isPrerenderTab_;
|
| -
|
| - // YES if this Tab was initiated from a voice search.
|
| - BOOL isVoiceSearchResultsTab_;
|
| -
|
| - // YES if the Tab needs to be reloaded after the app becomes active.
|
| - BOOL requireReloadAfterBecomingActive_;
|
| -
|
| - // Last visited timestamp.
|
| - double lastVisitedTimestamp_;
|
| -
|
| - // The Full Screen Controller responsible for hiding/showing the toolbar.
|
| - FullScreenController* fullScreenController_;
|
| -
|
| - // The Overscroll controller responsible for displaying the
|
| - // overscrollActionsView above the toolbar.
|
| - OverscrollActionsController* overscrollActionsController_;
|
| -
|
| - // Lightweight object dealing with various different UI behaviours when
|
| - // opening a URL in an external application.
|
| - ExternalAppLauncher* externalAppLauncher_;
|
| -
|
| - // Handles suggestions for form entry.
|
| - FormSuggestionController* suggestionController_;
|
| -
|
| - // Manages the input accessory view during form input.
|
| - FormInputAccessoryViewController* inputAccessoryViewController_;
|
| -
|
| - // Handles autofill.
|
| - AutofillController* autofillController_;
|
| -
|
| - // Handles caching and retrieving of snapshots.
|
| - SnapshotManager* snapshotManager_;
|
| -
|
| - // Handles retrieving, generating and updating snapshots of CRWWebController's
|
| - // web page.
|
| - WebControllerSnapshotHelper* webControllerSnapshotHelper_;
|
| -
|
| - // Handles support for window.print JavaScript calls.
|
| - std::unique_ptr<PrintObserver> printObserver_;
|
| -
|
| - // AutoReloadBridge for this tab.
|
| - AutoReloadBridge* autoReloadBridge_;
|
| -
|
| - // WebStateImpl for this tab.
|
| - web::WebStateImpl* webStateImpl_;
|
| -
|
| - // Allows Tab to conform CRWWebStateDelegate protocol.
|
| - std::unique_ptr<web::WebStateObserverBridge> webStateObserver_;
|
| -
|
| - // Context used by history to scope the lifetime of navigation entry
|
| - // references to Tab.
|
| - TabHistoryContext tabHistoryContext_;
|
| -
|
| - // C++ bridge that receives notifications from the FaviconDriver.
|
| - std::unique_ptr<FaviconDriverObserverBridge> faviconDriverObserverBridge_;
|
| -
|
| - // U2F call controller object.
|
| - U2FController* U2FController_;
|
| -
|
| - // C++ observer used to trigger snapshots after the removal of InfoBars.
|
| - std::unique_ptr<TabInfoBarObserver> tabInfoBarObserver_;
|
| -}
|
| -
|
| -// Returns the tab's reader mode controller. May contain nil if the feature is
|
| -// disabled.
|
| -@property(nonatomic, readonly) ReaderModeController* readerModeController;
|
| -
|
| -// Returns a list of FormSuggestionProviders to be queried for suggestions
|
| -// in order of priority.
|
| -- (NSArray*)suggestionProviders;
|
| -
|
| -// Returns a list of FormInputAccessoryViewProviders to be queried for an input
|
| -// accessory view in order of priority.
|
| -- (NSArray*)accessoryViewProviders;
|
| -
|
| -// Sets the favicon on the current NavigationItem.
|
| -- (void)setFavicon:(const gfx::Image*)image;
|
| -
|
| -// Saves the current title to the history database.
|
| -- (void)saveTitleToHistoryDB;
|
| -
|
| -// Adds the current session entry to this history database.
|
| -- (void)addCurrentEntryToHistoryDB;
|
| -
|
| -// Adds any cached entries from |addPageVector_| to the history DB.
|
| -- (void)commitCachedEntriesToHistoryDB;
|
| -
|
| -// Returns the OpenInController for this tab.
|
| -- (OpenInController*)openInController;
|
| -
|
| -// Handles exportable files if possible.
|
| -- (void)handleExportableFile:(net::HttpResponseHeaders*)headers;
|
| -
|
| -// Called after the session history is replaced, useful for updating members
|
| -// with new sessionID.
|
| -- (void)didReplaceSessionHistory;
|
| -
|
| -// Called when the UIApplication's state becomes active.
|
| -- (void)applicationDidBecomeActive;
|
| -
|
| -@end
|
| -
|
| -namespace {
|
| +
|
| class FaviconDriverObserverBridge : public favicon::FaviconDriverObserver {
|
| public:
|
| FaviconDriverObserverBridge(Tab* owner,
|
| @@ -346,7 +379,7 @@
|
| const gfx::Image& image) override;
|
|
|
| private:
|
| - __weak Tab* owner_;
|
| + Tab* owner_; // Owns this instance.
|
| ScopedObserver<favicon::FaviconDriver, favicon::FaviconDriverObserver>
|
| scoped_observer_;
|
| DISALLOW_COPY_AND_ASSIGN(FaviconDriverObserverBridge);
|
| @@ -382,7 +415,7 @@
|
| infobars::InfoBar* new_infobar) override;
|
|
|
| private:
|
| - __weak Tab* owner_;
|
| + Tab* owner_; // Owns this instance;
|
| ScopedObserver<infobars::InfoBarManager, TabInfoBarObserver> scoped_observer_;
|
| DISALLOW_COPY_AND_ASSIGN(TabInfoBarObserver);
|
| };
|
| @@ -427,33 +460,27 @@
|
| @implementation Tab
|
|
|
| @synthesize browserState = browserState_;
|
| -@synthesize tabId = tabId_;
|
| @synthesize useGreyImageCache = useGreyImageCache_;
|
| @synthesize isPrerenderTab = isPrerenderTab_;
|
| @synthesize isLinkLoadingPrerenderTab = isLinkLoadingPrerenderTab_;
|
| @synthesize isVoiceSearchResultsTab = isVoiceSearchResultsTab_;
|
| -@synthesize passwordController = passwordController_;
|
| -@synthesize overscrollActionsController = overscrollActionsController_;
|
| -@synthesize readerModeController = readerModeController_;
|
| -@synthesize overscrollActionsControllerDelegate =
|
| - overscrollActionsControllerDelegate_;
|
| -@synthesize passKitDialogProvider = passKitDialogProvider_;
|
| @synthesize delegate = delegate_;
|
| -@synthesize dialogDelegate = dialogDelegate_;
|
| -@synthesize snapshotOverlayProvider = snapshotOverlayProvider_;
|
| @synthesize tabSnapshottingDelegate = tabSnapshottingDelegate_;
|
| @synthesize tabHeadersDelegate = tabHeadersDelegate_;
|
| -@synthesize fullScreenControllerDelegate = fullScreenControllerDelegate_;
|
|
|
| - (instancetype)initWithWebState:(web::WebState*)webState {
|
| DCHECK(webState);
|
| self = [super init];
|
| if (self) {
|
| + propertyReleaser_Tab_.Init(self, [Tab class]);
|
| +
|
| // TODO(crbug.com/620465): Tab should only use public API of WebState.
|
| // Remove this cast once this is the case.
|
| webStateImpl_ = static_cast<web::WebStateImpl*>(webState);
|
| browserState_ =
|
| ios::ChromeBrowserState::FromBrowserState(webState->GetBrowserState());
|
| +
|
| + tabHistoryContext_ = base::MakeUnique<TabHistoryContext>();
|
| webStateObserver_ =
|
| base::MakeUnique<web::WebStateObserverBridge>(webState, self);
|
|
|
| @@ -461,10 +488,10 @@
|
| [[self webController] addObserver:self];
|
| [[self webController] setDelegate:self];
|
|
|
| - snapshotManager_ = [[SnapshotManager alloc] init];
|
| - webControllerSnapshotHelper_ = [[WebControllerSnapshotHelper alloc]
|
| + snapshotManager_.reset([[SnapshotManager alloc] init]);
|
| + webControllerSnapshotHelper_.reset([[WebControllerSnapshotHelper alloc]
|
| initWithSnapshotManager:snapshotManager_
|
| - tab:self];
|
| + tab:self]);
|
|
|
| [[NSNotificationCenter defaultCenter]
|
| addObserver:self
|
| @@ -476,39 +503,40 @@
|
| }
|
|
|
| - (void)attachTabHelpers {
|
| - tabInfoBarObserver_ = base::MakeUnique<TabInfoBarObserver>(self);
|
| + tabInfoBarObserver_.reset(new TabInfoBarObserver(self));
|
| tabInfoBarObserver_->SetShouldObserveInfoBarManager(true);
|
|
|
| - if (experimental_flags::IsAutoReloadEnabled())
|
| - autoReloadBridge_ = [[AutoReloadBridge alloc] initWithTab:self];
|
| + if (experimental_flags::IsAutoReloadEnabled()) {
|
| + autoReloadBridge_.reset([[AutoReloadBridge alloc] initWithTab:self]);
|
| + }
|
| printObserver_ = base::MakeUnique<PrintObserver>(self.webState);
|
|
|
| - id<PasswordsUiDelegate> passwordsUiDelegate =
|
| - [[PasswordsUiDelegateImpl alloc] init];
|
| - passwordController_ =
|
| - [[PasswordController alloc] initWithWebState:self.webState
|
| - passwordsUiDelegate:passwordsUiDelegate];
|
| + base::scoped_nsprotocol<id<PasswordsUiDelegate>> passwordsUiDelegate(
|
| + [[PasswordsUiDelegateImpl alloc] init]);
|
| + passwordController_.reset([[PasswordController alloc]
|
| + initWithWebState:self.webState
|
| + passwordsUiDelegate:passwordsUiDelegate]);
|
| password_manager::PasswordGenerationManager* passwordGenerationManager =
|
| [passwordController_ passwordGenerationManager];
|
| - autofillController_ =
|
| - [[AutofillController alloc] initWithBrowserState:browserState_
|
| - passwordGenerationManager:passwordGenerationManager
|
| - webState:self.webState];
|
| - suggestionController_ = [[FormSuggestionController alloc]
|
| + autofillController_.reset([[AutofillController alloc]
|
| + initWithBrowserState:browserState_
|
| + passwordGenerationManager:passwordGenerationManager
|
| + webState:self.webState]);
|
| + suggestionController_.reset([[FormSuggestionController alloc]
|
| initWithWebState:self.webState
|
| - providers:[self suggestionProviders]];
|
| - inputAccessoryViewController_ = [[FormInputAccessoryViewController alloc]
|
| + providers:[self suggestionProviders]]);
|
| + inputAccessoryViewController_.reset([[FormInputAccessoryViewController alloc]
|
| initWithWebState:self.webState
|
| - providers:[self accessoryViewProviders]];
|
| + providers:[self accessoryViewProviders]]);
|
|
|
| [self setShouldObserveFaviconChanges:YES];
|
|
|
| // Create the ReaderModeController immediately so it can register for
|
| // WebState changes.
|
| if (experimental_flags::IsReaderModeEnabled()) {
|
| - readerModeController_ =
|
| - [[ReaderModeController alloc] initWithWebState:self.webState
|
| - delegate:self];
|
| + readerModeController_.reset([[ReaderModeController alloc]
|
| + initWithWebState:self.webState
|
| + delegate:self]);
|
| }
|
| }
|
|
|
| @@ -560,11 +588,19 @@
|
| return [self.webController loadPhase] == web::PAGE_LOADED;
|
| }
|
|
|
| +- (void)setDialogDelegate:(id<TabDialogDelegate>)dialogDelegate {
|
| + dialogDelegate_.reset(dialogDelegate);
|
| +}
|
| +
|
| - (void)setIsVoiceSearchResultsTab:(BOOL)isVoiceSearchResultsTab {
|
| // There is intentionally no equality check in this setter, as we want the
|
| // notificaiton to be sent regardless of whether the value has changed.
|
| isVoiceSearchResultsTab_ = isVoiceSearchResultsTab;
|
| [parentTabModel_ notifyTabChanged:self];
|
| +}
|
| +
|
| +- (PasswordController*)passwordController {
|
| + return passwordController_.get();
|
| }
|
|
|
| - (void)retrieveSnapshot:(void (^)(UIImage*))callback {
|
| @@ -619,7 +655,7 @@
|
|
|
| - (NSString*)tabId {
|
| if (tabId_)
|
| - return tabId_;
|
| + return tabId_.get();
|
|
|
| DCHECK(self.webState);
|
| web::SerializableUserDataManager* userDataManager =
|
| @@ -632,8 +668,8 @@
|
| userDataManager->AddSerializableData(tabId, kTabIDKey);
|
| }
|
|
|
| - tabId_ = [tabId copy];
|
| - return tabId_;
|
| + tabId_.reset([tabId copy]);
|
| + return tabId_.get();
|
| }
|
|
|
| - (web::WebState*)webState {
|
| @@ -647,8 +683,9 @@
|
|
|
| favicon::FaviconDriver* faviconDriver =
|
| favicon::WebFaviconDriver::FromWebState(self.webState);
|
| - if (faviconDriver)
|
| + if (faviconDriver) {
|
| faviconDriver->FetchFavicon(url);
|
| + }
|
| }
|
|
|
| - (void)setFavicon:(const gfx::Image*)image {
|
| @@ -675,8 +712,9 @@
|
|
|
| - (UIView*)view {
|
| // Record reload of previously-evicted tab.
|
| - if (![self.webController isViewAlive] && [parentTabModel_ tabUsageRecorder])
|
| + if (![self.webController isViewAlive] && [parentTabModel_ tabUsageRecorder]) {
|
| [parentTabModel_ tabUsageRecorder]->RecordPageLoadStart(self);
|
| + }
|
| return self.webState ? self.webState->GetView() : nil;
|
| }
|
|
|
| @@ -716,10 +754,10 @@
|
| if (fullScreenController_) {
|
| [fullScreenController_ invalidate];
|
| [self.webController removeObserver:fullScreenController_];
|
| - fullScreenController_ = [[FullScreenController alloc]
|
| + fullScreenController_.reset([[FullScreenController alloc]
|
| initWithDelegate:fullScreenControllerDelegate_
|
| navigationManager:self.navigationManager
|
| - sessionID:self.tabId];
|
| + sessionID:self.tabId]);
|
| [self.webController addObserver:fullScreenController_];
|
| // If the content of the page was loaded without knowledge of the
|
| // toolbar position it will be misplaced under the toolbar instead of
|
| @@ -763,18 +801,23 @@
|
| [self countMainFrameLoad];
|
| }
|
|
|
| +- (id<FullScreenControllerDelegate>)fullScreenControllerDelegate {
|
| + return fullScreenControllerDelegate_.get();
|
| +}
|
| +
|
| - (void)setFullScreenControllerDelegate:
|
| (id<FullScreenControllerDelegate>)fullScreenControllerDelegate {
|
| - if (fullScreenControllerDelegate == fullScreenControllerDelegate_)
|
| - return;
|
| + if (fullScreenControllerDelegate == fullScreenControllerDelegate_) {
|
| + return;
|
| + }
|
| // Lazily create a FullScreenController.
|
| // The check for fullScreenControllerDelegate is necessary to avoid recreating
|
| // a FullScreenController during teardown.
|
| if (!fullScreenController_ && fullScreenControllerDelegate) {
|
| - fullScreenController_ = [[FullScreenController alloc]
|
| + fullScreenController_.reset([[FullScreenController alloc]
|
| initWithDelegate:fullScreenControllerDelegate
|
| navigationManager:self.navigationManager
|
| - sessionID:self.tabId];
|
| + sessionID:self.tabId]);
|
| [self.webController addObserver:fullScreenController_];
|
| // If the content of the page was loaded without knowledge of the
|
| // toolbar position it will be misplaced under the toolbar instead of
|
| @@ -782,31 +825,41 @@
|
| // sure the content is moved to the right place.
|
| [fullScreenController_ moveContentBelowHeader];
|
| }
|
| - fullScreenControllerDelegate_ = fullScreenControllerDelegate;
|
| + fullScreenControllerDelegate_.reset(fullScreenControllerDelegate);
|
| +}
|
| +
|
| +- (OverscrollActionsController*)overscrollActionsController {
|
| + return overscrollActionsController_.get();
|
| +}
|
| +
|
| +- (id<OverscrollActionsControllerDelegate>)overscrollActionsControllerDelegate {
|
| + return overscrollActionsControllerDelegate_.get();
|
| }
|
|
|
| - (void)setOverscrollActionsControllerDelegate:
|
| (id<OverscrollActionsControllerDelegate>)
|
| overscrollActionsControllerDelegate {
|
| if (overscrollActionsControllerDelegate_ ==
|
| - overscrollActionsControllerDelegate) {
|
| - return;
|
| - }
|
| + overscrollActionsControllerDelegate)
|
| + return;
|
|
|
| // Lazily create a OverscrollActionsController.
|
| // The check for overscrollActionsControllerDelegate is necessary to avoid
|
| // recreating a OverscrollActionsController during teardown.
|
| if (!overscrollActionsController_) {
|
| - overscrollActionsController_ = [[OverscrollActionsController alloc] init];
|
| + overscrollActionsController_.reset(
|
| + [[OverscrollActionsController alloc] init]);
|
| [self.webController addObserver:overscrollActionsController_];
|
| }
|
| OverscrollStyle style = OverscrollStyle::REGULAR_PAGE_NON_INCOGNITO;
|
| - if (browserState_->IsOffTheRecord())
|
| + if (browserState_->IsOffTheRecord()) {
|
| style = OverscrollStyle::REGULAR_PAGE_INCOGNITO;
|
| + }
|
| [overscrollActionsController_ setStyle:style];
|
| [overscrollActionsController_
|
| setDelegate:overscrollActionsControllerDelegate];
|
| - overscrollActionsControllerDelegate_ = overscrollActionsControllerDelegate;
|
| + overscrollActionsControllerDelegate_.reset(
|
| + overscrollActionsControllerDelegate);
|
| }
|
|
|
| - (void)saveTitleToHistoryDB {
|
| @@ -816,9 +869,8 @@
|
| // Don't update the history if current entry has no title.
|
| NSString* title = [self title];
|
| if (![title length] ||
|
| - [title isEqualToString:l10n_util::GetNSString(IDS_DEFAULT_TAB_TITLE)]) {
|
| - return;
|
| - }
|
| + [title isEqualToString:l10n_util::GetNSString(IDS_DEFAULT_TAB_TITLE)])
|
| + return;
|
|
|
| history::HistoryService* historyService =
|
| ios::HistoryServiceFactory::GetForBrowserState(
|
| @@ -884,12 +936,12 @@
|
| referrer.url != GURL(kChromeContentSuggestionsReferrer);
|
|
|
| history::HistoryAddPageArgs args(
|
| - url, item->GetTimestamp(), &tabHistoryContext_, item->GetUniqueID(),
|
| - referrer.url, redirects, item->GetTransitionType(),
|
| + url, item->GetTimestamp(), tabHistoryContext_.get(),
|
| + item->GetUniqueID(), referrer.url, redirects, item->GetTransitionType(),
|
| history::SOURCE_BROWSED, false, consider_for_ntp_most_visited);
|
| addPageVector_.push_back(args);
|
| } else {
|
| - historyService->AddPage(url, item->GetTimestamp(), &tabHistoryContext_,
|
| + historyService->AddPage(url, item->GetTimestamp(), tabHistoryContext_.get(),
|
| item->GetUniqueID(), referrer.url, redirects,
|
| item->GetTransitionType(), history::SOURCE_BROWSED,
|
| false);
|
| @@ -937,7 +989,7 @@
|
| if (!initialNavigation && !isPrerenderTab_ &&
|
| !PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD) &&
|
| (transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK) == 0) {
|
| - base::RecordAction(base::UserMetricsAction("MobileTabClobbered"));
|
| + base::RecordAction(UserMetricsAction("MobileTabClobbered"));
|
| }
|
| if ([parentTabModel_ tabUsageRecorder])
|
| [parentTabModel_ tabUsageRecorder]->RecordPageLoadStart(self);
|
| @@ -966,8 +1018,9 @@
|
| }
|
|
|
| - (void)webWillReload {
|
| - if ([parentTabModel_ tabUsageRecorder])
|
| + if ([parentTabModel_ tabUsageRecorder]) {
|
| [parentTabModel_ tabUsageRecorder]->RecordReload(self);
|
| + }
|
| }
|
|
|
| // Halt the tab, which amounts to halting its webController.
|
| @@ -985,24 +1038,24 @@
|
| [[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
| [passwordController_ detach];
|
| - passwordController_ = nil;
|
| + passwordController_.reset();
|
| tabInfoBarObserver_.reset();
|
|
|
| faviconDriverObserverBridge_.reset();
|
| [openInController_ detachFromWebController];
|
| - openInController_ = nil;
|
| + openInController_.reset();
|
| [autofillController_ detachFromWebState];
|
| [suggestionController_ detachFromWebState];
|
| if (fullScreenController_)
|
| [self.webController removeObserver:fullScreenController_];
|
| [fullScreenController_ invalidate];
|
| - fullScreenController_ = nil;
|
| + fullScreenController_.reset();
|
| if (overscrollActionsController_)
|
| [self.webController removeObserver:overscrollActionsController_];
|
| [overscrollActionsController_ invalidate];
|
| - overscrollActionsController_ = nil;
|
| + overscrollActionsController_.reset();
|
| [readerModeController_ detachFromWebState];
|
| - readerModeController_ = nil;
|
| + readerModeController_.reset();
|
|
|
| // Invalidate any snapshot stored for this session.
|
| DCHECK(self.tabId);
|
| @@ -1031,8 +1084,8 @@
|
| favicon::WebFaviconDriver::FromWebState(self.webState);
|
| // Some MockWebContents used in tests do not support the FaviconDriver.
|
| if (faviconDriver) {
|
| - faviconDriverObserverBridge_ =
|
| - base::MakeUnique<FaviconDriverObserverBridge>(self, faviconDriver);
|
| + faviconDriverObserverBridge_.reset(
|
| + new FaviconDriverObserverBridge(self, faviconDriver));
|
| }
|
| } else {
|
| faviconDriverObserverBridge_.reset();
|
| @@ -1042,7 +1095,7 @@
|
| - (void)goBack {
|
| if (self.navigationManager) {
|
| DCHECK(self.navigationManager->CanGoBack());
|
| - base::RecordAction(base::UserMetricsAction("Back"));
|
| + base::RecordAction(UserMetricsAction("Back"));
|
| self.navigationManager->GoBack();
|
| }
|
| }
|
| @@ -1050,7 +1103,7 @@
|
| - (void)goForward {
|
| if (self.navigationManager) {
|
| DCHECK(self.navigationManager->CanGoForward());
|
| - base::RecordAction(base::UserMetricsAction("Forward"));
|
| + base::RecordAction(UserMetricsAction("Forward"));
|
| self.navigationManager->GoForward();
|
| }
|
| }
|
| @@ -1078,22 +1131,28 @@
|
| - (BOOL)openExternalURL:(const GURL&)url
|
| sourceURL:(const GURL&)sourceURL
|
| linkClicked:(BOOL)linkClicked {
|
| - if (!externalAppLauncher_)
|
| - externalAppLauncher_ = [[ExternalAppLauncher alloc] init];
|
| + if (!externalAppLauncher_.get())
|
| + externalAppLauncher_.reset([[ExternalAppLauncher alloc] init]);
|
| +
|
| + // This method may release CRWWebController which may cause a crash
|
| + // (crbug.com/393949).
|
| + [[self.webController retain] autorelease];
|
|
|
| // Make a local url copy for possible modification.
|
| GURL finalURL = url;
|
|
|
| // Check if it's a direct FIDO U2F x-callback call. If so, do not open it, to
|
| // prevent pages from spoofing requests with different origins.
|
| - if (finalURL.SchemeIs("u2f-x-callback"))
|
| + if (finalURL.SchemeIs("u2f-x-callback")) {
|
| return NO;
|
| + }
|
|
|
| // Check if it's a FIDO U2F call.
|
| if (finalURL.SchemeIs("u2f")) {
|
| // Create U2FController object lazily.
|
| - if (!U2FController_)
|
| - U2FController_ = [[U2FController alloc] init];
|
| + if (!U2FController_) {
|
| + U2FController_.reset([[U2FController alloc] init]);
|
| + }
|
|
|
| DCHECK([self navigationManager]);
|
| GURL origin =
|
| @@ -1105,8 +1164,9 @@
|
| tabURL:self.url
|
| tabID:self.tabId];
|
|
|
| - if (!finalURL.is_valid())
|
| + if (!finalURL.is_valid()) {
|
| return NO;
|
| + }
|
| }
|
|
|
| if ([externalAppLauncher_ openURL:finalURL linkClicked:linkClicked]) {
|
| @@ -1121,8 +1181,9 @@
|
| if (sourceURL.is_valid()) {
|
| ReadingListModel* model =
|
| ReadingListModelFactory::GetForBrowserState(browserState_);
|
| - if (model && model->loaded())
|
| + if (model && model->loaded()) {
|
| model->SetReadStatus(sourceURL, true);
|
| + }
|
| }
|
|
|
| return YES;
|
| @@ -1133,10 +1194,11 @@
|
| - (void)webState:(web::WebState*)webState
|
| didFinishNavigation:(web::NavigationContext*)navigation {
|
| if (navigation->IsSameDocument()) {
|
| - // Fetch the favicon for the new URL.
|
| auto* faviconDriver = favicon::WebFaviconDriver::FromWebState(webState);
|
| - if (faviconDriver)
|
| + if (faviconDriver) {
|
| + // Fetch the favicon for the new URL.
|
| faviconDriver->FetchFavicon(navigation->GetUrl());
|
| + }
|
| }
|
|
|
| if (!navigation->IsErrorPage()) {
|
| @@ -1167,18 +1229,18 @@
|
|
|
| - (OpenInController*)openInController {
|
| if (!openInController_) {
|
| - openInController_ = [[OpenInController alloc]
|
| + openInController_.reset([[OpenInController alloc]
|
| initWithRequestContext:browserState_->GetRequestContext()
|
| - webController:self.webController];
|
| - }
|
| - return openInController_;
|
| + webController:self.webController]);
|
| + }
|
| + return openInController_.get();
|
| }
|
|
|
| - (id<CRWNativeContent>)controllerForUnhandledContentAtURL:(const GURL&)url {
|
| // Shows download manager UI for unhandled content.
|
| DownloadManagerController* downloadController =
|
| - [[DownloadManagerController alloc] initWithWebState:self.webState
|
| - downloadURL:url];
|
| + [[[DownloadManagerController alloc] initWithWebState:self.webState
|
| + downloadURL:url] autorelease];
|
| [downloadController start];
|
| return downloadController;
|
| }
|
| @@ -1211,21 +1273,22 @@
|
| }
|
|
|
| - (void)countMainFrameLoad {
|
| - if ([self isPrerenderTab] || [self url].SchemeIs(kChromeUIScheme))
|
| - return;
|
| - base::RecordAction(base::UserMetricsAction("MobilePageLoaded"));
|
| + if ([self isPrerenderTab] || [self url].SchemeIs(kChromeUIScheme)) {
|
| + return;
|
| + }
|
| + base::RecordAction(UserMetricsAction("MobilePageLoaded"));
|
| }
|
|
|
| - (void)applicationDidBecomeActive {
|
| - if (!requireReloadAfterBecomingActive_)
|
| - return;
|
| - if (visible_) {
|
| - self.navigationManager->Reload(web::ReloadType::NORMAL,
|
| - false /* check_for_repost */);
|
| - } else {
|
| - [self.webController requirePageReload];
|
| - }
|
| - requireReloadAfterBecomingActive_ = NO;
|
| + if (requireReloadAfterBecomingActive_) {
|
| + if (visible_) {
|
| + self.navigationManager->Reload(web::ReloadType::NORMAL,
|
| + false /* check_for_repost */);
|
| + } else {
|
| + [self.webController requirePageReload];
|
| + }
|
| + requireReloadAfterBecomingActive_ = NO;
|
| + }
|
| }
|
|
|
| #pragma mark -
|
| @@ -1249,6 +1312,10 @@
|
|
|
| - (UIView*)superviewForReaderModePanel {
|
| return self.view;
|
| +}
|
| +
|
| +- (ReaderModeController*)readerModeController {
|
| + return readerModeController_.get();
|
| }
|
|
|
| - (BOOL)canSwitchToReaderMode {
|
| @@ -1328,6 +1395,15 @@
|
| navigationManager->LoadURLWithParams(params);
|
| }
|
|
|
| +- (id<SnapshotOverlayProvider>)snapshotOverlayProvider {
|
| + return snapshotOverlayProvider_.get();
|
| +}
|
| +
|
| +- (void)setSnapshotOverlayProvider:
|
| + (id<SnapshotOverlayProvider>)snapshotOverlayProvider {
|
| + snapshotOverlayProvider_.reset(snapshotOverlayProvider);
|
| +}
|
| +
|
| - (void)evaluateU2FResultFromURL:(const GURL&)URL {
|
| DCHECK(U2FController_);
|
| [U2FController_ evaluateU2FResultFromU2FURL:URL webState:self.webState];
|
| @@ -1368,7 +1444,7 @@
|
| // checked in several places.
|
| if (isUserNavigationEvent && !isPrerenderTab_ &&
|
| ![self navigationManager]->GetPendingItem() && url != self.url) {
|
| - base::RecordAction(base::UserMetricsAction("MobileTabClobbered"));
|
| + base::RecordAction(UserMetricsAction("MobileTabClobbered"));
|
| if ([parentTabModel_ tabUsageRecorder])
|
| [parentTabModel_ tabUsageRecorder]->RecordPageLoadStart(self);
|
| }
|
| @@ -1407,8 +1483,9 @@
|
| }
|
| favicon::FaviconDriver* faviconDriver =
|
| favicon::WebFaviconDriver::FromWebState(webState);
|
| - if (faviconDriver)
|
| + if (faviconDriver) {
|
| faviconDriver->FetchFavicon(lastCommittedURL);
|
| + }
|
| [parentTabModel_ notifyTabChanged:self];
|
| if (parentTabModel_) {
|
| [[NSNotificationCenter defaultCenter]
|
| @@ -1461,8 +1538,9 @@
|
| else
|
| [autoReloadBridge_ loadFailedForURL:lastCommittedURL wasPost:wasPost];
|
| [webControllerSnapshotHelper_ setSnapshotCoalescingEnabled:YES];
|
| - if (!loadSuccess)
|
| + if (!loadSuccess) {
|
| [fullScreenController_ disableFullScreen];
|
| + }
|
| [self recordInterfaceOrientation];
|
| navigation_metrics::RecordMainFrameNavigation(
|
| lastCommittedURL, true, self.browserState->IsOffTheRecord());
|
| @@ -1491,8 +1569,9 @@
|
| finishPageLoadForTab:self
|
| loadSuccess:loadSuccess];
|
|
|
| - if (loadSuccess)
|
| + if (loadSuccess) {
|
| [self updateSnapshotWithOverlay:YES visibleFrameOnly:YES];
|
| + }
|
| [webControllerSnapshotHelper_ setSnapshotCoalescingEnabled:NO];
|
| }
|
|
|
| @@ -1571,8 +1650,9 @@
|
|
|
| // Always allow frame loads.
|
| BOOL isFrameLoad = (url != mainDocumentURL);
|
| - if (isFrameLoad)
|
| + if (isFrameLoad) {
|
| return YES;
|
| + }
|
|
|
| // TODO(crbug.com/546402): If this turns out to be useful, find a less hacky
|
| // hook point to send this from.
|
| @@ -1701,8 +1781,9 @@
|
| }
|
|
|
| if (visible_) {
|
| - if (!applicationIsNotActive)
|
| + if (!applicationIsNotActive) {
|
| [fullScreenController_ disableFullScreen];
|
| + }
|
| } else {
|
| [self.webController requirePageReload];
|
| }
|
| @@ -1744,8 +1825,8 @@
|
| signin_metrics::LogAccountReconcilorStateOnGaiaResponse(
|
| ios::AccountReconcilorFactory::GetForBrowserState(browserState_)
|
| ->GetState());
|
| - GenericChromeCommand* command =
|
| - [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_ACCOUNTS_SETTINGS];
|
| + base::scoped_nsobject<GenericChromeCommand> command(
|
| + [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_ACCOUNTS_SETTINGS]);
|
| [self.view chromeExecuteCommand:command];
|
| }
|
|
|
| @@ -1760,8 +1841,8 @@
|
| signin_metrics::LogAccountReconcilorStateOnGaiaResponse(
|
| ios::AccountReconcilorFactory::GetForBrowserState(browserState_)
|
| ->GetState());
|
| - GenericChromeCommand* command =
|
| - [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_ADD_ACCOUNT];
|
| + base::scoped_nsobject<GenericChromeCommand> command(
|
| + [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_ADD_ACCOUNT]);
|
| [self.view chromeExecuteCommand:command];
|
| }
|
|
|
| @@ -1782,23 +1863,31 @@
|
| [self goBack];
|
|
|
| if (url.is_valid()) {
|
| - OpenUrlCommand* command = [[OpenUrlCommand alloc]
|
| + base::scoped_nsobject<OpenUrlCommand> command([[OpenUrlCommand alloc]
|
| initWithURL:url
|
| referrer:web::Referrer() // Strip referrer when switching modes.
|
| inIncognito:YES
|
| inBackground:NO
|
| - appendTo:kLastTab];
|
| + appendTo:kLastTab]);
|
| [self.view chromeExecuteCommand:command];
|
| } else {
|
| - GenericChromeCommand* command =
|
| - [[GenericChromeCommand alloc] initWithTag:IDC_NEW_INCOGNITO_TAB];
|
| - [self.view chromeExecuteCommand:command];
|
| + base::scoped_nsobject<GenericChromeCommand> chromeCommand(
|
| + [[GenericChromeCommand alloc] initWithTag:IDC_NEW_INCOGNITO_TAB]);
|
| + [self.view chromeExecuteCommand:chromeCommand];
|
| }
|
| }
|
|
|
| - (NativeAppNavigationController*)nativeAppNavigationController {
|
| // TODO(crbug.com/711511): This call should eventually be eliminated.
|
| return nil;
|
| +}
|
| +
|
| +- (id<PassKitDialogProvider>)passKitDialogProvider {
|
| + return passKitDialogProvider_.get();
|
| +}
|
| +
|
| +- (void)setPassKitDialogProvider:(id<PassKitDialogProvider>)provider {
|
| + passKitDialogProvider_.reset(provider);
|
| }
|
|
|
| - (void)wasShown {
|
| @@ -1829,7 +1918,7 @@
|
| @implementation Tab (TestingSupport)
|
|
|
| - (void)replaceExternalAppLauncher:(id)externalAppLauncher {
|
| - externalAppLauncher_ = externalAppLauncher;
|
| + externalAppLauncher_.reset([externalAppLauncher retain]);
|
| }
|
|
|
| - (TabModel*)parentTabModel {
|
| @@ -1837,7 +1926,7 @@
|
| }
|
|
|
| - (FormInputAccessoryViewController*)inputAccessoryViewController {
|
| - return inputAccessoryViewController_;
|
| + return inputAccessoryViewController_.get();
|
| }
|
|
|
| @end
|
|
|