Commit 49ad9b78 authored by Mohammad Refaat's avatar Mohammad Refaat Committed by Commit Bot

Stop sending TabChange notification for Favicon updates.

TabStripController used didChangeTab TabModelObserver's method
to monitor favicon changes. This was done through TabModelFaviconDriverObserver
which used to forward to Favicon driver notification through didChangeTab.
So to remove the connection between didChangeTab and favicon notification i
changed TabModelFaviconDriverObserver to be WebStateListFaviconDriverObserver
and it will have a bridge to be used to monitor the favicon driver observer.
Also instead of going through TabModel, WebStateListFaviconObserver will be
monitoring the webStateList given at its constructor and Observing each of its'
webstates favicon drivers. TabStripController conform to the bridge protocol and
creates a WebStateListFaviconObserver giving it the webStateList to monitor its
drivers.



Bug: 911350
Change-Id: I19a8523c368aa06dabc80005ffcf65d78c00e07f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1626544
Commit-Queue: Mohammad Refaat <mrefaat@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#663090}
parent d5fa4425
......@@ -44,8 +44,6 @@ source_set("tabs_internal") {
"tab_model.mm",
"tab_model_closing_web_state_observer.h",
"tab_model_closing_web_state_observer.mm",
"tab_model_favicon_driver_observer.h",
"tab_model_favicon_driver_observer.mm",
"tab_model_list.mm",
"tab_model_observers.h",
"tab_model_observers.mm",
......@@ -150,7 +148,6 @@ source_set("tabs_internal") {
source_set("unit_tests") {
testonly = true
sources = [
"tab_model_favicon_driver_observer_unittest.mm",
"tab_model_list_unittest.mm",
"tab_model_unittest.mm",
"tab_title_util_unittest.mm",
......@@ -162,7 +159,6 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/bookmarks/test",
"//components/favicon/ios",
"//components/history/core/browser",
"//components/keyed_service/core",
"//components/search_engines",
......@@ -200,7 +196,6 @@ source_set("unit_tests") {
"//testing/gtest",
"//third_party/ocmock",
"//ui/base",
"//ui/gfx",
]
configs += [ "//build/config/compiler:enable_arc" ]
}
......@@ -41,7 +41,6 @@
#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
#import "ios/chrome/browser/tabs/tab.h"
#import "ios/chrome/browser/tabs/tab_model_closing_web_state_observer.h"
#import "ios/chrome/browser/tabs/tab_model_favicon_driver_observer.h"
#import "ios/chrome/browser/tabs/tab_model_list.h"
#import "ios/chrome/browser/tabs/tab_model_observers.h"
#import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h"
......@@ -365,9 +364,6 @@ void RecordMainFrameNavigationMetric(web::WebState* web_state) {
std::make_unique<WebStateListObserverBridge>(
tabModelSelectedTabObserver));
_webStateListObservers.push_back(
std::make_unique<TabModelFaviconDriverObserver>(self, _observers));
auto webStateListMetricsObserver =
std::make_unique<WebStateListMetricsObserver>();
_webStateListMetricsObserver = webStateListMetricsObserver.get();
......
......@@ -45,6 +45,7 @@
#include "ios/chrome/browser/ui/util/ui_util.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_favicon_driver_observer.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#include "ios/chrome/grit/ios_strings.h"
#import "ios/web/public/web_state/web_state.h"
......@@ -160,6 +161,7 @@ UIColor* BackgroundColor() {
TabStripViewLayoutDelegate,
TabViewDelegate,
WebStateListObserving,
WebStateFaviconDriverObserver,
UIGestureRecognizerDelegate,
UIScrollViewDelegate> {
TabModel* _tabModel;
......@@ -237,6 +239,11 @@ UIColor* BackgroundColor() {
// Bridges C++ WebStateListObserver methods to this TabStripController.
std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
// Bridges FaviconDriverObservers methods to this TabStripController, and
// maintains a FaviconObserver for each all webstates.
std::unique_ptr<WebStateListFaviconDriverObserver>
_webStateListFaviconObserver;
API_AVAILABLE(ios(11.0)) DropAndNavigateInteraction* _buttonNewTabInteraction;
}
......@@ -399,6 +406,9 @@ UIColor* BackgroundColor() {
[_tabModel addObserver:self];
_webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
_tabModel.webStateList->AddObserver(_webStateListObserver.get());
_webStateListFaviconObserver =
std::make_unique<WebStateListFaviconDriverObserver>(
_tabModel.webStateList, self);
_style = style;
_dispatcher = dispatcher;
......@@ -963,15 +973,6 @@ UIColor* BackgroundColor() {
NSUInteger index = [self indexForModelIndex:modelIndex];
TabView* view = [_tabArray objectAtIndex:index];
[view setTitle:tab_util::GetTabTitle(webState)];
[view setFavicon:nil];
favicon::FaviconDriver* faviconDriver =
favicon::WebFaviconDriver::FromWebState(webState);
if (faviconDriver && faviconDriver->FaviconIsValid()) {
gfx::Image favicon = faviconDriver->GetFavicon();
if (!favicon.IsEmpty())
[view setFavicon:favicon.ToUIImage()];
}
if (webState->IsLoading() && !IsVisibleURLNewTabPage(webState))
[view startProgressSpinner];
......@@ -1076,14 +1077,31 @@ UIColor* BackgroundColor() {
[self updateTabCount];
}
// Observer method, WebState replaced in |webStateList|.
- (void)webStateList:(WebStateList*)webStateList
didReplaceWebState:(web::WebState*)oldWebState
withWebState:(web::WebState*)newWebState
atIndex:(int)atIndex {
// TabViews do not hold references to their parent Tabs, so it's safe to treat
// this as a tab change rather than a tab replace.
[self updateTabViewForWebState:newWebState];
#pragma mark -
#pragma mark WebStateFaviconDriverObserver
// Observer method. |webState| got a favicon update.
- (void)faviconDriver:(favicon::FaviconDriver*)driver
didUpdateFaviconForWebState:(web::WebState*)webState {
if (!driver)
return;
int modelIndex = _tabModel.webStateList->GetIndexOfWebState(webState);
if (modelIndex == WebStateList::kInvalidIndex) {
DCHECK(false) << "Received FavIcon update notification for webState that is"
" not in the WebStateList";
return;
}
NSUInteger index = [self indexForModelIndex:modelIndex];
TabView* view = [_tabArray objectAtIndex:index];
[view setFavicon:nil];
if (driver->FaviconIsValid()) {
gfx::Image favicon = driver->GetFavicon();
if (!favicon.IsEmpty())
[view setFavicon:favicon.ToUIImage()];
}
}
#pragma mark -
......
......@@ -11,6 +11,8 @@ source_set("web_state_list") {
"web_state_list.h",
"web_state_list.mm",
"web_state_list_delegate.h",
"web_state_list_favicon_driver_observer.h",
"web_state_list_favicon_driver_observer.mm",
"web_state_list_metrics_observer.h",
"web_state_list_metrics_observer.mm",
"web_state_list_observer.h",
......@@ -26,6 +28,8 @@ source_set("web_state_list") {
]
deps = [
"//base",
"//components/favicon/core",
"//components/favicon/ios",
"//ios/chrome/browser/sessions:serialisation",
"//ios/web",
]
......@@ -51,6 +55,7 @@ source_set("unit_tests") {
sources = [
"active_web_state_observation_forwarder_unittest.mm",
"all_web_state_observation_forwarder_unittest.mm",
"web_state_list_favicon_driver_observer_unittest.mm",
"web_state_list_order_controller_unittest.mm",
"web_state_list_serialization_unittest.mm",
"web_state_list_unittest.mm",
......@@ -60,11 +65,16 @@ source_set("unit_tests") {
":test_support",
":web_state_list",
"//base",
"//components/favicon/ios",
"//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/sessions:serialisation",
"//ios/chrome/browser/web",
"//ios/web",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
"//net",
"//testing/gtest",
"//ui/gfx",
"//url",
]
configs += [ "//build/config/compiler:enable_arc" ]
......
......@@ -2,28 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_TABS_TAB_MODEL_FAVICON_DRIVER_OBSERVER_H_
#define IOS_CHROME_BROWSER_TABS_TAB_MODEL_FAVICON_DRIVER_OBSERVER_H_
#ifndef IOS_CHROME_BROWSER_WEB_STATE_LIST_WEB_STATE_LIST_FAVICON_DRIVER_OBSERVER_H_
#define IOS_CHROME_BROWSER_WEB_STATE_LIST_WEB_STATE_LIST_FAVICON_DRIVER_OBSERVER_H_
#include <map>
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "components/favicon/core/favicon_driver_observer.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer.h"
@class TabModel;
@class TabModelObservers;
class WebStateList;
namespace web {
class WebState;
} // namespace web
// Listen to multiple FaviconDriver for notification that their WebState's
// favicon has changed and forward the notifications to TabModelObservers.
@protocol WebStateFaviconDriverObserver
// Forward the call from |driver| OnFaviconUpdated method.
- (void)faviconDriver:(favicon::FaviconDriver*)driver
didUpdateFaviconForWebState:(web::WebState*)webState;
@end
// Listen to multiple FaviconDrivers for notification that their WebState's
// favicon has changed and forward the notifications to FaviconDriverObserving.
// The class listen to a WebStateList for the creation/replacement/removal
// of WebStates.
class TabModelFaviconDriverObserver : public favicon::FaviconDriverObserver,
public WebStateListObserver {
class WebStateListFaviconDriverObserver
: public WebStateListObserver,
public favicon::FaviconDriverObserver {
public:
TabModelFaviconDriverObserver(TabModel* tab_model,
TabModelObservers* observers);
~TabModelFaviconDriverObserver() override;
WebStateListFaviconDriverObserver(WebStateList* web_state_list,
id<WebStateFaviconDriverObserver> observer);
~WebStateListFaviconDriverObserver() override;
// WebStateListObserver implementation:
void WebStateInsertedAt(WebStateList* web_state_list,
......@@ -46,20 +58,22 @@ class TabModelFaviconDriverObserver : public favicon::FaviconDriverObserver,
const gfx::Image& image) override;
private:
// The owning TabModel. This will be passed to the TabModelObservers
// when forwarding notificaton.
__weak TabModel* tab_model_;
// Observes the FaviconDriver for |web_state| and updates the
// |driver_to_web_state_map_|.
void AddNewWebState(web::WebState* web_state);
// The TabModelObservers to which the FaviconDriver notification are
// forwarded. Should not be nil.
__weak TabModelObservers* observers_;
// The WebStateFaviconDriverObserver to which the FaviconDriver notification
// are forwarded. Should not be nil.
__weak id<WebStateFaviconDriverObserver> favicon_observer_;
// Maps FaviconDriver to the WebState they are attached to. Used
// to find the WebState that should be passed when forwarding the
// notification to TabModelObservers.
std::map<favicon::FaviconDriver*, web::WebState*> driver_to_web_state_map_;
DISALLOW_COPY_AND_ASSIGN(TabModelFaviconDriverObserver);
ScopedObserver<WebStateList, WebStateListObserver> web_state_list_observer_;
DISALLOW_COPY_AND_ASSIGN(WebStateListFaviconDriverObserver);
};
#endif // IOS_CHROME_BROWSER_TABS_TAB_MODEL_FAVICON_DRIVER_OBSERVER_H_
#endif // IOS_CHROME_BROWSER_WEB_STATE_LIST_WEB_STATE_LIST_FAVICON_DRIVER_OBSERVER_H_
......@@ -2,23 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/tabs/tab_model_favicon_driver_observer.h"
#import "ios/chrome/browser/web_state_list/web_state_list_favicon_driver_observer.h"
#include "base/logging.h"
#include "components/favicon/ios/web_favicon_driver.h"
#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
#import "ios/chrome/browser/tabs/tab_model_observers.h"
#include "base/logging.h"
#include "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/web/public/web_state/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
TabModelFaviconDriverObserver::TabModelFaviconDriverObserver(
TabModel* tab_model,
TabModelObservers* observers)
: tab_model_(tab_model), observers_(observers) {}
WebStateListFaviconDriverObserver::WebStateListFaviconDriverObserver(
WebStateList* web_state_list,
id<WebStateFaviconDriverObserver> observer)
: favicon_observer_(observer), web_state_list_observer_(this) {
web_state_list_observer_.Add(web_state_list);
for (int i = 0; i < web_state_list->count(); ++i)
AddNewWebState(web_state_list->GetWebStateAt(i));
}
TabModelFaviconDriverObserver::~TabModelFaviconDriverObserver() {
WebStateListFaviconDriverObserver::~WebStateListFaviconDriverObserver() {
if (!driver_to_web_state_map_.empty()) {
for (const auto& pair : driver_to_web_state_map_) {
favicon::FaviconDriver* driver = pair.first;
......@@ -28,55 +33,45 @@ TabModelFaviconDriverObserver::~TabModelFaviconDriverObserver() {
}
}
void TabModelFaviconDriverObserver::WebStateInsertedAt(
void WebStateListFaviconDriverObserver::WebStateInsertedAt(
WebStateList* web_state_list,
web::WebState* web_state,
int index,
bool activating) {
// Forward to WebStateReplacedAt as an insertion can be simulated as
// replacing a null WebState by a real one.
WebStateReplacedAt(web_state_list, nullptr, web_state, index);
AddNewWebState(web_state);
}
void TabModelFaviconDriverObserver::WebStateReplacedAt(
void WebStateListFaviconDriverObserver::WebStateReplacedAt(
WebStateList* web_state_list,
web::WebState* old_web_state,
web::WebState* new_web_state,
int index) {
if (old_web_state) {
favicon::WebFaviconDriver* driver =
favicon::WebFaviconDriver::FromWebState(old_web_state);
if (driver) {
auto iterator = driver_to_web_state_map_.find(driver);
DCHECK(iterator != driver_to_web_state_map_.end());
DCHECK(iterator->second == old_web_state);
driver_to_web_state_map_.erase(iterator);
driver->RemoveObserver(this);
}
// Forward to WebStateDetachedAt as this is considered a webState removal.
WebStateDetachedAt(web_state_list, old_web_state, index);
}
if (new_web_state) {
favicon::WebFaviconDriver* driver =
favicon::WebFaviconDriver::FromWebState(new_web_state);
if (driver) {
auto iterator = driver_to_web_state_map_.find(driver);
DCHECK(iterator == driver_to_web_state_map_.end());
driver_to_web_state_map_[driver] = new_web_state;
driver->AddObserver(this);
}
AddNewWebState(new_web_state);
}
}
void TabModelFaviconDriverObserver::WebStateDetachedAt(
void WebStateListFaviconDriverObserver::WebStateDetachedAt(
WebStateList* web_state_list,
web::WebState* web_state,
int index) {
// Forward to WebStateReplacedAt as a removal can be simulated as
// replacing a real WebState by a null one.
WebStateReplacedAt(web_state_list, web_state, nullptr, index);
favicon::WebFaviconDriver* driver =
favicon::WebFaviconDriver::FromWebState(web_state);
if (driver) {
auto iterator = driver_to_web_state_map_.find(driver);
DCHECK(iterator != driver_to_web_state_map_.end());
DCHECK(iterator->second == web_state);
driver_to_web_state_map_.erase(iterator);
driver->RemoveObserver(this);
}
}
void TabModelFaviconDriverObserver::OnFaviconUpdated(
void WebStateListFaviconDriverObserver::OnFaviconUpdated(
favicon::FaviconDriver* driver,
favicon::FaviconDriverObserver::NotificationIconType icon_type,
const GURL& icon_url,
......@@ -85,7 +80,18 @@ void TabModelFaviconDriverObserver::OnFaviconUpdated(
auto iterator = driver_to_web_state_map_.find(driver);
DCHECK(iterator != driver_to_web_state_map_.end());
DCHECK(iterator->second);
[favicon_observer_ faviconDriver:driver
didUpdateFaviconForWebState:iterator->second];
}
[observers_ tabModel:tab_model_
didChangeTab:LegacyTabHelper::GetTabForWebState(iterator->second)];
void WebStateListFaviconDriverObserver::AddNewWebState(
web::WebState* web_state) {
favicon::WebFaviconDriver* driver =
favicon::WebFaviconDriver::FromWebState(web_state);
if (driver) {
auto iterator = driver_to_web_state_map_.find(driver);
DCHECK(iterator == driver_to_web_state_map_.end());
driver_to_web_state_map_[driver] = web_state;
driver->AddObserver(this);
}
}
......@@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/tabs/tab_model_favicon_driver_observer.h"
#import "ios/chrome/browser/web_state_list/web_state_list_favicon_driver_observer.h"
#include "base/logging.h"
#include "base/scoped_observer.h"
#include "components/favicon/ios/web_favicon_driver.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
#import "ios/chrome/browser/tabs/tab_model_observers.h"
#import "ios/chrome/browser/web/tab_id_tab_helper.h"
#import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
......@@ -25,38 +21,37 @@
#error "This file requires ARC support."
#endif
@interface TabModelFaviconDriverObserverTestTabModelObserver
: NSObject<TabModelObserver>
@interface FakeWebStateFaviconDriverObserver
: NSObject <WebStateFaviconDriverObserver>
@property(nonatomic, readonly) BOOL tabModelDidChangeTabCalled;
@property(nonatomic, readonly) BOOL didUpdateFaviconCalled;
@end
@implementation TabModelFaviconDriverObserverTestTabModelObserver
@implementation FakeWebStateFaviconDriverObserver
@synthesize tabModelDidChangeTabCalled = _tabModelDidChangeTabCalled;
@synthesize didUpdateFaviconCalled = _didUpdateFaviconCalled;
- (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab {
_tabModelDidChangeTabCalled = YES;
- (void)faviconDriver:(favicon::FaviconDriver*)driver
didUpdateFaviconForWebState:(web::WebState*)webState {
_didUpdateFaviconCalled = YES;
}
@end
class TabModelFaviconDriverObserverTest : public PlatformTest {
class WebStateListFaviconDriverObserverTest : public PlatformTest {
public:
TabModelFaviconDriverObserverTest();
~TabModelFaviconDriverObserverTest() override = default;
WebStateListFaviconDriverObserverTest();
~WebStateListFaviconDriverObserverTest() override = default;
void TearDown() override;
favicon::FaviconDriver* CreateAndInsertWebState();
favicon::FaviconDriver* CreateAndInsertTab();
TabModelFaviconDriverObserver* tab_model_favicon_driver_observer() {
return &tab_model_favicon_driver_observer_;
WebStateListFaviconDriverObserver* web_state_list_favicon_driver_observer() {
return &web_state_list_favicon_driver_observer_;
}
TabModelFaviconDriverObserverTestTabModelObserver* tab_model_observer() {
return tab_model_observer_;
FakeWebStateFaviconDriverObserver* favicon_observer() {
return favicon_observer_;
}
private:
......@@ -64,52 +59,24 @@ class TabModelFaviconDriverObserverTest : public PlatformTest {
std::unique_ptr<ios::ChromeBrowserState> browser_state_;
FakeWebStateListDelegate web_state_list_delegate_;
WebStateList web_state_list_;
FakeWebStateFaviconDriverObserver* favicon_observer_;
WebStateListFaviconDriverObserver web_state_list_favicon_driver_observer_;
TabModelObservers* tab_model_observers_;
TabModelFaviconDriverObserver tab_model_favicon_driver_observer_;
ScopedObserver<WebStateList, WebStateListObserver>
scoped_web_state_list_observer_;
TabModelFaviconDriverObserverTestTabModelObserver* tab_model_observer_;
DISALLOW_COPY_AND_ASSIGN(TabModelFaviconDriverObserverTest);
DISALLOW_COPY_AND_ASSIGN(WebStateListFaviconDriverObserverTest);
};
TabModelFaviconDriverObserverTest::TabModelFaviconDriverObserverTest()
WebStateListFaviconDriverObserverTest::WebStateListFaviconDriverObserverTest()
: browser_state_(TestChromeBrowserState::Builder().Build()),
web_state_list_(&web_state_list_delegate_),
tab_model_observers_([TabModelObservers observers]),
tab_model_favicon_driver_observer_(nil, tab_model_observers_),
scoped_web_state_list_observer_(&tab_model_favicon_driver_observer_) {
scoped_web_state_list_observer_.Add(&web_state_list_);
tab_model_observer_ =
[[TabModelFaviconDriverObserverTestTabModelObserver alloc] init];
[tab_model_observers_ addObserver:tab_model_observer_];
}
favicon_observer_([[FakeWebStateFaviconDriverObserver alloc] init]),
void TabModelFaviconDriverObserverTest::TearDown() {
// Clear pointer to Objective-C instances to ensure they are released
// when the PlatformTest autoreleasepool is cleared.
[tab_model_observers_ removeObserver:tab_model_observer_];
tab_model_observer_ = nil;
// It is safe to drop the last strong reference to TabModelObservers here
// because TabModelFaviconDriverObserver only has a weak reference to it.
tab_model_observers_ = nil;
PlatformTest::TearDown();
}
web_state_list_favicon_driver_observer_(&web_state_list_,
favicon_observer_) {}
favicon::FaviconDriver*
TabModelFaviconDriverObserverTest::CreateAndInsertTab() {
WebStateListFaviconDriverObserverTest::CreateAndInsertWebState() {
std::unique_ptr<web::WebState> web_state =
web::WebState::Create(web::WebState::CreateParams(browser_state_.get()));
// TODO(crbug.com/783776): once the API has been changed to use WebState
// instead of Tab, then we can remove the creation of the LegacyTabHelper
// and TabIdTabHelper.
TabIdTabHelper::CreateForWebState(web_state.get());
LegacyTabHelper::CreateForWebState(web_state.get());
favicon::WebFaviconDriver::CreateForWebState(web_state.get(),
/*favicon_service=*/nullptr);
......@@ -123,14 +90,16 @@ TabModelFaviconDriverObserverTest::CreateAndInsertTab() {
return favicon_driver;
}
TEST_F(TabModelFaviconDriverObserverTest, OnFaviconUpdated) {
ASSERT_FALSE([tab_model_observer() tabModelDidChangeTabCalled]);
// Tests that calls to OnFaviconUpdated are forwarded correctly to
// WebStateFaviconDriverObserver.
TEST_F(WebStateListFaviconDriverObserverTest, OnFaviconUpdated) {
ASSERT_FALSE([favicon_observer() didUpdateFaviconCalled]);
favicon::FaviconDriver* favicon_driver = CreateAndInsertTab();
EXPECT_FALSE([tab_model_observer() tabModelDidChangeTabCalled]);
favicon::FaviconDriver* favicon_driver = CreateAndInsertWebState();
ASSERT_FALSE([favicon_observer() didUpdateFaviconCalled]);
tab_model_favicon_driver_observer()->OnFaviconUpdated(
web_state_list_favicon_driver_observer()->OnFaviconUpdated(
favicon_driver, favicon::FaviconDriverObserver::TOUCH_LARGEST, GURL(),
true, gfx::Image());
EXPECT_TRUE([tab_model_observer() tabModelDidChangeTabCalled]);
ASSERT_TRUE([favicon_observer() didUpdateFaviconCalled]);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment