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

Side by Side Diff: ios/shared/chrome/browser/tabs/web_state_list_serialization.mm

Issue 2799723002: [ios] Move WebStateList to ios/chrome/browser/web_state_list. (Closed)
Patch Set: Rebase. Created 3 years, 8 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
(Empty)
1 // Copyright 2017 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/shared/chrome/browser/tabs/web_state_list_serialization.h"
6
7 #include <memory>
8 #include <unordered_map>
9
10 #include "base/callback.h"
11 #include "base/logging.h"
12 #import "base/mac/foundation_util.h"
13 #import "ios/shared/chrome/browser/tabs/web_state_list.h"
14 #import "ios/shared/chrome/browser/tabs/web_state_opener.h"
15 #import "ios/web/public/serializable_user_data_manager.h"
16 #import "ios/web/public/web_state/web_state.h"
17
18 #if !defined(__has_feature) || !__has_feature(objc_arc)
19 #error "This file requires ARC support."
20 #endif
21
22 namespace {
23 // Keys used to store information about the opener-opened relationship between
24 // the WebStates stored in the WebStateList.
25 NSString* const kOpenerIndexKey = @"OpenerIndex";
26 NSString* const kOpenerNavigationIndexKey = @"OpenerNavigationIndex";
27
28 // Legacy keys used to store information about the opener-opener relationship
29 // before the M-60 release. Remove once M-70 has shipped.
30 NSString* const kObjectIDKey = @"TabID";
31 NSString* const kOpenerIDKey = @"OpenerID";
32
33 // Returns whether the opener-opener relationship is encoded with legacy format.
34 // The legacy format (pre M-59) references the opener by id while the new format
35 // references it by index.
36 // TODO(crbug.com/704941): remove once no sessions uses the old format.
37 bool IsSessionUsingLegacyFormat(WebStateList* web_state_list, int old_count) {
38 for (int index = old_count; index < web_state_list->count(); ++index) {
39 web::WebState* web_state = web_state_list->GetWebStateAt(index);
40 web::SerializableUserDataManager* user_data_manager =
41 web::SerializableUserDataManager::FromWebState(web_state);
42
43 if (!user_data_manager->GetValueForSerializationKey(kOpenerIndexKey))
44 return true;
45 }
46 return false;
47 }
48
49 // Restores the WebStates opener-opened relationship. The relationship is
50 // encoded using legacy format.
51 // TODO(crbug.com/704941): remove once no sessions uses the old format.
52 void RestoreRelationshipLegacy(WebStateList* web_state_list, int old_count) {
53 NSMutableDictionary<NSString*, NSValue*>* id_to_web_state =
54 [NSMutableDictionary dictionary];
55
56 for (int index = old_count; index < web_state_list->count(); ++index) {
57 web::WebState* web_state = web_state_list->GetWebStateAt(index);
58 web::SerializableUserDataManager* user_data_manager =
59 web::SerializableUserDataManager::FromWebState(web_state);
60
61 NSString* object_id = base::mac::ObjCCast<NSString>(
62 user_data_manager->GetValueForSerializationKey(kObjectIDKey));
63
64 if (!object_id || ![object_id length])
65 continue;
66
67 if (id_to_web_state[object_id] != nil)
68 continue;
69
70 id_to_web_state[object_id] = [NSValue valueWithPointer:web_state];
71 }
72
73 for (int index = old_count; index < web_state_list->count(); ++index) {
74 web::WebState* web_state = web_state_list->GetWebStateAt(index);
75 web::SerializableUserDataManager* user_data_manager =
76 web::SerializableUserDataManager::FromWebState(web_state);
77
78 NSString* opener_id = base::mac::ObjCCast<NSString>(
79 user_data_manager->GetValueForSerializationKey(kOpenerIDKey));
80
81 NSNumber* boxed_opener_navigation_index = base::mac::ObjCCast<NSNumber>(
82 user_data_manager->GetValueForSerializationKey(
83 kOpenerNavigationIndexKey));
84
85 if (!opener_id || !boxed_opener_navigation_index || ![opener_id length])
86 continue;
87
88 if (id_to_web_state[opener_id] == nil)
89 continue;
90
91 web::WebState* opener_web_state =
92 static_cast<web::WebState*>(id_to_web_state[opener_id].pointerValue);
93
94 web_state_list->SetOpenerOfWebStateAt(
95 index, WebStateOpener(opener_web_state,
96 [boxed_opener_navigation_index intValue]));
97 }
98 }
99
100 // Restores the WebStates opener-opened relationship.
101 void RestoreRelationship(WebStateList* web_state_list, int old_count) {
102 if (IsSessionUsingLegacyFormat(web_state_list, old_count))
103 return RestoreRelationshipLegacy(web_state_list, old_count);
104
105 for (int index = old_count; index < web_state_list->count(); ++index) {
106 web::WebState* web_state = web_state_list->GetWebStateAt(index);
107 web::SerializableUserDataManager* user_data_manager =
108 web::SerializableUserDataManager::FromWebState(web_state);
109
110 NSNumber* boxed_opener_index = base::mac::ObjCCast<NSNumber>(
111 user_data_manager->GetValueForSerializationKey(kOpenerIndexKey));
112
113 NSNumber* boxed_opener_navigation_index = base::mac::ObjCCast<NSNumber>(
114 user_data_manager->GetValueForSerializationKey(
115 kOpenerNavigationIndexKey));
116
117 if (!boxed_opener_index || !boxed_opener_navigation_index)
118 continue;
119
120 // If opener index is out of bound then assume there is no opener.
121 int opener_index = [boxed_opener_index intValue] + old_count;
122 if (opener_index < old_count || opener_index >= web_state_list->count())
123 continue;
124
125 web::WebState* opener = web_state_list->GetWebStateAt(opener_index);
126 web_state_list->SetOpenerOfWebStateAt(
127 index,
128 WebStateOpener(opener, [boxed_opener_navigation_index intValue]));
129 }
130 }
131 } // namespace
132
133 NSArray<CRWSessionStorage*>* SerializeWebStateList(
134 WebStateList* web_state_list) {
135 NSMutableArray<CRWSessionStorage*>* serialized_session =
136 [NSMutableArray arrayWithCapacity:web_state_list->count()];
137
138 for (int index = 0; index < web_state_list->count(); ++index) {
139 web::WebState* web_state = web_state_list->GetWebStateAt(index);
140 WebStateOpener opener = web_state_list->GetOpenerOfWebStateAt(index);
141
142 web::SerializableUserDataManager* user_data_manager =
143 web::SerializableUserDataManager::FromWebState(web_state);
144
145 int opener_index = WebStateList::kInvalidIndex;
146 if (opener.opener) {
147 opener_index = web_state_list->GetIndexOfWebState(opener.opener);
148 DCHECK_NE(opener_index, WebStateList::kInvalidIndex);
149 user_data_manager->AddSerializableData(@(opener_index), kOpenerIndexKey);
150 user_data_manager->AddSerializableData(@(opener.navigation_index),
151 kOpenerNavigationIndexKey);
152 } else {
153 user_data_manager->AddSerializableData([NSNull null], kOpenerIndexKey);
154 user_data_manager->AddSerializableData([NSNull null],
155 kOpenerNavigationIndexKey);
156 }
157
158 [serialized_session addObject:web_state->BuildSessionStorage()];
159 }
160
161 return [serialized_session copy];
162 }
163
164 void DeserializeWebStateList(WebStateList* web_state_list,
165 NSArray<CRWSessionStorage*>* sessions,
166 const WebStateFactory& web_state_factory) {
167 int old_count = web_state_list->count();
168 for (CRWSessionStorage* session in sessions) {
169 std::unique_ptr<web::WebState> web_state = web_state_factory.Run(session);
170 web_state_list->InsertWebState(web_state_list->count(),
171 std::move(web_state));
172 }
173
174 RestoreRelationship(web_state_list, old_count);
175 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698