|  | // Copyright 2021 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #import "ios/web/js_messaging/web_view_web_state_map.h" | 
|  |  | 
|  | #import "base/memory/ptr_util.h" | 
|  | #import "ios/web/public/browser_state.h" | 
|  | #import "ios/web/public/web_state.h" | 
|  |  | 
|  | namespace { | 
|  | const char kWebViewWebStateMapKeyName[] = "web_view_web_state_map"; | 
|  | }  // namespace | 
|  |  | 
|  | namespace web { | 
|  |  | 
|  | WebViewWebStateMap::WebViewWebStateMap(BrowserState* browser_state) {} | 
|  |  | 
|  | WebViewWebStateMap::~WebViewWebStateMap() { | 
|  | for (const WebViewWebStateAssociation& association : mappings_) { | 
|  | association.web_state->RemoveObserver(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | WebViewWebStateMap* WebViewWebStateMap::FromBrowserState( | 
|  | BrowserState* browser_state) { | 
|  | DCHECK(browser_state); | 
|  |  | 
|  | WebViewWebStateMap* web_view_web_state_map = static_cast<WebViewWebStateMap*>( | 
|  | browser_state->GetUserData(kWebViewWebStateMapKeyName)); | 
|  | if (!web_view_web_state_map) { | 
|  | web_view_web_state_map = new WebViewWebStateMap(browser_state); | 
|  | browser_state->SetUserData(kWebViewWebStateMapKeyName, | 
|  | base::WrapUnique(web_view_web_state_map)); | 
|  | } | 
|  | return web_view_web_state_map; | 
|  | } | 
|  |  | 
|  | void WebViewWebStateMap::SetAssociatedWebViewForWebState(WKWebView* web_view, | 
|  | WebState* web_state) { | 
|  | DCHECK(web_state); | 
|  |  | 
|  | auto it = mappings_.begin(); | 
|  | while (it != mappings_.end()) { | 
|  | if (it->web_state == web_state) { | 
|  | if (web_view) { | 
|  | // Update existing entry with new webview. | 
|  | it->web_view = web_view; | 
|  | } else { | 
|  | // Remove mapping since no web view is assocaited. | 
|  | mappings_.erase(it); | 
|  | web_state->RemoveObserver(this); | 
|  | } | 
|  | return; | 
|  | } | 
|  | it++; | 
|  | } | 
|  |  | 
|  | web_state->AddObserver(this); | 
|  | mappings_.push_back(WebViewWebStateAssociation(web_view, web_state)); | 
|  | } | 
|  |  | 
|  | WebState* WebViewWebStateMap::GetWebStateForWebView(WKWebView* web_view) { | 
|  | for (const WebViewWebStateAssociation& association : mappings_) { | 
|  | if (association.web_view == web_view) { | 
|  | return association.web_state; | 
|  | } | 
|  | } | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | void WebViewWebStateMap::WebStateDestroyed(WebState* web_state) { | 
|  | auto it = mappings_.begin(); | 
|  | while (it != mappings_.end()) { | 
|  | if (it->web_state == web_state) { | 
|  | mappings_.erase(it); | 
|  | web_state->RemoveObserver(this); | 
|  | break; | 
|  | } | 
|  | it++; | 
|  | } | 
|  | } | 
|  |  | 
|  | WebViewWebStateMap::WebViewWebStateAssociation::WebViewWebStateAssociation( | 
|  | WKWebView* web_view, | 
|  | WebState* web_state) | 
|  | : web_view(web_view), web_state(web_state) {} | 
|  | WebViewWebStateMap::WebViewWebStateAssociation::~WebViewWebStateAssociation() = | 
|  | default; | 
|  |  | 
|  | }  // namespace web |