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

Side by Side Diff: ios/chrome/browser/tabs/tab_model.mm

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

Powered by Google App Engine
This is Rietveld 408576698