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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 DCHECK(web_state_list); | 110 DCHECK(web_state_list); |
111 DCHECK_CURRENTLY_ON(web::WebThread::UI); | 111 DCHECK_CURRENTLY_ON(web::WebThread::UI); |
112 task_tracker->PostTaskAndReply( | 112 task_tracker->PostTaskAndReply( |
113 task_runner.get(), FROM_HERE, | 113 task_runner.get(), FROM_HERE, |
114 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies, | 114 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies, |
115 policy_cache), | 115 policy_cache), |
116 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache, | 116 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache, |
117 base::Unretained(web_state_list))); | 117 base::Unretained(web_state_list))); |
118 } | 118 } |
119 | 119 |
| 120 // Internal helper function returning the opener for a given Tab by |
| 121 // checking the associated Tab tabId (should be removed once the opener |
| 122 // is passed to the insertTab:atIndex: and replaceTab:withTab: methods). |
| 123 Tab* GetOpenerForTab(id<NSFastEnumeration> tabs, Tab* tab) { |
| 124 NSString* opener_id = |
| 125 [tab navigationManager]->GetSessionController().openerId; |
| 126 if (!opener_id) |
| 127 return nullptr; |
| 128 |
| 129 for (Tab* currentTab in tabs) { |
| 130 if ([opener_id isEqualToString:currentTab.tabId]) |
| 131 return currentTab; |
| 132 } |
| 133 |
| 134 return nullptr; |
| 135 } |
| 136 |
120 } // anonymous namespace | 137 } // anonymous namespace |
121 | 138 |
122 @interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory> | 139 @interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory> |
123 @end | 140 @end |
124 | 141 |
125 @implementation TabModelWebStateProxyFactory | 142 @implementation TabModelWebStateProxyFactory |
126 | 143 |
127 - (id)proxyForWebState:(web::WebState*)webState { | 144 - (id)proxyForWebState:(web::WebState*)webState { |
128 return LegacyTabHelper::GetTabForWebState(webState); | 145 return LegacyTabHelper::GetTabForWebState(webState); |
129 } | 146 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 // Helper method that posts a notification with the given name with |tab| | 227 // Helper method that posts a notification with the given name with |tab| |
211 // in the userInfo dictionary under the kTabModelTabKey. | 228 // in the userInfo dictionary under the kTabModelTabKey. |
212 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab; | 229 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab; |
213 | 230 |
214 // Helper method to restore a saved session and control if the state should | 231 // Helper method to restore a saved session and control if the state should |
215 // be persisted or not. Used to implement the public -restoreSessionWindow: | 232 // be persisted or not. Used to implement the public -restoreSessionWindow: |
216 // method and restoring session in the initialiser. | 233 // method and restoring session in the initialiser. |
217 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window | 234 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window |
218 persistState:(BOOL)persistState; | 235 persistState:(BOOL)persistState; |
219 | 236 |
| 237 // Helper method to insert |tab| at the given |index| recording |parentTab| as |
| 238 // the opener. Broadcasts the proper notifications about the change. The |
| 239 // receiver should be set as the parentTabModel for |tab|; this method doesn't |
| 240 // check that. |
| 241 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index opener:(Tab*)parentTab; |
| 242 |
220 @end | 243 @end |
221 | 244 |
222 @implementation TabModel | 245 @implementation TabModel |
223 | 246 |
224 @synthesize browserState = _browserState; | 247 @synthesize browserState = _browserState; |
225 @synthesize sessionID = _sessionID; | 248 @synthesize sessionID = _sessionID; |
226 @synthesize webUsageEnabled = webUsageEnabled_; | 249 @synthesize webUsageEnabled = webUsageEnabled_; |
227 | 250 |
228 #pragma mark - Overriden | 251 #pragma mark - Overriden |
229 | 252 |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 return nil; | 421 return nil; |
399 for (Tab* tab in self) { | 422 for (Tab* tab in self) { |
400 if ([windowName isEqualToString:tab.windowName]) { | 423 if ([windowName isEqualToString:tab.windowName]) { |
401 return tab; | 424 return tab; |
402 } | 425 } |
403 } | 426 } |
404 return nil; | 427 return nil; |
405 } | 428 } |
406 | 429 |
407 - (Tab*)nextTabWithOpener:(Tab*)tab afterTab:(Tab*)afterTab { | 430 - (Tab*)nextTabWithOpener:(Tab*)tab afterTab:(Tab*)afterTab { |
408 NSUInteger startIndex = NSNotFound; | 431 int startIndex = WebStateList::kInvalidIndex; |
409 // Start looking after |afterTab|. If it's not found, start looking after | |
410 // |tab|. If it's not found either, bail. | |
411 if (afterTab) | 432 if (afterTab) |
412 startIndex = [self indexOfTab:afterTab]; | 433 startIndex = _webStateList.GetIndexOfWebState(afterTab.webState); |
413 if (startIndex == NSNotFound) | 434 |
414 startIndex = [self indexOfTab:tab]; | 435 if (startIndex == WebStateList::kInvalidIndex) |
415 if (startIndex == NSNotFound) | 436 startIndex = _webStateList.GetIndexOfWebState(tab.webState); |
| 437 |
| 438 const int index = _webStateList.GetIndexOfNextWebStateOpenedBy( |
| 439 tab.webState, startIndex, false); |
| 440 if (index == WebStateList::kInvalidIndex) |
416 return nil; | 441 return nil; |
417 NSString* parentID = tab.tabId; | 442 |
418 for (NSUInteger i = startIndex + 1; i < self.count; ++i) { | 443 DCHECK_GE(index, 0); |
419 Tab* current = [self tabAtIndex:i]; | 444 return [self tabAtIndex:static_cast<NSUInteger>(index)]; |
420 DCHECK([current navigationManager]); | |
421 CRWSessionController* sessionController = | |
422 [current navigationManager]->GetSessionController(); | |
423 if ([sessionController.openerId isEqualToString:parentID]) | |
424 return current; | |
425 } | |
426 return nil; | |
427 } | 445 } |
428 | 446 |
429 - (Tab*)lastTabWithOpener:(Tab*)tab { | 447 - (Tab*)lastTabWithOpener:(Tab*)tab { |
430 NSUInteger startIndex = [self indexOfTab:tab]; | 448 int startIndex = _webStateList.GetIndexOfWebState(tab.webState); |
431 if (startIndex == NSNotFound) | 449 if (startIndex == WebStateList::kInvalidIndex) |
432 return nil; | 450 return nil; |
433 // There is at least one tab in the model, because otherwise the above check | |
434 // would have returned. | |
435 NSString* parentID = tab.tabId; | |
436 DCHECK([tab navigationManager]); | |
437 NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex(); | |
438 | 451 |
439 Tab* match = nil; | 452 const int index = _webStateList.GetIndexOfLastWebStateOpenedBy( |
440 // Find the last tab in the first matching 'group'. A 'group' is a set of | 453 tab.webState, startIndex, true); |
441 // tabs whose opener's id and opener's navigation index match. The navigation | 454 if (index == WebStateList::kInvalidIndex) |
442 // index is used in addition to the session id to detect navigations changes | 455 return nil; |
443 // within the same session. | 456 |
444 for (NSUInteger i = startIndex + 1; i < self.count; ++i) { | 457 DCHECK_GE(index, 0); |
445 Tab* tabToCheck = [self tabAtIndex:i]; | 458 return [self tabAtIndex:static_cast<NSUInteger>(index)]; |
446 DCHECK([tabToCheck navigationManager]); | |
447 CRWSessionController* sessionController = | |
448 [tabToCheck navigationManager]->GetSessionController(); | |
449 if ([sessionController.openerId isEqualToString:parentID] && | |
450 sessionController.openerNavigationIndex == parentNavIndex) { | |
451 match = tabToCheck; | |
452 } else if (match) { | |
453 break; | |
454 } | |
455 } | |
456 return match; | |
457 } | 459 } |
458 | 460 |
459 - (Tab*)openerOfTab:(Tab*)tab { | 461 - (Tab*)openerOfTab:(Tab*)tab { |
460 if (![tab navigationManager]) | 462 int index = _webStateList.GetIndexOfWebState(tab.webState); |
| 463 if (index == WebStateList::kInvalidIndex) |
461 return nil; | 464 return nil; |
462 NSString* openerId = [tab navigationManager]->GetSessionController().openerId; | 465 |
463 if (!openerId.length) // Short-circuit if opener is empty. | 466 web::WebState* opener = _webStateList.GetOpenerOfWebStateAt(index); |
464 return nil; | 467 return opener ? LegacyTabHelper::GetTabForWebState(opener) : nil; |
465 for (Tab* iteratedTab in self) { | |
466 if ([iteratedTab.tabId isEqualToString:openerId]) | |
467 return iteratedTab; | |
468 } | |
469 return nil; | |
470 } | 468 } |
471 | 469 |
472 - (Tab*)insertOrUpdateTabWithURL:(const GURL&)URL | 470 - (Tab*)insertOrUpdateTabWithURL:(const GURL&)URL |
473 referrer:(const web::Referrer&)referrer | 471 referrer:(const web::Referrer&)referrer |
474 transition:(ui::PageTransition)transition | 472 transition:(ui::PageTransition)transition |
475 windowName:(NSString*)windowName | 473 windowName:(NSString*)windowName |
476 opener:(Tab*)parentTab | 474 opener:(Tab*)parentTab |
477 openedByDOM:(BOOL)openedByDOM | 475 openedByDOM:(BOOL)openedByDOM |
478 atIndex:(NSUInteger)index | 476 atIndex:(NSUInteger)index |
479 inBackground:(BOOL)inBackground { | 477 inBackground:(BOOL)inBackground { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 atIndex:(NSUInteger)index { | 544 atIndex:(NSUInteger)index { |
547 DCHECK(_browserState); | 545 DCHECK(_browserState); |
548 DCHECK_EQ(webState->GetBrowserState(), _browserState); | 546 DCHECK_EQ(webState->GetBrowserState(), _browserState); |
549 base::scoped_nsobject<Tab> tab( | 547 base::scoped_nsobject<Tab> tab( |
550 [[Tab alloc] initWithWebState:std::move(webState) model:self]); | 548 [[Tab alloc] initWithWebState:std::move(webState) model:self]); |
551 [tab webController].webUsageEnabled = webUsageEnabled_; | 549 [tab webController].webUsageEnabled = webUsageEnabled_; |
552 [self insertTab:tab atIndex:index]; | 550 [self insertTab:tab atIndex:index]; |
553 return tab; | 551 return tab; |
554 } | 552 } |
555 | 553 |
556 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { | 554 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index opener:(Tab*)parentTab { |
557 DCHECK(tab); | 555 DCHECK(tab); |
558 DCHECK(![_tabRetainer containsObject:tab]); | 556 DCHECK(![_tabRetainer containsObject:tab]); |
559 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | 557 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); |
560 | 558 |
561 [_tabRetainer addObject:tab]; | 559 [_tabRetainer addObject:tab]; |
562 _webStateList.InsertWebState(static_cast<int>(index), tab.webState); | 560 _webStateList.InsertWebState(static_cast<int>(index), tab.webState, |
| 561 parentTab.webState); |
563 | 562 |
564 // Persist the session due to a new tab being inserted. If this is a | 563 // Persist the session due to a new tab being inserted. If this is a |
565 // background tab (will not become active), saving now will capture the | 564 // background tab (will not become active), saving now will capture the |
566 // state properly. If it does eventually become active, another save will | 565 // state properly. If it does eventually become active, another save will |
567 // be triggered to properly capture the end result. | 566 // be triggered to properly capture the end result. |
568 [self saveSessionImmediately:NO]; | 567 [self saveSessionImmediately:NO]; |
569 | 568 |
570 ++_newTabCount; | 569 ++_newTabCount; |
571 } | 570 } |
572 | 571 |
| 572 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { |
| 573 [self insertTab:tab atIndex:index opener:GetOpenerForTab(self, tab)]; |
| 574 } |
| 575 |
573 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { | 576 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { |
574 DCHECK([_tabRetainer containsObject:tab]); | 577 DCHECK([_tabRetainer containsObject:tab]); |
575 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX)); | 578 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX)); |
576 int fromIndex = _webStateList.GetIndexOfWebState(tab.webState); | 579 int fromIndex = _webStateList.GetIndexOfWebState(tab.webState); |
577 _webStateList.MoveWebStateAt(fromIndex, static_cast<int>(toIndex)); | 580 _webStateList.MoveWebStateAt(fromIndex, static_cast<int>(toIndex)); |
578 } | 581 } |
579 | 582 |
580 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { | 583 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { |
581 DCHECK([_tabRetainer containsObject:oldTab]); | 584 DCHECK([_tabRetainer containsObject:oldTab]); |
582 DCHECK(![_tabRetainer containsObject:newTab]); | 585 DCHECK(![_tabRetainer containsObject:newTab]); |
583 | 586 |
584 int index = _webStateList.GetIndexOfWebState(oldTab.webState); | 587 int index = _webStateList.GetIndexOfWebState(oldTab.webState); |
585 DCHECK_NE(index, WebStateList::kInvalidIndex); | 588 DCHECK_NE(index, WebStateList::kInvalidIndex); |
586 DCHECK_GE(index, 0); | 589 DCHECK_GE(index, 0); |
587 | 590 |
588 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); | 591 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); |
589 [_tabRetainer removeObject:oldTab]; | 592 [_tabRetainer removeObject:oldTab]; |
590 [_tabRetainer addObject:newTab]; | 593 [_tabRetainer addObject:newTab]; |
591 [newTab setParentTabModel:self]; | 594 [newTab setParentTabModel:self]; |
592 | 595 |
593 _webStateList.ReplaceWebStateAt(index, newTab.webState); | 596 _webStateList.ReplaceWebStateAt(index, newTab.webState, |
| 597 GetOpenerForTab(self, newTab).webState); |
594 | 598 |
595 if (self.currentTab == oldTab) | 599 if (self.currentTab == oldTab) |
596 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; | 600 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; |
597 | 601 |
598 [oldTab setParentTabModel:nil]; | 602 [oldTab setParentTabModel:nil]; |
599 [oldTab close]; | 603 [oldTab close]; |
600 } | 604 } |
601 | 605 |
602 - (void)closeTabAtIndex:(NSUInteger)index { | 606 - (void)closeTabAtIndex:(NSUInteger)index { |
603 DCHECK(index < self.count); | 607 DCHECK(index < self.count); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 index == self.count) { | 886 index == self.count) { |
883 // Also, any tab opened at the end of the TabStrip with a "TYPED" | 887 // Also, any tab opened at the end of the TabStrip with a "TYPED" |
884 // transition inherit group as well. This covers the cases where the user | 888 // transition inherit group as well. This covers the cases where the user |
885 // creates a New Tab (e.g. Ctrl+T, or clicks the New Tab button), or types | 889 // creates a New Tab (e.g. Ctrl+T, or clicks the New Tab button), or types |
886 // in the address bar and presses Alt+Enter. This allows for opening a new | 890 // in the address bar and presses Alt+Enter. This allows for opening a new |
887 // Tab to quickly look up something. When this Tab is closed, the old one | 891 // Tab to quickly look up something. When this Tab is closed, the old one |
888 // is re-selected, not the next-adjacent. | 892 // is re-selected, not the next-adjacent. |
889 // TODO(crbug.com/661988): Make this work. | 893 // TODO(crbug.com/661988): Make this work. |
890 } | 894 } |
891 | 895 |
892 [self insertTab:tab atIndex:index]; | 896 [self insertTab:tab atIndex:index opener:parentTab]; |
893 | 897 |
894 if (!inBackground && _tabUsageRecorder) | 898 if (!inBackground && _tabUsageRecorder) |
895 _tabUsageRecorder->TabCreatedForSelection(tab); | 899 _tabUsageRecorder->TabCreatedForSelection(tab); |
896 | 900 |
897 [[tab webController] loadWithParams:params]; | 901 [[tab webController] loadWithParams:params]; |
898 // Force the page to start loading even if it's in the background. | 902 // Force the page to start loading even if it's in the background. |
899 if (webUsageEnabled_) | 903 if (webUsageEnabled_) |
900 [[tab webController] triggerPendingLoad]; | 904 [[tab webController] triggerPendingLoad]; |
901 NSDictionary* userInfo = @{ | 905 NSDictionary* userInfo = @{ |
902 kTabModelTabKey : tab, | 906 kTabModelTabKey : tab, |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 if (!sessions.count) | 983 if (!sessions.count) |
980 return NO; | 984 return NO; |
981 | 985 |
982 int oldCount = _webStateList.count(); | 986 int oldCount = _webStateList.count(); |
983 DCHECK_GE(oldCount, 0); | 987 DCHECK_GE(oldCount, 0); |
984 | 988 |
985 web::WebState::CreateParams params(_browserState); | 989 web::WebState::CreateParams params(_browserState); |
986 scoped_refptr<web::CertificatePolicyCache> policyCache = | 990 scoped_refptr<web::CertificatePolicyCache> policyCache = |
987 web::BrowserState::GetCertificatePolicyCache(_browserState); | 991 web::BrowserState::GetCertificatePolicyCache(_browserState); |
988 | 992 |
| 993 base::scoped_nsobject<NSMutableArray<Tab*>> restoredTabs( |
| 994 [[NSMutableArray alloc] initWithCapacity:sessions.count]); |
| 995 |
| 996 // Recreate all the restored Tabs and add them to the WebStateList without |
| 997 // any opener-opened relationship (as the n-th restored Tab opener may be |
| 998 // at an index larger than n). Then in a second pass fix the openers. |
989 for (CRWSessionStorage* session in sessions) { | 999 for (CRWSessionStorage* session in sessions) { |
990 std::unique_ptr<web::WebState> webState = | 1000 std::unique_ptr<web::WebState> webState = |
991 web::WebState::Create(params, session); | 1001 web::WebState::Create(params, session); |
992 DCHECK_EQ(webState->GetBrowserState(), _browserState); | 1002 base::scoped_nsobject<Tab> tab( |
993 Tab* tab = | 1003 [[Tab alloc] initWithWebState:std::move(webState) model:self]); |
994 [self insertTabWithWebState:std::move(webState) atIndex:self.count]; | 1004 [tab webController].webUsageEnabled = webUsageEnabled_; |
995 tab.webController.usePlaceholderOverlay = YES; | 1005 [tab webController].usePlaceholderOverlay = YES; |
996 | 1006 |
997 // Restore the CertificatePolicyCache (note that webState is invalid after | 1007 // Restore the CertificatePolicyCache (note that webState is invalid after |
998 // passing it via move semantic to -insertTabWithWebState:atIndex:). | 1008 // passing it via move semantic to -insertTabWithWebState:atIndex:). |
999 UpdateCertificatePolicyCacheFromWebState(policyCache, tab.webState); | 1009 UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]); |
| 1010 [self insertTab:tab atIndex:self.count opener:nil]; |
| 1011 [restoredTabs addObject:tab.get()]; |
1000 } | 1012 } |
| 1013 |
| 1014 DCHECK_EQ(sessions.count, [restoredTabs count]); |
1001 DCHECK_GT(_webStateList.count(), oldCount); | 1015 DCHECK_GT(_webStateList.count(), oldCount); |
1002 | 1016 |
| 1017 // Fix openers now that all Tabs have been restored. Only look for an opener |
| 1018 // Tab in the newly restored Tabs and not in the already open Tabs. |
| 1019 for (int index = oldCount; index < _webStateList.count(); ++index) { |
| 1020 DCHECK_GE(index, oldCount); |
| 1021 NSUInteger tabIndex = static_cast<NSUInteger>(index - oldCount); |
| 1022 Tab* tab = [restoredTabs objectAtIndex:tabIndex]; |
| 1023 Tab* opener = GetOpenerForTab(restoredTabs.get(), tab); |
| 1024 if (opener) { |
| 1025 DCHECK(opener.webState); |
| 1026 _webStateList.SetOpenerOfWebStateAt(index, opener.webState); |
| 1027 } |
| 1028 } |
| 1029 |
1003 // Update the selected tab if there was a selected Tab in the saved session. | 1030 // Update the selected tab if there was a selected Tab in the saved session. |
1004 if (window.selectedIndex != NSNotFound) { | 1031 if (window.selectedIndex != NSNotFound) { |
1005 NSUInteger selectedIndex = window.selectedIndex + oldCount; | 1032 NSUInteger selectedIndex = window.selectedIndex + oldCount; |
1006 DCHECK_LT(selectedIndex, self.count); | 1033 DCHECK_LT(selectedIndex, self.count); |
1007 DCHECK([self tabAtIndex:selectedIndex]); | 1034 DCHECK([self tabAtIndex:selectedIndex]); |
1008 [self changeSelectedTabFrom:_currentTab | 1035 [self changeSelectedTabFrom:_currentTab |
1009 to:[self tabAtIndex:selectedIndex] | 1036 to:[self tabAtIndex:selectedIndex] |
1010 persistState:persistState]; | 1037 persistState:persistState]; |
1011 } | 1038 } |
1012 | 1039 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 initWithWindowName:windowName | 1127 initWithWindowName:windowName |
1101 opener:parentTab | 1128 opener:parentTab |
1102 openedByDOM:NO | 1129 openedByDOM:NO |
1103 model:self | 1130 model:self |
1104 browserState:_browserState]); | 1131 browserState:_browserState]); |
1105 web::NavigationManager::WebLoadParams params(URL); | 1132 web::NavigationManager::WebLoadParams params(URL); |
1106 params.referrer = referrer; | 1133 params.referrer = referrer; |
1107 params.transition_type = ui::PAGE_TRANSITION_TYPED; | 1134 params.transition_type = ui::PAGE_TRANSITION_TYPED; |
1108 [[tab webController] loadWithParams:params]; | 1135 [[tab webController] loadWithParams:params]; |
1109 [tab webController].webUsageEnabled = webUsageEnabled_; | 1136 [tab webController].webUsageEnabled = webUsageEnabled_; |
1110 [self insertTab:tab atIndex:index]; | 1137 [self insertTab:tab atIndex:index opener:parentTab]; |
1111 return tab; | 1138 return tab; |
1112 } | 1139 } |
1113 | 1140 |
1114 @end | 1141 @end |
OLD | NEW |