| Index: ios/chrome/browser/dom_distiller/web_state_pool_impl.mm
|
| diff --git a/ios/chrome/browser/dom_distiller/web_state_pool_impl.mm b/ios/chrome/browser/dom_distiller/web_state_pool_impl.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b1a6872b5b493157a7265606d0f49858ffeb4ce3
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/dom_distiller/web_state_pool_impl.mm
|
| @@ -0,0 +1,142 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ios/chrome/browser/dom_distiller/web_state_pool_impl.h"
|
| +
|
| +#include "components/favicon/ios/web_favicon_driver.h"
|
| +#include "components/keyed_service/core/service_access_type.h"
|
| +#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
|
| +#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
|
| +#include "ios/chrome/browser/favicon/favicon_service_factory.h"
|
| +#include "ios/chrome/browser/history/history_service_factory.h"
|
| +
|
| +namespace {
|
| +// Number of WebState in the pool.
|
| +const int kMaxNumberOfWebState = 10;
|
| +// Maximum delay before timeout.
|
| +const int kMaxDelayFavicon = 10;
|
| +// Number of second before the WebState is returned to the pool after the
|
| +// reception of the favicon.
|
| +const int kDelayFavicon = 1;
|
| +}
|
| +
|
| +namespace dom_distiller {
|
| +
|
| +WebStatePoolImpl::WebStatePoolImpl(web::BrowserState* browser_state)
|
| + : browser_state_(browser_state),
|
| + unique_web_states_(kMaxNumberOfWebState),
|
| + web_states_(kMaxNumberOfWebState),
|
| + weak_ptr_factory_(this) {}
|
| +WebStatePoolImpl::~WebStatePoolImpl() {}
|
| +
|
| +void WebStatePoolImpl::OnFaviconUpdated(
|
| + favicon::FaviconDriver* favicon_driver,
|
| + favicon::FaviconDriverObserver::NotificationIconType notification_icon_type,
|
| + const GURL& icon_url,
|
| + bool icon_url_changed,
|
| + const gfx::Image& image) {
|
| + dispatch_after(
|
| + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayFavicon * NSEC_PER_SEC)),
|
| + dispatch_get_main_queue(), ^{
|
| + OnFaviconDownloaded(favicon_driver);
|
| + });
|
| +}
|
| +
|
| +void WebStatePoolImpl::RequestWebState(WebStatePoolDelegate* delegate) {
|
| + int available_web_state = GetFirstWebStateAvailable();
|
| + if (available_web_state == -1) {
|
| + pending_delegates_.push_back(delegate);
|
| + return;
|
| + }
|
| +
|
| + if (!web_states_[available_web_state]) {
|
| + // Lazily initialize WebState.
|
| + CreateWebState(available_web_state);
|
| + }
|
| + web::WebState* web_state = web_states_[available_web_state];
|
| + favicon::WebFaviconDriver* favicon_driver =
|
| + favicon::WebFaviconDriver::FromWebState(web_state);
|
| + favicon_web_state_.insert(
|
| + std::make_pair(favicon_driver, available_web_state));
|
| + registered_web_state_.insert(std::make_pair(web_state, available_web_state));
|
| +
|
| + delegate->OnWebStateAvailable(web_state);
|
| +}
|
| +
|
| +void WebStatePoolImpl::CreateWebState(int web_state_index) {
|
| + const web::WebState::CreateParams web_state_create_params(browser_state_);
|
| + std::unique_ptr<web::WebState> web_state_unique =
|
| + web::WebState::Create(web_state_create_params);
|
| + web::WebState* web_state = web_state_unique.get();
|
| + unique_web_states_[web_state_index] = std::move(web_state_unique);
|
| + web_states_[web_state_index] = web_state;
|
| +
|
| + ios::ChromeBrowserState* original_browser_state =
|
| + ios::ChromeBrowserState::FromBrowserState(browser_state_);
|
| +
|
| + favicon::WebFaviconDriver::CreateForWebState(
|
| + web_state,
|
| + ios::FaviconServiceFactory::GetForBrowserState(
|
| + original_browser_state, ServiceAccessType::EXPLICIT_ACCESS),
|
| + ios::HistoryServiceFactory::GetForBrowserState(
|
| + original_browser_state, ServiceAccessType::EXPLICIT_ACCESS),
|
| + ios::BookmarkModelFactory::GetForBrowserState(original_browser_state));
|
| + favicon::WebFaviconDriver* favicon_driver =
|
| + favicon::WebFaviconDriver::FromWebState(web_state);
|
| + favicon_driver->AddObserver(this);
|
| +}
|
| +
|
| +void WebStatePoolImpl::ReturnWebState(web::WebState* web_state) {
|
| + favicon::WebFaviconDriver* favicon_driver =
|
| + favicon::WebFaviconDriver::FromWebState(web_state);
|
| +
|
| + base::WeakPtr<WebStatePoolImpl> weak_this = weak_ptr_factory_.GetWeakPtr();
|
| + dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
|
| + (int64_t)(kMaxDelayFavicon * NSEC_PER_SEC)),
|
| + dispatch_get_main_queue(), ^{
|
| + WebStatePoolImpl* web_state_pool = weak_this.get();
|
| + if (web_state_pool)
|
| + web_state_pool->OnFaviconDownloaded(favicon_driver);
|
| + });
|
| + registered_web_state_.erase(web_state);
|
| +
|
| + // The favicon might have been downloaded before the WebState is returned.
|
| + while (GetFirstWebStateAvailable() != -1) {
|
| + RequestWebState(pending_delegates_.front());
|
| + pending_delegates_.pop_front();
|
| + }
|
| +}
|
| +
|
| +void WebStatePoolImpl::OnFaviconDownloaded(favicon::FaviconDriver* driver) {
|
| + favicon_web_state_.erase(driver);
|
| +
|
| + while (GetFirstWebStateAvailable() != -1) {
|
| + RequestWebState(pending_delegates_.front());
|
| + pending_delegates_.pop_front();
|
| + }
|
| +}
|
| +
|
| +int WebStatePoolImpl::GetFirstWebStateAvailable() {
|
| + bool used_web_state[kMaxNumberOfWebState] = {false};
|
| +
|
| + for (auto it = favicon_web_state_.begin(); it != favicon_web_state_.end();
|
| + it++) {
|
| + // Check the WebState used to download favicon.
|
| + used_web_state[it->second] = true;
|
| + }
|
| + for (auto it = registered_web_state_.begin();
|
| + it != registered_web_state_.end(); it++) {
|
| + // Check the WebState used by delegates.
|
| + used_web_state[it->second] = true;
|
| + }
|
| +
|
| + for (int index = 0; index < kMaxNumberOfWebState; index++) {
|
| + if (!used_web_state[index]) {
|
| + return index;
|
| + }
|
| + }
|
| + return -1;
|
| +}
|
| +
|
| +} // namespace dom_distiller
|
|
|