OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 #include "ios/chrome/browser/dom_distiller/web_state_pool_impl.h" |
| 6 |
| 7 #include "components/favicon/ios/web_favicon_driver.h" |
| 8 #include "components/keyed_service/core/service_access_type.h" |
| 9 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" |
| 10 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 11 #include "ios/chrome/browser/favicon/favicon_service_factory.h" |
| 12 #include "ios/chrome/browser/history/history_service_factory.h" |
| 13 |
| 14 namespace { |
| 15 // Number of WebState in the pool. |
| 16 const int kMaxNumberOfWebState = 10; |
| 17 // Maximum delay before timeout. |
| 18 const int kMaxDelayFavicon = 10; |
| 19 // Number of second before the WebState is returned to the pool after the |
| 20 // reception of the favicon. |
| 21 const int kDelayFavicon = 1; |
| 22 } |
| 23 |
| 24 namespace dom_distiller { |
| 25 |
| 26 WebStatePoolImpl::WebStatePoolImpl(web::BrowserState* browser_state) |
| 27 : browser_state_(browser_state), |
| 28 unique_web_states_(kMaxNumberOfWebState), |
| 29 web_states_(kMaxNumberOfWebState), |
| 30 weak_ptr_factory_(this) {} |
| 31 WebStatePoolImpl::~WebStatePoolImpl() {} |
| 32 |
| 33 void WebStatePoolImpl::OnFaviconUpdated( |
| 34 favicon::FaviconDriver* favicon_driver, |
| 35 favicon::FaviconDriverObserver::NotificationIconType notification_icon_type, |
| 36 const GURL& icon_url, |
| 37 bool icon_url_changed, |
| 38 const gfx::Image& image) { |
| 39 dispatch_after( |
| 40 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayFavicon * NSEC_PER_SEC)), |
| 41 dispatch_get_main_queue(), ^{ |
| 42 OnFaviconDownloaded(favicon_driver); |
| 43 }); |
| 44 } |
| 45 |
| 46 void WebStatePoolImpl::RequestWebState(WebStatePoolDelegate* delegate) { |
| 47 int available_web_state = GetFirstWebStateAvailable(); |
| 48 if (available_web_state == -1) { |
| 49 pending_delegates_.push_back(delegate); |
| 50 return; |
| 51 } |
| 52 |
| 53 if (!web_states_[available_web_state]) { |
| 54 // Lazily initialize WebState. |
| 55 CreateWebState(available_web_state); |
| 56 } |
| 57 web::WebState* web_state = web_states_[available_web_state]; |
| 58 favicon::WebFaviconDriver* favicon_driver = |
| 59 favicon::WebFaviconDriver::FromWebState(web_state); |
| 60 favicon_web_state_.insert( |
| 61 std::make_pair(favicon_driver, available_web_state)); |
| 62 registered_web_state_.insert(std::make_pair(web_state, available_web_state)); |
| 63 |
| 64 delegate->OnWebStateAvailable(web_state); |
| 65 } |
| 66 |
| 67 void WebStatePoolImpl::CreateWebState(int web_state_index) { |
| 68 const web::WebState::CreateParams web_state_create_params(browser_state_); |
| 69 std::unique_ptr<web::WebState> web_state_unique = |
| 70 web::WebState::Create(web_state_create_params); |
| 71 web::WebState* web_state = web_state_unique.get(); |
| 72 unique_web_states_[web_state_index] = std::move(web_state_unique); |
| 73 web_states_[web_state_index] = web_state; |
| 74 |
| 75 ios::ChromeBrowserState* original_browser_state = |
| 76 ios::ChromeBrowserState::FromBrowserState(browser_state_); |
| 77 |
| 78 favicon::WebFaviconDriver::CreateForWebState( |
| 79 web_state, |
| 80 ios::FaviconServiceFactory::GetForBrowserState( |
| 81 original_browser_state, ServiceAccessType::EXPLICIT_ACCESS), |
| 82 ios::HistoryServiceFactory::GetForBrowserState( |
| 83 original_browser_state, ServiceAccessType::EXPLICIT_ACCESS), |
| 84 ios::BookmarkModelFactory::GetForBrowserState(original_browser_state)); |
| 85 favicon::WebFaviconDriver* favicon_driver = |
| 86 favicon::WebFaviconDriver::FromWebState(web_state); |
| 87 favicon_driver->AddObserver(this); |
| 88 } |
| 89 |
| 90 void WebStatePoolImpl::ReturnWebState(web::WebState* web_state) { |
| 91 favicon::WebFaviconDriver* favicon_driver = |
| 92 favicon::WebFaviconDriver::FromWebState(web_state); |
| 93 |
| 94 base::WeakPtr<WebStatePoolImpl> weak_this = weak_ptr_factory_.GetWeakPtr(); |
| 95 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, |
| 96 (int64_t)(kMaxDelayFavicon * NSEC_PER_SEC)), |
| 97 dispatch_get_main_queue(), ^{ |
| 98 WebStatePoolImpl* web_state_pool = weak_this.get(); |
| 99 if (web_state_pool) |
| 100 web_state_pool->OnFaviconDownloaded(favicon_driver); |
| 101 }); |
| 102 registered_web_state_.erase(web_state); |
| 103 |
| 104 // The favicon might have been downloaded before the WebState is returned. |
| 105 while (GetFirstWebStateAvailable() != -1) { |
| 106 RequestWebState(pending_delegates_.front()); |
| 107 pending_delegates_.pop_front(); |
| 108 } |
| 109 } |
| 110 |
| 111 void WebStatePoolImpl::OnFaviconDownloaded(favicon::FaviconDriver* driver) { |
| 112 favicon_web_state_.erase(driver); |
| 113 |
| 114 while (GetFirstWebStateAvailable() != -1) { |
| 115 RequestWebState(pending_delegates_.front()); |
| 116 pending_delegates_.pop_front(); |
| 117 } |
| 118 } |
| 119 |
| 120 int WebStatePoolImpl::GetFirstWebStateAvailable() { |
| 121 bool used_web_state[kMaxNumberOfWebState] = {false}; |
| 122 |
| 123 for (auto it = favicon_web_state_.begin(); it != favicon_web_state_.end(); |
| 124 it++) { |
| 125 // Check the WebState used to download favicon. |
| 126 used_web_state[it->second] = true; |
| 127 } |
| 128 for (auto it = registered_web_state_.begin(); |
| 129 it != registered_web_state_.end(); it++) { |
| 130 // Check the WebState used by delegates. |
| 131 used_web_state[it->second] = true; |
| 132 } |
| 133 |
| 134 for (int index = 0; index < kMaxNumberOfWebState; index++) { |
| 135 if (!used_web_state[index]) { |
| 136 return index; |
| 137 } |
| 138 } |
| 139 return -1; |
| 140 } |
| 141 |
| 142 } // namespace dom_distiller |
OLD | NEW |