| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #include "chrome/browser/browser.h" | 5 #include "chrome/browser/browser.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <shellapi.h> | 8 #include <shellapi.h> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 // We don't need to process INVALIDATE_STATE, since that's not visible. | 515 // We don't need to process INVALIDATE_STATE, since that's not visible. |
| 516 } | 516 } |
| 517 | 517 |
| 518 scheduled_updates_.clear(); | 518 scheduled_updates_.clear(); |
| 519 } | 519 } |
| 520 | 520 |
| 521 //////////////////////////////////////////////////////////////////////////////// | 521 //////////////////////////////////////////////////////////////////////////////// |
| 522 // TabContentsDelegate | 522 // TabContentsDelegate |
| 523 | 523 |
| 524 void Browser::OpenURLFromTab(TabContents* source, | 524 void Browser::OpenURLFromTab(TabContents* source, |
| 525 const GURL& url, | 525 const GURL& url, const GURL& referrer, |
| 526 WindowOpenDisposition disposition, | 526 WindowOpenDisposition disposition, |
| 527 PageTransition::Type transition) { | 527 PageTransition::Type transition) { |
| 528 // No code for these yet | 528 // No code for these yet |
| 529 DCHECK((disposition != NEW_POPUP) && (disposition != SAVE_TO_DISK)); | 529 DCHECK((disposition != NEW_POPUP) && (disposition != SAVE_TO_DISK)); |
| 530 | 530 |
| 531 TabContents* current_tab = source ? source : GetSelectedTabContents(); | 531 TabContents* current_tab = source ? source : GetSelectedTabContents(); |
| 532 bool source_tab_was_frontmost = (current_tab == GetSelectedTabContents()); | 532 bool source_tab_was_frontmost = (current_tab == GetSelectedTabContents()); |
| 533 TabContents* new_contents = NULL; | 533 TabContents* new_contents = NULL; |
| 534 | 534 |
| 535 // If the URL is part of the same web site, then load it in the same | 535 // If the URL is part of the same web site, then load it in the same |
| (...skipping 28 matching lines...) Expand all Loading... |
| 564 } | 564 } |
| 565 | 565 |
| 566 Browser* b = GetOrCreateTabbedBrowser(); | 566 Browser* b = GetOrCreateTabbedBrowser(); |
| 567 DCHECK(b); | 567 DCHECK(b); |
| 568 | 568 |
| 569 // If we have just created a new browser window, make sure we select the | 569 // If we have just created a new browser window, make sure we select the |
| 570 // tab. | 570 // tab. |
| 571 if (b->tab_count() == 0 && disposition == NEW_BACKGROUND_TAB) | 571 if (b->tab_count() == 0 && disposition == NEW_BACKGROUND_TAB) |
| 572 disposition = NEW_FOREGROUND_TAB; | 572 disposition = NEW_FOREGROUND_TAB; |
| 573 | 573 |
| 574 b->OpenURL(url, disposition, transition); | 574 b->OpenURL(url, referrer, disposition, transition); |
| 575 b->Show(); | 575 b->Show(); |
| 576 b->MoveToFront(true); | 576 b->MoveToFront(true); |
| 577 return; | 577 return; |
| 578 } | 578 } |
| 579 | 579 |
| 580 if (profile_->IsOffTheRecord() && disposition == OFF_THE_RECORD) | 580 if (profile_->IsOffTheRecord() && disposition == OFF_THE_RECORD) |
| 581 disposition = NEW_FOREGROUND_TAB; | 581 disposition = NEW_FOREGROUND_TAB; |
| 582 | 582 |
| 583 if (disposition == NEW_WINDOW) { | 583 if (disposition == NEW_WINDOW) { |
| 584 Browser* new_browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile_, | 584 Browser* new_browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile_, |
| 585 BrowserType::TABBED_BROWSER, L""); | 585 BrowserType::TABBED_BROWSER, L""); |
| 586 new_contents = new_browser->AddTabWithURL(url, transition, true, instance); | 586 new_contents = new_browser->AddTabWithURL(url, referrer, transition, true, |
| 587 instance); |
| 587 new_browser->Show(); | 588 new_browser->Show(); |
| 588 } else if ((disposition == CURRENT_TAB) && current_tab) { | 589 } else if ((disposition == CURRENT_TAB) && current_tab) { |
| 589 if (transition == PageTransition::TYPED || | 590 if (transition == PageTransition::TYPED || |
| 590 transition == PageTransition::AUTO_BOOKMARK || | 591 transition == PageTransition::AUTO_BOOKMARK || |
| 591 transition == PageTransition::GENERATED || | 592 transition == PageTransition::GENERATED || |
| 592 transition == PageTransition::START_PAGE) { | 593 transition == PageTransition::START_PAGE) { |
| 593 // Don't forget the openers if this tab is a New Tab page opened at the | 594 // Don't forget the openers if this tab is a New Tab page opened at the |
| 594 // end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one | 595 // end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one |
| 595 // navigation of one of these transition types before resetting the | 596 // navigation of one of these transition types before resetting the |
| 596 // opener relationships (this allows for the use case of opening a new | 597 // opener relationships (this allows for the use case of opening a new |
| (...skipping 11 matching lines...) Expand all Loading... |
| 608 // If the user navigates the current tab to another page in any way | 609 // If the user navigates the current tab to another page in any way |
| 609 // other than by clicking a link, we want to pro-actively forget all | 610 // other than by clicking a link, we want to pro-actively forget all |
| 610 // TabStrip opener relationships since we assume they're beginning a | 611 // TabStrip opener relationships since we assume they're beginning a |
| 611 // different task by reusing the current tab. | 612 // different task by reusing the current tab. |
| 612 tabstrip_model_.ForgetAllOpeners(); | 613 tabstrip_model_.ForgetAllOpeners(); |
| 613 // In this specific case we also want to reset the group relationship, | 614 // In this specific case we also want to reset the group relationship, |
| 614 // since it is now technically invalid. | 615 // since it is now technically invalid. |
| 615 tabstrip_model_.ForgetGroup(current_tab); | 616 tabstrip_model_.ForgetGroup(current_tab); |
| 616 } | 617 } |
| 617 } | 618 } |
| 618 current_tab->controller()->LoadURL(url, transition); | 619 current_tab->controller()->LoadURL(url, referrer, transition); |
| 619 // The TabContents might have changed as part of the navigation (ex: new tab | 620 // The TabContents might have changed as part of the navigation (ex: new tab |
| 620 // page can become WebContents). | 621 // page can become WebContents). |
| 621 new_contents = current_tab->controller()->active_contents(); | 622 new_contents = current_tab->controller()->active_contents(); |
| 622 GetStatusBubble()->Hide(); | 623 GetStatusBubble()->Hide(); |
| 623 | 624 |
| 624 // Synchronously update the location bar. This allows us to immediately | 625 // Synchronously update the location bar. This allows us to immediately |
| 625 // have the URL bar update when the user types something, rather than | 626 // have the URL bar update when the user types something, rather than |
| 626 // going through the normal system of ScheduleUIUpdate which has a delay. | 627 // going through the normal system of ScheduleUIUpdate which has a delay. |
| 627 UpdateToolBar(false); | 628 UpdateToolBar(false); |
| 628 } else if (disposition == OFF_THE_RECORD) { | 629 } else if (disposition == OFF_THE_RECORD) { |
| 629 OpenURLOffTheRecord(profile_, url); | 630 OpenURLOffTheRecord(profile_, url); |
| 630 return; | 631 return; |
| 631 } else if (disposition != SUPPRESS_OPEN) { | 632 } else if (disposition != SUPPRESS_OPEN) { |
| 632 new_contents = | 633 new_contents = |
| 633 AddTabWithURL(url, transition, disposition != NEW_BACKGROUND_TAB, | 634 AddTabWithURL(url, referrer, transition, |
| 634 instance); | 635 disposition != NEW_BACKGROUND_TAB, instance); |
| 635 } | 636 } |
| 636 | 637 |
| 637 if (disposition != NEW_BACKGROUND_TAB && source_tab_was_frontmost) { | 638 if (disposition != NEW_BACKGROUND_TAB && source_tab_was_frontmost) { |
| 638 // Give the focus to the newly navigated tab, if the source tab was | 639 // Give the focus to the newly navigated tab, if the source tab was |
| 639 // front-most. | 640 // front-most. |
| 640 new_contents->Focus(); | 641 new_contents->Focus(); |
| 641 } | 642 } |
| 642 } | 643 } |
| 643 | 644 |
| 644 void Browser::NavigationStateChanged(const TabContents* source, | 645 void Browser::NavigationStateChanged(const TabContents* source, |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1201 SessionService* session_service = profile()->GetSessionService(); | 1202 SessionService* session_service = profile()->GetSessionService(); |
| 1202 if (session_service) | 1203 if (session_service) |
| 1203 session_service->WindowClosing(session_id()); | 1204 session_service->WindowClosing(session_id()); |
| 1204 | 1205 |
| 1205 CloseAllTabs(); | 1206 CloseAllTabs(); |
| 1206 } | 1207 } |
| 1207 | 1208 |
| 1208 // Tab Creation Functions | 1209 // Tab Creation Functions |
| 1209 | 1210 |
| 1210 TabContents* Browser::AddTabWithURL( | 1211 TabContents* Browser::AddTabWithURL( |
| 1211 const GURL& url, PageTransition::Type transition, bool foreground, | 1212 const GURL& url, const GURL& referrer, PageTransition::Type transition, |
| 1212 SiteInstance* instance) { | 1213 bool foreground, SiteInstance* instance) { |
| 1213 if (type_ == BrowserType::APPLICATION && tabstrip_model_.count() == 1) { | 1214 if (type_ == BrowserType::APPLICATION && tabstrip_model_.count() == 1) { |
| 1214 NOTREACHED() << "Cannot add a tab in a mono tab application."; | 1215 NOTREACHED() << "Cannot add a tab in a mono tab application."; |
| 1215 return NULL; | 1216 return NULL; |
| 1216 } | 1217 } |
| 1217 | 1218 |
| 1218 GURL url_to_load = url; | 1219 GURL url_to_load = url; |
| 1219 if (url_to_load.is_empty()) | 1220 if (url_to_load.is_empty()) |
| 1220 url_to_load = GetHomePage(); | 1221 url_to_load = GetHomePage(); |
| 1221 TabContents* contents = | 1222 TabContents* contents = |
| 1222 CreateTabContentsForURL(url_to_load, profile_, transition, false, | 1223 CreateTabContentsForURL(url_to_load, referrer, profile_, transition, |
| 1223 instance); | 1224 false, instance); |
| 1224 tabstrip_model_.AddTabContents(contents, -1, transition, foreground); | 1225 tabstrip_model_.AddTabContents(contents, -1, transition, foreground); |
| 1225 // By default, content believes it is not hidden. When adding contents | 1226 // By default, content believes it is not hidden. When adding contents |
| 1226 // in the background, tell it that it's hidden. | 1227 // in the background, tell it that it's hidden. |
| 1227 if (!foreground) | 1228 if (!foreground) |
| 1228 contents->WasHidden(); | 1229 contents->WasHidden(); |
| 1229 return contents; | 1230 return contents; |
| 1230 } | 1231 } |
| 1231 | 1232 |
| 1232 TabContents* Browser::AddWebApplicationTab(Profile* profile, | 1233 TabContents* Browser::AddWebApplicationTab(Profile* profile, |
| 1233 WebApp* web_app, | 1234 WebApp* web_app, |
| 1234 bool lazy) { | 1235 bool lazy) { |
| 1235 DCHECK(web_app); | 1236 DCHECK(web_app); |
| 1236 | 1237 |
| 1237 // TODO(acw): Do we need an "application launched" transition type? | 1238 // TODO(acw): Do we need an "application launched" transition type? |
| 1238 // TODO(creis): Should we reuse the current instance (ie. process) here? | 1239 // TODO(creis): Should we reuse the current instance (ie. process) here? |
| 1239 TabContents* contents = | 1240 TabContents* contents = |
| 1240 CreateTabContentsForURL(web_app->url(), profile, PageTransition::LINK, | 1241 CreateTabContentsForURL(web_app->url(), GURL(), profile, |
| 1241 lazy, NULL); | 1242 PageTransition::LINK, lazy, NULL); |
| 1242 if (contents->AsWebContents()) | 1243 if (contents->AsWebContents()) |
| 1243 contents->AsWebContents()->SetWebApp(web_app); | 1244 contents->AsWebContents()->SetWebApp(web_app); |
| 1244 | 1245 |
| 1245 if (lazy) { | 1246 if (lazy) { |
| 1246 contents->controller()->LoadURLLazily( | 1247 contents->controller()->LoadURLLazily( |
| 1247 web_app->url(), PageTransition::LINK, web_app->name(), NULL); | 1248 web_app->url(), GURL(), PageTransition::LINK, web_app->name(), NULL); |
| 1248 } | 1249 } |
| 1249 tabstrip_model_.AddTabContents(contents, -1, PageTransition::LINK, !lazy); | 1250 tabstrip_model_.AddTabContents(contents, -1, PageTransition::LINK, !lazy); |
| 1250 return contents; | 1251 return contents; |
| 1251 } | 1252 } |
| 1252 | 1253 |
| 1253 TabContents* Browser::AddTabWithNavigationController( | 1254 TabContents* Browser::AddTabWithNavigationController( |
| 1254 NavigationController* ctrl, PageTransition::Type type) { | 1255 NavigationController* ctrl, PageTransition::Type type) { |
| 1255 TabContents* tc = ctrl->active_contents(); | 1256 TabContents* tc = ctrl->active_contents(); |
| 1256 tabstrip_model_.AddTabContents(tc, -1, type, true); | 1257 tabstrip_model_.AddTabContents(tc, -1, type, true); |
| 1257 return tc; | 1258 return tc; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1324 if (BrowserList::GetBrowserCountForType(profile_, | 1325 if (BrowserList::GetBrowserCountForType(profile_, |
| 1325 BrowserType::TABBED_BROWSER) > 1 || | 1326 BrowserType::TABBED_BROWSER) > 1 || |
| 1326 tab_count() > 1) | 1327 tab_count() > 1) |
| 1327 result |= TAB_TEAROFF_ACTION; | 1328 result |= TAB_TEAROFF_ACTION; |
| 1328 if (tab_count() > 1) | 1329 if (tab_count() > 1) |
| 1329 result |= TAB_MOVE_ACTION; | 1330 result |= TAB_MOVE_ACTION; |
| 1330 return result; | 1331 return result; |
| 1331 } | 1332 } |
| 1332 | 1333 |
| 1333 TabContents* Browser::CreateTabContentsForURL( | 1334 TabContents* Browser::CreateTabContentsForURL( |
| 1334 const GURL& url, Profile* profile, PageTransition::Type transition, | 1335 const GURL& url, const GURL& referrer, Profile* profile, |
| 1335 bool defer_load, SiteInstance* instance) const { | 1336 PageTransition::Type transition, bool defer_load, |
| 1337 SiteInstance* instance) const { |
| 1336 // Create an appropriate tab contents. | 1338 // Create an appropriate tab contents. |
| 1337 GURL real_url = url; | 1339 GURL real_url = url; |
| 1338 TabContentsType type = TabContents::TypeForURL(&real_url); | 1340 TabContentsType type = TabContents::TypeForURL(&real_url); |
| 1339 DCHECK(type != TAB_CONTENTS_UNKNOWN_TYPE); | 1341 DCHECK(type != TAB_CONTENTS_UNKNOWN_TYPE); |
| 1340 | 1342 |
| 1341 TabContents* contents = | 1343 TabContents* contents = |
| 1342 TabContents::CreateWithType(type, GetTopLevelHWND(), profile, instance); | 1344 TabContents::CreateWithType(type, GetTopLevelHWND(), profile, instance); |
| 1343 contents->SetupController(profile); | 1345 contents->SetupController(profile); |
| 1344 | 1346 |
| 1345 if (!defer_load) { | 1347 if (!defer_load) { |
| 1346 // Load the initial URL before adding the new tab contents to the tab strip | 1348 // Load the initial URL before adding the new tab contents to the tab strip |
| 1347 // so that the tab contents has navigation state. | 1349 // so that the tab contents has navigation state. |
| 1348 contents->controller()->LoadURL(url, transition); | 1350 contents->controller()->LoadURL(url, referrer, transition); |
| 1349 } | 1351 } |
| 1350 | 1352 |
| 1351 return contents; | 1353 return contents; |
| 1352 } | 1354 } |
| 1353 | 1355 |
| 1354 void Browser::ShowApplicationMenu(const gfx::Point& p) { | 1356 void Browser::ShowApplicationMenu(const gfx::Point& p) { |
| 1355 if (!window_) | 1357 if (!window_) |
| 1356 return; | 1358 return; |
| 1357 | 1359 |
| 1358 HWND hwnd = reinterpret_cast<HWND>(window_->GetPlatformID()); | 1360 HWND hwnd = reinterpret_cast<HWND>(window_->GetPlatformID()); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1606 TabContents* tc; | 1608 TabContents* tc; |
| 1607 for (i = 0, c = tabstrip_model_.count(); i < c; ++i) { | 1609 for (i = 0, c = tabstrip_model_.count(); i < c; ++i) { |
| 1608 tc = tabstrip_model_.GetTabContentsAt(i); | 1610 tc = tabstrip_model_.GetTabContentsAt(i); |
| 1609 if (tc->type() == TAB_CONTENTS_NATIVE_UI && | 1611 if (tc->type() == TAB_CONTENTS_NATIVE_UI && |
| 1610 tc->GetURL() == url) { | 1612 tc->GetURL() == url) { |
| 1611 tabstrip_model_.SelectTabContentsAt(i, false); | 1613 tabstrip_model_.SelectTabContentsAt(i, false); |
| 1612 return; | 1614 return; |
| 1613 } | 1615 } |
| 1614 } | 1616 } |
| 1615 | 1617 |
| 1616 TabContents* contents = CreateTabContentsForURL(url, profile_, | 1618 TabContents* contents = CreateTabContentsForURL(url, GURL(), profile_, |
| 1617 PageTransition::LINK, false, | 1619 PageTransition::LINK, false, |
| 1618 NULL); | 1620 NULL); |
| 1619 AddNewContents(NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true); | 1621 AddNewContents(NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true); |
| 1620 } | 1622 } |
| 1621 | 1623 |
| 1622 NavigationController* Browser::BuildRestoredNavigationController( | 1624 NavigationController* Browser::BuildRestoredNavigationController( |
| 1623 const std::vector<TabNavigation>& navigations, | 1625 const std::vector<TabNavigation>& navigations, |
| 1624 int selected_navigation) { | 1626 int selected_navigation) { |
| 1625 if (!navigations.empty()) { | 1627 if (!navigations.empty()) { |
| 1626 DCHECK(selected_navigation >= 0 && | 1628 DCHECK(selected_navigation >= 0 && |
| 1627 selected_navigation < static_cast<int>(navigations.size())); | 1629 selected_navigation < static_cast<int>(navigations.size())); |
| 1628 // We should have a valid URL, if we don't fall back to the default. | 1630 // We should have a valid URL, if we don't fall back to the default. |
| 1629 GURL url = navigations[selected_navigation].url; | 1631 GURL url = navigations[selected_navigation].url; |
| 1630 if (url.is_empty()) | 1632 if (url.is_empty()) |
| 1631 url = GetHomePage(); | 1633 url = GetHomePage(); |
| 1632 | 1634 |
| 1633 // Create a NavigationController. This constructor creates the appropriate | 1635 // Create a NavigationController. This constructor creates the appropriate |
| 1634 // set of TabContents. | 1636 // set of TabContents. |
| 1635 return new NavigationController( | 1637 return new NavigationController( |
| 1636 profile_, navigations, selected_navigation, GetTopLevelHWND()); | 1638 profile_, navigations, selected_navigation, GetTopLevelHWND()); |
| 1637 } else { | 1639 } else { |
| 1638 // No navigations. Create a tab with about:blank. | 1640 // No navigations. Create a tab with about:blank. |
| 1639 TabContents* contents = | 1641 TabContents* contents = |
| 1640 CreateTabContentsForURL(GURL("about:blank"), profile_, | 1642 CreateTabContentsForURL(GURL("about:blank"), GURL(), profile_, |
| 1641 PageTransition::START_PAGE, false, NULL); | 1643 PageTransition::START_PAGE, false, NULL); |
| 1642 return new NavigationController(contents, profile_); | 1644 return new NavigationController(contents, profile_); |
| 1643 } | 1645 } |
| 1644 } | 1646 } |
| 1645 | 1647 |
| 1646 // static | 1648 // static |
| 1647 void Browser::OpenURLOffTheRecord(Profile* profile, const GURL& url) { | 1649 void Browser::OpenURLOffTheRecord(Profile* profile, const GURL& url) { |
| 1648 Profile* off_the_record_profile = profile->GetOffTheRecordProfile(); | 1650 Profile* off_the_record_profile = profile->GetOffTheRecordProfile(); |
| 1649 Browser* browser = BrowserList::FindBrowserWithType( | 1651 Browser* browser = BrowserList::FindBrowserWithType( |
| 1650 off_the_record_profile, BrowserType::TABBED_BROWSER); | 1652 off_the_record_profile, BrowserType::TABBED_BROWSER); |
| 1651 if (browser == NULL) { | 1653 if (browser == NULL) { |
| 1652 browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, off_the_record_profile, | 1654 browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, off_the_record_profile, |
| 1653 BrowserType::TABBED_BROWSER, L""); | 1655 BrowserType::TABBED_BROWSER, L""); |
| 1654 } | 1656 } |
| 1655 browser->AddTabWithURL(url, PageTransition::LINK, true, NULL); | 1657 // TODO(eroman): should we have referrer here? |
| 1658 browser->AddTabWithURL(url, GURL(), PageTransition::LINK, true, NULL); |
| 1656 browser->Show(); | 1659 browser->Show(); |
| 1657 browser->MoveToFront(true); | 1660 browser->MoveToFront(true); |
| 1658 } | 1661 } |
| 1659 | 1662 |
| 1660 // static | 1663 // static |
| 1661 std::wstring Browser::ComputePopupTitle(const GURL& url, | 1664 std::wstring Browser::ComputePopupTitle(const GURL& url, |
| 1662 const std::wstring& title) { | 1665 const std::wstring& title) { |
| 1663 DCHECK(!g_browser_process->IsUsingNewFrames()); | 1666 DCHECK(!g_browser_process->IsUsingNewFrames()); |
| 1664 std::wstring result(title); | 1667 std::wstring result(title); |
| 1665 FormatTitleForDisplay(&result); | 1668 FormatTitleForDisplay(&result); |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1862 void Browser::FormatTitleForDisplay(std::wstring* title) { | 1865 void Browser::FormatTitleForDisplay(std::wstring* title) { |
| 1863 size_t current_index = 0; | 1866 size_t current_index = 0; |
| 1864 size_t match_index; | 1867 size_t match_index; |
| 1865 while ((match_index = title->find(L'\n', current_index)) != | 1868 while ((match_index = title->find(L'\n', current_index)) != |
| 1866 std::wstring::npos) { | 1869 std::wstring::npos) { |
| 1867 title->replace(match_index, 1, L""); | 1870 title->replace(match_index, 1, L""); |
| 1868 current_index = match_index; | 1871 current_index = match_index; |
| 1869 } | 1872 } |
| 1870 } | 1873 } |
| 1871 | 1874 |
| OLD | NEW |