| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "ios/chrome/browser/tabs/tab_model.h" | 5 #import "ios/chrome/browser/tabs/tab_model.h" |
| 6 | 6 |
| 7 #include <cstdint> | 7 #include <cstdint> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #import "ios/chrome/browser/tabs/tab_model_observers_bridge.h" | 39 #import "ios/chrome/browser/tabs/tab_model_observers_bridge.h" |
| 40 #import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h" | 40 #import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h" |
| 41 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" | 41 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" |
| 42 #import "ios/chrome/browser/tabs/tab_model_web_state_list_delegate.h" | 42 #import "ios/chrome/browser/tabs/tab_model_web_state_list_delegate.h" |
| 43 #import "ios/chrome/browser/tabs/tab_parenting_observer.h" | 43 #import "ios/chrome/browser/tabs/tab_parenting_observer.h" |
| 44 #import "ios/chrome/browser/xcallback_parameters.h" | 44 #import "ios/chrome/browser/xcallback_parameters.h" |
| 45 #import "ios/shared/chrome/browser/tabs/web_state_list.h" | 45 #import "ios/shared/chrome/browser/tabs/web_state_list.h" |
| 46 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h
" | 46 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h
" |
| 47 #import "ios/shared/chrome/browser/tabs/web_state_list_metrics_observer.h" | 47 #import "ios/shared/chrome/browser/tabs/web_state_list_metrics_observer.h" |
| 48 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" | 48 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" |
| 49 #import "ios/shared/chrome/browser/tabs/web_state_list_serialization.h" |
| 49 #import "ios/shared/chrome/browser/tabs/web_state_opener.h" | 50 #import "ios/shared/chrome/browser/tabs/web_state_opener.h" |
| 50 #include "ios/web/public/browser_state.h" | 51 #include "ios/web/public/browser_state.h" |
| 51 #include "ios/web/public/certificate_policy_cache.h" | 52 #include "ios/web/public/certificate_policy_cache.h" |
| 52 #include "ios/web/public/navigation_item.h" | 53 #include "ios/web/public/navigation_item.h" |
| 53 #import "ios/web/public/navigation_manager.h" | 54 #import "ios/web/public/navigation_manager.h" |
| 54 #import "ios/web/public/serializable_user_data_manager.h" | 55 #import "ios/web/public/serializable_user_data_manager.h" |
| 55 #include "ios/web/public/web_state/session_certificate_policy_cache.h" | 56 #include "ios/web/public/web_state/session_certificate_policy_cache.h" |
| 56 #include "ios/web/public/web_thread.h" | 57 #include "ios/web/public/web_thread.h" |
| 57 #import "ios/web/web_state/ui/crw_web_controller.h" | 58 #import "ios/web/web_state/ui/crw_web_controller.h" |
| 58 #import "ios/web/web_state/web_state_impl.h" | 59 #import "ios/web/web_state/web_state_impl.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 69 NSString* const kTabModelTabDeselectedNotification = | 70 NSString* const kTabModelTabDeselectedNotification = |
| 70 @"kTabModelTabDeselectedNotification"; | 71 @"kTabModelTabDeselectedNotification"; |
| 71 NSString* const kTabModelNewTabWillOpenNotification = | 72 NSString* const kTabModelNewTabWillOpenNotification = |
| 72 @"kTabModelNewTabWillOpenNotification"; | 73 @"kTabModelNewTabWillOpenNotification"; |
| 73 NSString* const kTabModelTabKey = @"tab"; | 74 NSString* const kTabModelTabKey = @"tab"; |
| 74 NSString* const kTabModelPageLoadSuccess = @"pageLoadSuccess"; | 75 NSString* const kTabModelPageLoadSuccess = @"pageLoadSuccess"; |
| 75 NSString* const kTabModelOpenInBackgroundKey = @"shouldOpenInBackground"; | 76 NSString* const kTabModelOpenInBackgroundKey = @"shouldOpenInBackground"; |
| 76 | 77 |
| 77 namespace { | 78 namespace { |
| 78 | 79 |
| 79 // The key under which the opener Tab ID is stored in the WebState's | |
| 80 // serializable user data. | |
| 81 NSString* const kOpenerIDKey = @"OpenerID"; | |
| 82 | |
| 83 // The key under which the opener navigation index is stored in the WebState's | |
| 84 // serializable user data. | |
| 85 NSString* const kOpenerNavigationIndexKey = @"OpenerNavigationIndex"; | |
| 86 | |
| 87 // Updates CRWSessionCertificatePolicyManager's certificate policy cache. | 80 // Updates CRWSessionCertificatePolicyManager's certificate policy cache. |
| 88 void UpdateCertificatePolicyCacheFromWebState( | 81 void UpdateCertificatePolicyCacheFromWebState( |
| 89 const scoped_refptr<web::CertificatePolicyCache>& policy_cache, | 82 const scoped_refptr<web::CertificatePolicyCache>& policy_cache, |
| 90 const web::WebState* web_state) { | 83 const web::WebState* web_state) { |
| 91 DCHECK(web_state); | 84 DCHECK(web_state); |
| 92 DCHECK_CURRENTLY_ON(web::WebThread::UI); | 85 DCHECK_CURRENTLY_ON(web::WebThread::UI); |
| 93 web_state->GetSessionCertificatePolicyCache()->UpdateCertificatePolicyCache( | 86 web_state->GetSessionCertificatePolicyCache()->UpdateCertificatePolicyCache( |
| 94 policy_cache); | 87 policy_cache); |
| 95 } | 88 } |
| 96 | 89 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 117 DCHECK(web_state_list); | 110 DCHECK(web_state_list); |
| 118 DCHECK_CURRENTLY_ON(web::WebThread::UI); | 111 DCHECK_CURRENTLY_ON(web::WebThread::UI); |
| 119 task_tracker->PostTaskAndReply( | 112 task_tracker->PostTaskAndReply( |
| 120 task_runner.get(), FROM_HERE, | 113 task_runner.get(), FROM_HERE, |
| 121 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies, | 114 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies, |
| 122 policy_cache), | 115 policy_cache), |
| 123 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache, | 116 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache, |
| 124 base::Unretained(web_state_list))); | 117 base::Unretained(web_state_list))); |
| 125 } | 118 } |
| 126 | 119 |
| 127 // Internal helper function returning the opener for a given Tab by | |
| 128 // checking the associated Tab tabId (should be removed once the opener | |
| 129 // is passed to the insertTab:atIndex: and replaceTab:withTab: methods). | |
| 130 WebStateOpener GetOpenerForTab(id<NSFastEnumeration> tabs, Tab* tab) { | |
| 131 web::SerializableUserDataManager* user_data_manager = | |
| 132 web::SerializableUserDataManager::FromWebState(tab.webState); | |
| 133 | |
| 134 NSString* opener_id = base::mac::ObjCCast<NSString>( | |
| 135 user_data_manager->GetValueForSerializationKey(kOpenerIDKey)); | |
| 136 if (!opener_id || ![opener_id length]) | |
| 137 return WebStateOpener(nullptr); | |
| 138 | |
| 139 NSNumber* boxed_opener_navigation_index = base::mac::ObjCCast<NSNumber>( | |
| 140 user_data_manager->GetValueForSerializationKey( | |
| 141 kOpenerNavigationIndexKey)); | |
| 142 if (!boxed_opener_navigation_index) | |
| 143 return WebStateOpener(nullptr); | |
| 144 | |
| 145 for (Tab* current_tab in tabs) { | |
| 146 if ([opener_id isEqualToString:current_tab.tabId]) { | |
| 147 return WebStateOpener(current_tab.webState, | |
| 148 [boxed_opener_navigation_index intValue]); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 return WebStateOpener(nullptr); | |
| 153 } | |
| 154 | |
| 155 } // anonymous namespace | 120 } // anonymous namespace |
| 156 | 121 |
| 157 @interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory> | 122 @interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory> |
| 158 @end | 123 @end |
| 159 | 124 |
| 160 @implementation TabModelWebStateProxyFactory | 125 @implementation TabModelWebStateProxyFactory |
| 161 | 126 |
| 162 - (id)proxyForWebState:(web::WebState*)webState { | 127 - (id)proxyForWebState:(web::WebState*)webState { |
| 163 return LegacyTabHelper::GetTabForWebState(webState); | 128 return LegacyTabHelper::GetTabForWebState(webState); |
| 164 } | 129 } |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 | 658 |
| 694 - (SessionWindowIOS*)windowForSavingSession { | 659 - (SessionWindowIOS*)windowForSavingSession { |
| 695 // Background tabs will already have their state preserved, but not the | 660 // Background tabs will already have their state preserved, but not the |
| 696 // fg tab. Do it now. | 661 // fg tab. Do it now. |
| 697 [self.currentTab recordStateInHistory]; | 662 [self.currentTab recordStateInHistory]; |
| 698 | 663 |
| 699 // Build the array of sessions. Copy the session objects as the saving will | 664 // Build the array of sessions. Copy the session objects as the saving will |
| 700 // be done on a separate thread. | 665 // be done on a separate thread. |
| 701 // TODO(crbug.com/661986): This could get expensive especially since this | 666 // TODO(crbug.com/661986): This could get expensive especially since this |
| 702 // window may never be saved (if another call comes in before the delay). | 667 // window may never be saved (if another call comes in before the delay). |
| 703 NSMutableArray<CRWSessionStorage*>* sessions = | |
| 704 [NSMutableArray arrayWithCapacity:[self count]]; | |
| 705 | |
| 706 for (int index = 0; index < _webStateList->count(); ++index) { | |
| 707 web::WebState* webState = _webStateList->GetWebStateAt(index); | |
| 708 web::SerializableUserDataManager* userDataManager = | |
| 709 web::SerializableUserDataManager::FromWebState(webState); | |
| 710 | |
| 711 WebStateOpener opener = _webStateList->GetOpenerOfWebStateAt(index); | |
| 712 if (opener.opener) { | |
| 713 Tab* parentTab = LegacyTabHelper::GetTabForWebState(opener.opener); | |
| 714 userDataManager->AddSerializableData(parentTab.tabId, kOpenerIDKey); | |
| 715 userDataManager->AddSerializableData(@(opener.navigation_index), | |
| 716 kOpenerNavigationIndexKey); | |
| 717 } else { | |
| 718 userDataManager->AddSerializableData([NSNull null], kOpenerIDKey); | |
| 719 userDataManager->AddSerializableData([NSNull null], | |
| 720 kOpenerNavigationIndexKey); | |
| 721 } | |
| 722 | |
| 723 [sessions addObject:webState->BuildSessionStorage()]; | |
| 724 } | |
| 725 | |
| 726 return [[[SessionWindowIOS alloc] | 668 return [[[SessionWindowIOS alloc] |
| 727 initWithSessions:sessions | 669 initWithSessions:SerializeWebStateList(_webStateList.get()) |
| 728 selectedIndex:[self indexOfTab:self.currentTab]] autorelease]; | 670 selectedIndex:[self indexOfTab:self.currentTab]] autorelease]; |
| 729 } | 671 } |
| 730 | 672 |
| 731 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab { | 673 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab { |
| 732 // A scoped_nsobject is used rather than an NSDictionary with static | 674 // A scoped_nsobject is used rather than an NSDictionary with static |
| 733 // initializer dictionaryWithObject, because that approach adds the dictionary | 675 // initializer dictionaryWithObject, because that approach adds the dictionary |
| 734 // to the autorelease pool, which in turn holds Tab alive longer than | 676 // to the autorelease pool, which in turn holds Tab alive longer than |
| 735 // necessary. | 677 // necessary. |
| 736 base::scoped_nsobject<NSDictionary> userInfo( | 678 base::scoped_nsobject<NSDictionary> userInfo( |
| 737 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); | 679 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); |
| 738 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName | 680 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName |
| 739 object:self | 681 object:self |
| 740 userInfo:userInfo]; | 682 userInfo:userInfo]; |
| 741 } | 683 } |
| 742 | 684 |
| 743 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window | 685 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window |
| 744 persistState:(BOOL)persistState { | 686 persistState:(BOOL)persistState { |
| 745 DCHECK(_browserState); | 687 DCHECK(_browserState); |
| 746 DCHECK(window); | 688 DCHECK(window); |
| 747 | 689 |
| 748 NSArray* sessions = window.sessions; | 690 NSArray* sessions = window.sessions; |
| 749 if (!sessions.count) | 691 if (!sessions.count) |
| 750 return NO; | 692 return NO; |
| 751 | 693 |
| 752 int oldCount = _webStateList->count(); | 694 int oldCount = _webStateList->count(); |
| 753 DCHECK_GE(oldCount, 0); | 695 DCHECK_GE(oldCount, 0); |
| 754 | 696 |
| 755 web::WebState::CreateParams params(_browserState); | 697 web::WebState::CreateParams createParams(_browserState); |
| 698 DeserializeWebStateList( |
| 699 _webStateList.get(), sessions, |
| 700 base::BindRepeating(&web::WebState::CreateWithStorageSession, |
| 701 createParams)); |
| 702 |
| 703 DCHECK_GT(_webStateList->count(), oldCount); |
| 704 int restoredCount = _webStateList->count() - oldCount; |
| 705 DCHECK_EQ(sessions.count, static_cast<NSUInteger>(restoredCount)); |
| 706 |
| 756 scoped_refptr<web::CertificatePolicyCache> policyCache = | 707 scoped_refptr<web::CertificatePolicyCache> policyCache = |
| 757 web::BrowserState::GetCertificatePolicyCache(_browserState); | 708 web::BrowserState::GetCertificatePolicyCache(_browserState); |
| 758 | 709 |
| 759 base::scoped_nsobject<NSMutableArray<Tab*>> restoredTabs( | 710 base::scoped_nsobject<NSMutableArray<Tab*>> restoredTabs( |
| 760 [[NSMutableArray alloc] initWithCapacity:sessions.count]); | 711 [[NSMutableArray alloc] initWithCapacity:sessions.count]); |
| 761 | 712 |
| 762 // Recreate all the restored Tabs and add them to the WebStateList without | |
| 763 // any opener-opened relationship (as the n-th restored Tab opener may be | |
| 764 // at an index larger than n). Then in a second pass fix the openers. | |
| 765 for (CRWSessionStorage* session in sessions) { | |
| 766 std::unique_ptr<web::WebState> webState = | |
| 767 web::WebState::CreateWithStorageSession(params, session); | |
| 768 _webStateList->InsertWebState(_webStateList->count(), std::move(webState)); | |
| 769 } | |
| 770 | |
| 771 for (int index = oldCount; index < _webStateList->count(); ++index) { | 713 for (int index = oldCount; index < _webStateList->count(); ++index) { |
| 772 web::WebState* webState = _webStateList->GetWebStateAt(index); | 714 web::WebState* webState = _webStateList->GetWebStateAt(index); |
| 773 Tab* tab = LegacyTabHelper::GetTabForWebState(webState); | 715 Tab* tab = LegacyTabHelper::GetTabForWebState(webState); |
| 716 |
| 774 tab.webController.webUsageEnabled = webUsageEnabled_; | 717 tab.webController.webUsageEnabled = webUsageEnabled_; |
| 775 tab.webController.usePlaceholderOverlay = YES; | 718 tab.webController.usePlaceholderOverlay = YES; |
| 776 | 719 |
| 777 // Restore the CertificatePolicyCache (note that webState is invalid after | 720 // Restore the CertificatePolicyCache (note that webState is invalid after |
| 778 // passing it via move semantic to -initWithWebState:model:). | 721 // passing it via move semantic to -initWithWebState:model:). |
| 779 UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]); | 722 UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]); |
| 780 [restoredTabs addObject:tab]; | 723 [restoredTabs addObject:tab]; |
| 781 } | 724 } |
| 782 | 725 |
| 783 DCHECK_EQ(sessions.count, [restoredTabs count]); | |
| 784 DCHECK_GT(_webStateList->count(), oldCount); | |
| 785 | |
| 786 // Fix openers now that all Tabs have been restored. Only look for an opener | |
| 787 // Tab in the newly restored Tabs and not in the already open Tabs. | |
| 788 for (int index = oldCount; index < _webStateList->count(); ++index) { | |
| 789 DCHECK_GE(index, oldCount); | |
| 790 NSUInteger tabIndex = static_cast<NSUInteger>(index - oldCount); | |
| 791 Tab* tab = [restoredTabs objectAtIndex:tabIndex]; | |
| 792 WebStateOpener opener = GetOpenerForTab(restoredTabs.get(), tab); | |
| 793 if (opener.opener) | |
| 794 _webStateList->SetOpenerOfWebStateAt(index, opener); | |
| 795 } | |
| 796 | |
| 797 // Update the selected tab if there was a selected Tab in the saved session. | 726 // Update the selected tab if there was a selected Tab in the saved session. |
| 798 if (window.selectedIndex != NSNotFound) { | 727 if (window.selectedIndex != NSNotFound) { |
| 799 NSUInteger selectedIndex = window.selectedIndex + oldCount; | 728 NSUInteger selectedIndex = window.selectedIndex + oldCount; |
| 800 DCHECK_LT(selectedIndex, self.count); | 729 DCHECK_LT(selectedIndex, self.count); |
| 801 DCHECK([self tabAtIndex:selectedIndex]); | 730 DCHECK([self tabAtIndex:selectedIndex]); |
| 802 | 731 |
| 803 if (persistState && self.currentTab) | 732 if (persistState && self.currentTab) |
| 804 [self.currentTab recordStateInHistory]; | 733 [self.currentTab recordStateInHistory]; |
| 805 _webStateList->ActivateWebStateAt(static_cast<int>(selectedIndex)); | 734 _webStateList->ActivateWebStateAt(static_cast<int>(selectedIndex)); |
| 806 } | 735 } |
| 807 | 736 |
| 808 // If there was only one tab and it was the new tab page, clobber it. | 737 // If there was only one tab and it was the new tab page, clobber it. |
| 809 BOOL closedNTPTab = NO; | 738 BOOL closedNTPTab = NO; |
| 810 if (oldCount == 1) { | 739 if (oldCount == 1) { |
| 811 Tab* tab = [self tabAtIndex:0]; | 740 Tab* tab = [self tabAtIndex:0]; |
| 812 if (tab.url == GURL(kChromeUINewTabURL)) { | 741 if (tab.url == GURL(kChromeUINewTabURL)) { |
| 813 [self closeTab:tab]; | 742 [self closeTab:tab]; |
| 814 closedNTPTab = YES; | 743 closedNTPTab = YES; |
| 815 oldCount = 0; | 744 oldCount = 0; |
| 816 } | 745 } |
| 817 } | 746 } |
| 818 if (_tabUsageRecorder) | 747 if (_tabUsageRecorder) |
| 819 _tabUsageRecorder->InitialRestoredTabs(self.currentTab, restoredTabs); | 748 _tabUsageRecorder->InitialRestoredTabs(self.currentTab, restoredTabs.get()); |
| 820 return closedNTPTab; | 749 return closedNTPTab; |
| 821 } | 750 } |
| 822 | 751 |
| 823 #pragma mark - Notification Handlers | 752 #pragma mark - Notification Handlers |
| 824 | 753 |
| 825 // Called when UIApplicationWillResignActiveNotification is received. | 754 // Called when UIApplicationWillResignActiveNotification is received. |
| 826 - (void)willResignActive:(NSNotification*)notify { | 755 - (void)willResignActive:(NSNotification*)notify { |
| 827 if (webUsageEnabled_ && self.currentTab) { | 756 if (webUsageEnabled_ && self.currentTab) { |
| 828 [[SnapshotCache sharedInstance] | 757 [[SnapshotCache sharedInstance] |
| 829 willBeSavedGreyWhenBackgrounding:self.currentTab.tabId]; | 758 willBeSavedGreyWhenBackgrounding:self.currentTab.tabId]; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 858 } | 787 } |
| 859 | 788 |
| 860 // Called when UIApplicationWillEnterForegroundNotification is received. | 789 // Called when UIApplicationWillEnterForegroundNotification is received. |
| 861 - (void)applicationWillEnterForeground:(NSNotification*)notify { | 790 - (void)applicationWillEnterForeground:(NSNotification*)notify { |
| 862 if (_tabUsageRecorder) { | 791 if (_tabUsageRecorder) { |
| 863 _tabUsageRecorder->AppWillEnterForeground(); | 792 _tabUsageRecorder->AppWillEnterForeground(); |
| 864 } | 793 } |
| 865 } | 794 } |
| 866 | 795 |
| 867 @end | 796 @end |
| OLD | NEW |