web_state_impl_realized_web_state.mm 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. // Copyright 2021 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. #import "ios/web/web_state/web_state_impl_realized_web_state.h"
  5. #if !defined(__has_feature) || !__has_feature(objc_arc)
  6. #error "This file requires ARC support."
  7. #endif
  8. #import "base/bind.h"
  9. #import "base/check.h"
  10. #import "base/compiler_specific.h"
  11. #import "base/metrics/histogram_macros.h"
  12. #import "base/strings/sys_string_conversions.h"
  13. #import "ios/web/common/features.h"
  14. #import "ios/web/js_messaging/web_view_js_utils.h"
  15. #import "ios/web/navigation/crw_error_page_helper.h"
  16. #import "ios/web/navigation/navigation_context_impl.h"
  17. #import "ios/web/navigation/navigation_item_impl.h"
  18. #import "ios/web/navigation/navigation_manager_impl.h"
  19. #import "ios/web/navigation/session_storage_builder.h"
  20. #import "ios/web/navigation/wk_navigation_util.h"
  21. #import "ios/web/public/browser_state.h"
  22. #import "ios/web/public/favicon/favicon_url.h"
  23. #import "ios/web/public/js_messaging/web_frame.h"
  24. #import "ios/web/public/navigation/navigation_item.h"
  25. #import "ios/web/public/navigation/web_state_policy_decider.h"
  26. #import "ios/web/public/security/certificate_policy_cache.h"
  27. #import "ios/web/public/session/crw_session_storage.h"
  28. #import "ios/web/public/session/serializable_user_data_manager.h"
  29. #import "ios/web/public/ui/java_script_dialog_presenter.h"
  30. #import "ios/web/public/web_client.h"
  31. #import "ios/web/public/web_state_delegate.h"
  32. #import "ios/web/public/web_state_observer.h"
  33. #import "ios/web/public/webui/web_ui_ios.h"
  34. #import "ios/web/public/webui/web_ui_ios_controller.h"
  35. #import "ios/web/public/webui/web_ui_ios_controller_factory.h"
  36. #import "ios/web/session/session_certificate_policy_cache_impl.h"
  37. #import "ios/web/web_state/policy_decision_state_tracker.h"
  38. #import "ios/web/web_state/ui/crw_web_controller.h"
  39. #import "ios/web/web_state/ui/crw_web_view_navigation_proxy.h"
  40. #import "ios/web/webui/web_ui_ios_controller_factory_registry.h"
  41. #import "ios/web/webui/web_ui_ios_impl.h"
  42. #import "ui/gfx/geometry/rect_f.h"
  43. #import "ui/gfx/image/image.h"
  44. #import "url/gurl.h"
  45. #import "url/url_constants.h"
  46. namespace web {
  47. #pragma mark - WebStateImpl::RealizedWebState public methods
  48. WebStateImpl::RealizedWebState::RealizedWebState(WebStateImpl* owner)
  49. : owner_(owner),
  50. interface_binder_(owner),
  51. user_agent_type_(UserAgentType::AUTOMATIC) {
  52. DCHECK(owner_);
  53. }
  54. WebStateImpl::RealizedWebState::~RealizedWebState() = default;
  55. void WebStateImpl::RealizedWebState::Init(const CreateParams& params,
  56. CRWSessionStorage* session_storage) {
  57. created_with_opener_ = params.created_with_opener;
  58. navigation_manager_ = std::make_unique<NavigationManagerImpl>();
  59. navigation_manager_->SetDelegate(this);
  60. navigation_manager_->SetBrowserState(params.browser_state);
  61. web_controller_ = [[CRWWebController alloc] initWithWebState:owner_];
  62. // Restore session history last because NavigationManagerImpl relies on
  63. // CRWWebController to restore history into the web view.
  64. if (session_storage) {
  65. // Session storage restore is asynchronous because it involves a page
  66. // load in WKWebView. Temporarily cache the restored session so it can
  67. // be returned if BuildSessionStorage() or GetTitle() is called before
  68. // the actual restoration completes. This can happen to inactive tabs
  69. // when a navigation in the current tab triggers the serialization of
  70. // all tabs and when user clicks on tab switcher without switching to
  71. // a tab.
  72. restored_session_storage_ = session_storage;
  73. SessionStorageBuilder::ExtractSessionState(*owner_, *navigation_manager_,
  74. restored_session_storage_);
  75. // Update the BrowserState's CertificatePolicyCache with the newly
  76. // restored policy cache entries.
  77. DCHECK(certificate_policy_cache_);
  78. certificate_policy_cache_->UpdateCertificatePolicyCache(
  79. web::BrowserState::GetCertificatePolicyCache(params.browser_state));
  80. // Load the stable identifier. Must not be empty or nil.
  81. DCHECK(session_storage.stableIdentifier.length);
  82. stable_identifier_ = [session_storage.stableIdentifier copy];
  83. // Restore the last active time, even if it is null, as that would mean
  84. // the session predates M-99 (when the last active time started to be
  85. // saved in CRWSessionStorage) and thus the WebState can be considered
  86. // "infinitely" old.
  87. last_active_time_ = session_storage.lastActiveTime;
  88. } else {
  89. certificate_policy_cache_ =
  90. std::make_unique<SessionCertificatePolicyCacheImpl>(
  91. params.browser_state);
  92. // Generate a random stable identifier. Ensure it is immutable.
  93. stable_identifier_ = [[[NSUUID UUID] UUIDString] copy];
  94. }
  95. // Let CreateParams override the last active time.
  96. if (!params.last_active_time.is_null())
  97. last_active_time_ = params.last_active_time;
  98. }
  99. void WebStateImpl::RealizedWebState::TearDown() {
  100. [web_controller_ close];
  101. // WebUI depends on web state so it must be destroyed first in case any WebUI
  102. // implementations depends on accessing web state during destruction.
  103. ClearWebUI();
  104. for (auto& observer : observers())
  105. observer.WebStateDestroyed(owner_);
  106. for (auto& observer : policy_deciders())
  107. observer.WebStateDestroyed();
  108. for (auto& observer : policy_deciders())
  109. observer.ResetWebState();
  110. SetDelegate(nullptr);
  111. }
  112. const NavigationManagerImpl&
  113. WebStateImpl::RealizedWebState::GetNavigationManager() const {
  114. return *navigation_manager_;
  115. }
  116. NavigationManagerImpl& WebStateImpl::RealizedWebState::GetNavigationManager() {
  117. return *navigation_manager_;
  118. }
  119. const WebFramesManagerImpl&
  120. WebStateImpl::RealizedWebState::GetWebFramesManager() const {
  121. return web_frames_manager_;
  122. }
  123. WebFramesManagerImpl& WebStateImpl::RealizedWebState::GetWebFramesManager() {
  124. return web_frames_manager_;
  125. }
  126. const SessionCertificatePolicyCacheImpl&
  127. WebStateImpl::RealizedWebState::GetSessionCertificatePolicyCache() const {
  128. return *certificate_policy_cache_;
  129. }
  130. SessionCertificatePolicyCacheImpl&
  131. WebStateImpl::RealizedWebState::GetSessionCertificatePolicyCache() {
  132. return *certificate_policy_cache_;
  133. }
  134. void WebStateImpl::RealizedWebState::SetSessionCertificatePolicyCache(
  135. std::unique_ptr<SessionCertificatePolicyCacheImpl>
  136. session_certificate_policy_cache) {
  137. DCHECK(!certificate_policy_cache_);
  138. certificate_policy_cache_ = std::move(session_certificate_policy_cache);
  139. }
  140. void WebStateImpl::RealizedWebState::SetWebViewNavigationProxyForTesting(
  141. id<CRWWebViewNavigationProxy> web_view) {
  142. web_view_for_testing_ = web_view;
  143. }
  144. #pragma mark - WebStateImpl implementation
  145. CRWWebController* WebStateImpl::RealizedWebState::GetWebController() {
  146. return web_controller_;
  147. }
  148. void WebStateImpl::RealizedWebState::SetWebController(
  149. CRWWebController* web_controller) {
  150. [web_controller_ close];
  151. web_controller_ = web_controller;
  152. }
  153. void WebStateImpl::RealizedWebState::OnNavigationStarted(
  154. NavigationContextImpl* context) {
  155. // Navigation manager loads internal URLs to restore session history and
  156. // create back-forward entries for WebUI. Do not trigger external callbacks.
  157. if ([CRWErrorPageHelper isErrorPageFileURL:context->GetUrl()] ||
  158. wk_navigation_util::IsRestoreSessionUrl(context->GetUrl())) {
  159. return;
  160. }
  161. for (auto& observer : observers())
  162. observer.DidStartNavigation(owner_, context);
  163. }
  164. void WebStateImpl::RealizedWebState::OnNavigationRedirected(
  165. NavigationContextImpl* context) {
  166. for (auto& observer : observers())
  167. observer.DidRedirectNavigation(owner_, context);
  168. }
  169. void WebStateImpl::RealizedWebState::OnNavigationFinished(
  170. NavigationContextImpl* context) {
  171. // Navigation manager loads internal URLs to restore session history and
  172. // create back-forward entries for WebUI. Do not trigger external callbacks.
  173. if ([CRWErrorPageHelper isErrorPageFileURL:context->GetUrl()] ||
  174. wk_navigation_util::IsRestoreSessionUrl(context->GetUrl())) {
  175. return;
  176. }
  177. for (auto& observer : observers())
  178. observer.DidFinishNavigation(owner_, context);
  179. // Update cached_favicon_urls_.
  180. if (!context->IsSameDocument()) {
  181. // Favicons are not valid after document change. Favicon URLs will be
  182. // refetched by CRWWebController and passed to OnFaviconUrlUpdated.
  183. cached_favicon_urls_.clear();
  184. } else if (!cached_favicon_urls_.empty()) {
  185. // For same-document navigations favicon urls will not be refetched and
  186. // WebStateObserver:FaviconUrlUpdated must use the cached results.
  187. for (auto& observer : observers()) {
  188. observer.FaviconUrlUpdated(owner_, cached_favicon_urls_);
  189. }
  190. }
  191. }
  192. void WebStateImpl::RealizedWebState::OnBackForwardStateChanged() {
  193. for (auto& observer : observers())
  194. observer.DidChangeBackForwardState(owner_);
  195. }
  196. void WebStateImpl::RealizedWebState::OnTitleChanged() {
  197. for (auto& observer : observers())
  198. observer.TitleWasSet(owner_);
  199. }
  200. void WebStateImpl::RealizedWebState::OnRenderProcessGone() {
  201. for (auto& observer : observers())
  202. observer.RenderProcessGone(owner_);
  203. }
  204. void WebStateImpl::RealizedWebState::OnScriptCommandReceived(
  205. const std::string& command,
  206. const base::Value& value,
  207. const GURL& page_url,
  208. bool user_is_interacting,
  209. WebFrame* sender_frame) {
  210. size_t dot_position = command.find_first_of('.');
  211. if (dot_position == 0 || dot_position == std::string::npos)
  212. return;
  213. std::string prefix = command.substr(0, dot_position);
  214. auto it = script_command_callbacks().find(prefix);
  215. if (it == script_command_callbacks().end())
  216. return;
  217. it->second.Notify(value, page_url, user_is_interacting, sender_frame);
  218. }
  219. void WebStateImpl::RealizedWebState::SetIsLoading(bool is_loading) {
  220. if (is_loading == is_loading_)
  221. return;
  222. is_loading_ = is_loading;
  223. if (is_loading) {
  224. for (auto& observer : observers())
  225. observer.DidStartLoading(owner_);
  226. } else {
  227. for (auto& observer : observers())
  228. observer.DidStopLoading(owner_);
  229. }
  230. }
  231. void WebStateImpl::RealizedWebState::OnPageLoaded(const GURL& url,
  232. bool load_success) {
  233. // Navigation manager loads internal URLs to restore session history and
  234. // create back-forward entries for WebUI. Do not trigger external callbacks.
  235. if (wk_navigation_util::IsWKInternalUrl(url))
  236. return;
  237. PageLoadCompletionStatus load_completion_status =
  238. load_success ? PageLoadCompletionStatus::SUCCESS
  239. : PageLoadCompletionStatus::FAILURE;
  240. for (auto& observer : observers())
  241. observer.PageLoaded(owner_, load_completion_status);
  242. }
  243. void WebStateImpl::RealizedWebState::OnFaviconUrlUpdated(
  244. const std::vector<FaviconURL>& candidates) {
  245. cached_favicon_urls_ = candidates;
  246. for (auto& observer : observers())
  247. observer.FaviconUrlUpdated(owner_, candidates);
  248. }
  249. void WebStateImpl::RealizedWebState::CreateWebUI(const GURL& url) {
  250. if (HasWebUI()) {
  251. if (web_ui_->GetController()->GetHost() == url.host()) {
  252. // Don't recreate webUI for the same host.
  253. return;
  254. }
  255. ClearWebUI();
  256. }
  257. web_ui_ = CreateWebUIIOS(url);
  258. }
  259. void WebStateImpl::RealizedWebState::ClearWebUI() {
  260. web_ui_.reset();
  261. }
  262. bool WebStateImpl::RealizedWebState::HasWebUI() const {
  263. return !!web_ui_;
  264. }
  265. void WebStateImpl::RealizedWebState::SetContentsMimeType(
  266. const std::string& mime_type) {
  267. mime_type_ = mime_type;
  268. }
  269. void WebStateImpl::RealizedWebState::ShouldAllowRequest(
  270. NSURLRequest* request,
  271. WebStatePolicyDecider::RequestInfo request_info,
  272. WebStatePolicyDecider::PolicyDecisionCallback callback) {
  273. auto request_state_tracker =
  274. std::make_unique<PolicyDecisionStateTracker>(std::move(callback));
  275. PolicyDecisionStateTracker* request_state_tracker_ptr =
  276. request_state_tracker.get();
  277. auto policy_decider_callback = base::BindRepeating(
  278. &PolicyDecisionStateTracker::OnSinglePolicyDecisionReceived,
  279. base::Owned(std::move(request_state_tracker)));
  280. int num_decisions_requested = 0;
  281. for (auto& policy_decider : policy_deciders()) {
  282. policy_decider.ShouldAllowRequest(request, request_info,
  283. policy_decider_callback);
  284. num_decisions_requested++;
  285. if (request_state_tracker_ptr->DeterminedFinalResult())
  286. break;
  287. }
  288. request_state_tracker_ptr->FinishedRequestingDecisions(
  289. num_decisions_requested);
  290. }
  291. bool WebStateImpl::RealizedWebState::ShouldAllowErrorPageToBeDisplayed(
  292. NSURLResponse* response,
  293. bool for_main_frame) {
  294. for (auto& policy_decider : policy_deciders()) {
  295. if (!policy_decider.ShouldAllowErrorPageToBeDisplayed(response,
  296. for_main_frame)) {
  297. return false;
  298. }
  299. }
  300. return true;
  301. }
  302. void WebStateImpl::RealizedWebState::ShouldAllowResponse(
  303. NSURLResponse* response,
  304. WebStatePolicyDecider::ResponseInfo response_info,
  305. WebStatePolicyDecider::PolicyDecisionCallback callback) {
  306. auto response_state_tracker =
  307. std::make_unique<PolicyDecisionStateTracker>(std::move(callback));
  308. PolicyDecisionStateTracker* response_state_tracker_ptr =
  309. response_state_tracker.get();
  310. auto policy_decider_callback = base::BindRepeating(
  311. &PolicyDecisionStateTracker::OnSinglePolicyDecisionReceived,
  312. base::Owned(std::move(response_state_tracker)));
  313. int num_decisions_requested = 0;
  314. for (auto& policy_decider : policy_deciders()) {
  315. policy_decider.ShouldAllowResponse(response, response_info,
  316. policy_decider_callback);
  317. num_decisions_requested++;
  318. if (response_state_tracker_ptr->DeterminedFinalResult())
  319. break;
  320. }
  321. response_state_tracker_ptr->FinishedRequestingDecisions(
  322. num_decisions_requested);
  323. }
  324. UIView* WebStateImpl::RealizedWebState::GetWebViewContainer() {
  325. if (delegate_) {
  326. return delegate_->GetWebViewContainer(owner_);
  327. }
  328. return nil;
  329. }
  330. UserAgentType WebStateImpl::RealizedWebState::GetUserAgentForNextNavigation(
  331. const GURL& url) {
  332. if (user_agent_type_ == UserAgentType::AUTOMATIC) {
  333. return GetWebClient()->GetDefaultUserAgent(owner_, url);
  334. }
  335. return user_agent_type_;
  336. }
  337. UserAgentType
  338. WebStateImpl::RealizedWebState::GetUserAgentForSessionRestoration() const {
  339. return user_agent_type_;
  340. }
  341. void WebStateImpl::RealizedWebState::SendChangeLoadProgress(double progress) {
  342. for (auto& observer : observers())
  343. observer.LoadProgressChanged(owner_, progress);
  344. }
  345. void WebStateImpl::RealizedWebState::ShowRepostFormWarningDialog(
  346. base::OnceCallback<void(bool)> callback) {
  347. if (delegate_) {
  348. delegate_->ShowRepostFormWarningDialog(owner_, std::move(callback));
  349. } else {
  350. std::move(callback).Run(true);
  351. }
  352. }
  353. void WebStateImpl::RealizedWebState::RunJavaScriptDialog(
  354. const GURL& origin_url,
  355. JavaScriptDialogType java_script_dialog_type,
  356. NSString* message_text,
  357. NSString* default_prompt_text,
  358. DialogClosedCallback callback) {
  359. JavaScriptDialogPresenter* presenter =
  360. delegate_ ? delegate_->GetJavaScriptDialogPresenter(owner_) : nullptr;
  361. if (!presenter) {
  362. std::move(callback).Run(false, nil);
  363. return;
  364. }
  365. running_javascript_dialog_ = true;
  366. presenter->RunJavaScriptDialog(
  367. owner_, origin_url, java_script_dialog_type, message_text,
  368. default_prompt_text,
  369. // Use a lambda to mark the dialog as closed if the `WebState` still
  370. // exists, then always run `callback`, even if the `WebState` has been
  371. // destroyed (otherwise, WebKit raises an inconsistent state exception).
  372. //
  373. // Since bound callback that take a member function and a `WeakPtr<T>`
  374. // are not called, this cannot be implemented by passing the `callback`
  375. // to `JavaScriptDialogClosed` as otherwise the call would not happen
  376. // if `WebState` is destroyed.
  377. base::BindOnce(
  378. [](base::WeakPtr<WebStateImpl> weak_web_state,
  379. DialogClosedCallback callback, bool success,
  380. NSString* user_input) {
  381. if (weak_web_state) {
  382. DCHECK(weak_web_state->pimpl_);
  383. weak_web_state->pimpl_->JavaScriptDialogClosed();
  384. }
  385. std::move(callback).Run(success, user_input);
  386. },
  387. owner_->weak_factory_.GetWeakPtr(), std::move(callback)));
  388. }
  389. bool WebStateImpl::RealizedWebState::IsJavaScriptDialogRunning() const {
  390. return running_javascript_dialog_;
  391. }
  392. WebState* WebStateImpl::RealizedWebState::CreateNewWebState(
  393. const GURL& url,
  394. const GURL& opener_url,
  395. bool initiated_by_user) {
  396. if (delegate_) {
  397. return delegate_->CreateNewWebState(owner_, url, opener_url,
  398. initiated_by_user);
  399. }
  400. return nullptr;
  401. }
  402. void WebStateImpl::RealizedWebState::OnAuthRequired(
  403. NSURLProtectionSpace* protection_space,
  404. NSURLCredential* proposed_credential,
  405. WebStateDelegate::AuthCallback callback) {
  406. if (delegate_) {
  407. delegate_->OnAuthRequired(owner_, protection_space, proposed_credential,
  408. std::move(callback));
  409. } else {
  410. std::move(callback).Run(nil, nil);
  411. }
  412. }
  413. void WebStateImpl::RealizedWebState::WebFrameBecameAvailable(
  414. std::unique_ptr<WebFrame> frame) {
  415. WebFrame* frame_ptr = frame.get();
  416. bool success = GetWebFramesManager().AddFrame(std::move(frame));
  417. if (!success) {
  418. // Frame was not added, do not notify observers.
  419. return;
  420. }
  421. for (auto& observer : observers())
  422. observer.WebFrameDidBecomeAvailable(owner_, frame_ptr);
  423. }
  424. void WebStateImpl::RealizedWebState::WebFrameBecameUnavailable(
  425. const std::string& frame_id) {
  426. WebFrame* frame = GetWebFramesManager().GetFrameWithId(frame_id);
  427. if (!frame) {
  428. return;
  429. }
  430. NotifyObserversAndRemoveWebFrame(frame);
  431. }
  432. void WebStateImpl::RealizedWebState::RemoveAllWebFrames() {
  433. for (WebFrame* frame : GetWebFramesManager().GetAllWebFrames()) {
  434. NotifyObserversAndRemoveWebFrame(frame);
  435. }
  436. }
  437. WebStateDelegate* WebStateImpl::RealizedWebState::GetDelegate() {
  438. return delegate_;
  439. }
  440. void WebStateImpl::RealizedWebState::SetDelegate(WebStateDelegate* delegate) {
  441. if (delegate == delegate_)
  442. return;
  443. if (delegate_)
  444. delegate_->Detach(owner_);
  445. delegate_ = delegate;
  446. if (delegate_) {
  447. delegate_->Attach(owner_);
  448. }
  449. }
  450. bool WebStateImpl::RealizedWebState::IsWebUsageEnabled() const {
  451. return [web_controller_ webUsageEnabled];
  452. }
  453. void WebStateImpl::RealizedWebState::SetWebUsageEnabled(bool enabled) {
  454. [web_controller_ setWebUsageEnabled:enabled];
  455. }
  456. UIView* WebStateImpl::RealizedWebState::GetView() {
  457. return [web_controller_ view];
  458. }
  459. void WebStateImpl::RealizedWebState::DidCoverWebContent() {
  460. [web_controller_ removeWebViewFromViewHierarchy];
  461. WasHidden();
  462. }
  463. void WebStateImpl::RealizedWebState::DidRevealWebContent() {
  464. [web_controller_ addWebViewToViewHierarchy];
  465. WasShown();
  466. }
  467. base::Time WebStateImpl::RealizedWebState::GetLastActiveTime() const {
  468. return last_active_time_;
  469. }
  470. void WebStateImpl::RealizedWebState::WasShown() {
  471. if (IsVisible())
  472. return;
  473. // Update last active time when the WebState transition to visible.
  474. last_active_time_ = base::Time::Now();
  475. [web_controller_ wasShown];
  476. for (auto& observer : observers())
  477. observer.WasShown(owner_);
  478. }
  479. void WebStateImpl::RealizedWebState::WasHidden() {
  480. if (!IsVisible())
  481. return;
  482. [web_controller_ wasHidden];
  483. for (auto& observer : observers())
  484. observer.WasHidden(owner_);
  485. }
  486. void WebStateImpl::RealizedWebState::SetKeepRenderProcessAlive(
  487. bool keep_alive) {
  488. [web_controller_ setKeepsRenderProcessAlive:keep_alive];
  489. }
  490. BrowserState* WebStateImpl::RealizedWebState::GetBrowserState() const {
  491. return navigation_manager_->GetBrowserState();
  492. }
  493. NSString* WebStateImpl::RealizedWebState::GetStableIdentifier() const {
  494. return [stable_identifier_ copy];
  495. }
  496. void WebStateImpl::RealizedWebState::OpenURL(
  497. const WebState::OpenURLParams& params) {
  498. DCHECK(Configured());
  499. if (delegate_)
  500. delegate_->OpenURLFromWebState(owner_, params);
  501. }
  502. void WebStateImpl::RealizedWebState::Stop() {
  503. if (navigation_manager_->IsRestoreSessionInProgress()) {
  504. // Do not interrupt session restoration process. For embedder session
  505. // restoration is opaque and WebState acts like it's idle.
  506. return;
  507. }
  508. [web_controller_ stopLoading];
  509. }
  510. CRWSessionStorage* WebStateImpl::RealizedWebState::BuildSessionStorage() {
  511. [web_controller_ recordStateInHistory];
  512. if (restored_session_storage_) {
  513. // UserData can be updated in an uncommitted WebState. Even if a WebState
  514. // hasn't been restored, its opener value may have changed.
  515. restored_session_storage_.userData =
  516. SerializableUserDataManager::FromWebState(owner_)
  517. ->GetUserDataForSession();
  518. return restored_session_storage_;
  519. }
  520. return SessionStorageBuilder::BuildStorage(*owner_, *navigation_manager_,
  521. *certificate_policy_cache_);
  522. }
  523. CRWJSInjectionReceiver* WebStateImpl::RealizedWebState::GetJSInjectionReceiver()
  524. const {
  525. return [web_controller_ jsInjectionReceiver];
  526. }
  527. void WebStateImpl::RealizedWebState::LoadData(NSData* data,
  528. NSString* mime_type,
  529. const GURL& url) {
  530. [web_controller_ loadData:data MIMEType:mime_type forURL:url];
  531. }
  532. void WebStateImpl::RealizedWebState::ExecuteJavaScript(
  533. const std::u16string& javascript) {
  534. [web_controller_ executeJavaScript:base::SysUTF16ToNSString(javascript)
  535. completionHandler:nil];
  536. }
  537. void WebStateImpl::RealizedWebState::ExecuteJavaScript(
  538. const std::u16string& javascript,
  539. JavaScriptResultCallback callback) {
  540. __block JavaScriptResultCallback stack_callback = std::move(callback);
  541. [web_controller_
  542. executeJavaScript:base::SysUTF16ToNSString(javascript)
  543. completionHandler:^(id value, NSError* error) {
  544. std::move(stack_callback).Run(ValueResultFromWKResult(value).get());
  545. }];
  546. }
  547. void WebStateImpl::RealizedWebState::ExecuteUserJavaScript(
  548. NSString* javascript) {
  549. [web_controller_ executeUserJavaScript:javascript completionHandler:nil];
  550. }
  551. const std::string& WebStateImpl::RealizedWebState::GetContentsMimeType() const {
  552. return mime_type_;
  553. }
  554. bool WebStateImpl::RealizedWebState::ContentIsHTML() const {
  555. return [web_controller_ contentIsHTML];
  556. }
  557. const std::u16string& WebStateImpl::RealizedWebState::GetTitle() const {
  558. DCHECK(Configured());
  559. // Empty string returned by reference if there is no navigation item.
  560. // It is safe to return a function level static as they are thread-safe.
  561. static const std::u16string kEmptyString16;
  562. // TODO(crbug.com/1270778): Implement the NavigationManager logic necessary
  563. // to match the WebContents implementation of this method.
  564. NavigationItem* item = navigation_manager_->GetLastCommittedItem();
  565. // Display title for the visible item makes more sense.
  566. item = navigation_manager_->GetVisibleItem();
  567. return item ? item->GetTitleForDisplay() : kEmptyString16;
  568. }
  569. bool WebStateImpl::RealizedWebState::IsLoading() const {
  570. return is_loading_;
  571. }
  572. double WebStateImpl::RealizedWebState::GetLoadingProgress() const {
  573. if (navigation_manager_->IsRestoreSessionInProgress())
  574. return 0.0;
  575. return [web_controller_ loadingProgress];
  576. }
  577. bool WebStateImpl::RealizedWebState::IsVisible() const {
  578. return [web_controller_ isVisible];
  579. }
  580. bool WebStateImpl::RealizedWebState::IsCrashed() const {
  581. return [web_controller_ isWebProcessCrashed];
  582. }
  583. bool WebStateImpl::RealizedWebState::IsEvicted() const {
  584. return ![web_controller_ isViewAlive];
  585. }
  586. const FaviconStatus& WebStateImpl::RealizedWebState::GetFaviconStatus() const {
  587. static const FaviconStatus missing_favicon_status;
  588. NavigationItem* item = navigation_manager_->GetLastCommittedItem();
  589. return item ? item->GetFaviconStatus() : missing_favicon_status;
  590. }
  591. void WebStateImpl::RealizedWebState::SetFaviconStatus(
  592. const FaviconStatus& favicon_status) {
  593. NavigationItem* item = navigation_manager_->GetLastCommittedItem();
  594. if (item)
  595. item->SetFaviconStatus(favicon_status);
  596. }
  597. int WebStateImpl::RealizedWebState::GetNavigationItemCount() const {
  598. return navigation_manager_->GetItemCount();
  599. }
  600. const GURL& WebStateImpl::RealizedWebState::GetVisibleURL() const {
  601. NavigationItem* item = navigation_manager_->GetVisibleItem();
  602. return item ? item->GetVirtualURL() : GURL::EmptyGURL();
  603. }
  604. const GURL& WebStateImpl::RealizedWebState::GetLastCommittedURL() const {
  605. NavigationItem* item = navigation_manager_->GetLastCommittedItem();
  606. return item ? item->GetVirtualURL() : GURL::EmptyGURL();
  607. }
  608. GURL WebStateImpl::RealizedWebState::GetCurrentURL(
  609. URLVerificationTrustLevel* trust_level) const {
  610. if (!trust_level) {
  611. auto ignore_trust = URLVerificationTrustLevel::kNone;
  612. return [web_controller_ currentURLWithTrustLevel:&ignore_trust];
  613. }
  614. GURL result = [web_controller_ currentURLWithTrustLevel:trust_level];
  615. NavigationItemImpl* item = navigation_manager_->GetLastCommittedItemImpl();
  616. GURL lastCommittedURL = item ? item->GetURL() : GURL();
  617. bool equalOrigins;
  618. if (result.SchemeIs(url::kAboutScheme) &&
  619. GetWebClient()->IsAppSpecificURL(GetLastCommittedURL())) {
  620. // This special case is added for any app specific URLs that have been
  621. // rewritten to about:// URLs. In this case, an about scheme does not have
  622. // an origin to compare, only a path.
  623. equalOrigins = result.path() == lastCommittedURL.path();
  624. } else {
  625. equalOrigins = result.DeprecatedGetOriginAsURL() ==
  626. lastCommittedURL.DeprecatedGetOriginAsURL();
  627. }
  628. UMA_HISTOGRAM_BOOLEAN("Web.CurrentOriginEqualsLastCommittedOrigin",
  629. equalOrigins);
  630. if (!equalOrigins || (item && item->IsUntrusted())) {
  631. *trust_level = URLVerificationTrustLevel::kMixed;
  632. }
  633. return result;
  634. }
  635. id<CRWWebViewProxy> WebStateImpl::RealizedWebState::GetWebViewProxy() const {
  636. return [web_controller_ webViewProxy];
  637. }
  638. void WebStateImpl::RealizedWebState::DidChangeVisibleSecurityState() {
  639. for (auto& observer : observers())
  640. observer.DidChangeVisibleSecurityState(owner_);
  641. }
  642. WebState::InterfaceBinder*
  643. WebStateImpl::RealizedWebState::GetInterfaceBinderForMainFrame() {
  644. return &interface_binder_;
  645. }
  646. bool WebStateImpl::RealizedWebState::HasOpener() const {
  647. return created_with_opener_;
  648. }
  649. void WebStateImpl::RealizedWebState::SetHasOpener(bool has_opener) {
  650. created_with_opener_ = has_opener;
  651. }
  652. bool WebStateImpl::RealizedWebState::CanTakeSnapshot() const {
  653. // The WKWebView snapshot API depends on IPC execution that does not function
  654. // properly when JavaScript dialogs are running.
  655. return !running_javascript_dialog_;
  656. }
  657. void WebStateImpl::RealizedWebState::TakeSnapshot(const gfx::RectF& rect,
  658. SnapshotCallback callback) {
  659. DCHECK(CanTakeSnapshot());
  660. // Move the callback to a __block pointer, which will be in scope as long
  661. // as the callback is retained.
  662. __block SnapshotCallback shared_callback = std::move(callback);
  663. [web_controller_ takeSnapshotWithRect:rect.ToCGRect()
  664. completion:^(UIImage* snapshot) {
  665. shared_callback.Run(gfx::Image(snapshot));
  666. }];
  667. }
  668. void WebStateImpl::RealizedWebState::CreateFullPagePdf(
  669. base::OnceCallback<void(NSData*)> callback) {
  670. // Move the callback to a __block pointer, which will be in scope as long
  671. // as the callback is retained.
  672. __block base::OnceCallback<void(NSData*)> callback_for_block =
  673. std::move(callback);
  674. [web_controller_
  675. createFullPagePDFWithCompletion:^(NSData* pdf_document_data) {
  676. std::move(callback_for_block).Run(pdf_document_data);
  677. }];
  678. }
  679. void WebStateImpl::RealizedWebState::CloseMediaPresentations() {
  680. [web_controller_ closeMediaPresentations];
  681. }
  682. void WebStateImpl::RealizedWebState::CloseWebState() {
  683. if (delegate_) {
  684. delegate_->CloseWebState(owner_);
  685. }
  686. }
  687. bool WebStateImpl::RealizedWebState::SetSessionStateData(NSData* data) {
  688. bool state_set = [web_controller_ setSessionStateData:data];
  689. if (!state_set)
  690. return false;
  691. // If this fails (e.g., see crbug.com/1019672 for a previous failure), this
  692. // may be a bug in WebKit session restoration, or a bug in generating the
  693. // |cached_data_| blob.
  694. if (navigation_manager_->GetItemCount() == 0) {
  695. return false;
  696. }
  697. for (int i = 0; i < navigation_manager_->GetItemCount(); i++) {
  698. NavigationItem* item = navigation_manager_->GetItemAtIndex(i);
  699. if ([CRWErrorPageHelper isErrorPageFileURL:item->GetURL()]) {
  700. item->SetVirtualURL([CRWErrorPageHelper
  701. failedNavigationURLFromErrorPageFileURL:item->GetURL()]);
  702. }
  703. }
  704. return true;
  705. }
  706. NSData* WebStateImpl::RealizedWebState::SessionStateData() const {
  707. // Don't mix safe and unsafe session restoration -- if a webState still
  708. // has unrestored targetUrl pages, leave it that way.
  709. for (int i = 0; i < navigation_manager_->GetItemCount(); i++) {
  710. NavigationItem* item = navigation_manager_->GetItemAtIndex(i);
  711. if (wk_navigation_util::IsRestoreSessionUrl(item->GetURL())) {
  712. return nil;
  713. }
  714. }
  715. return [web_controller_ sessionStateData];
  716. }
  717. PermissionState WebStateImpl::RealizedWebState::GetStateForPermission(
  718. Permission permission) const {
  719. return [web_controller_ stateForPermission:permission];
  720. }
  721. void WebStateImpl::RealizedWebState::SetStateForPermission(
  722. PermissionState state,
  723. Permission permission) {
  724. [web_controller_ setState:state forPermission:permission];
  725. }
  726. NSDictionary<NSNumber*, NSNumber*>*
  727. WebStateImpl::RealizedWebState::GetStatesForAllPermissions() const {
  728. return [web_controller_ statesForAllPermissions];
  729. }
  730. void WebStateImpl::RealizedWebState::OnStateChangedForPermission(
  731. Permission permission) {
  732. for (auto& observer : observers()) {
  733. observer.PermissionStateChanged(owner_, permission);
  734. }
  735. }
  736. #pragma mark - NavigationManagerDelegate implementation
  737. void WebStateImpl::RealizedWebState::ClearDialogs() {
  738. if (delegate_) {
  739. JavaScriptDialogPresenter* presenter =
  740. delegate_->GetJavaScriptDialogPresenter(owner_);
  741. if (presenter) {
  742. presenter->CancelDialogs(owner_);
  743. }
  744. }
  745. }
  746. void WebStateImpl::RealizedWebState::RecordPageStateInNavigationItem() {
  747. [web_controller_ recordStateInHistory];
  748. }
  749. void WebStateImpl::RealizedWebState::LoadCurrentItem(
  750. NavigationInitiationType type) {
  751. [web_controller_ loadCurrentURLWithRendererInitiatedNavigation:
  752. type == NavigationInitiationType::RENDERER_INITIATED];
  753. }
  754. void WebStateImpl::RealizedWebState::LoadIfNecessary() {
  755. [web_controller_ loadCurrentURLIfNecessary];
  756. }
  757. void WebStateImpl::RealizedWebState::Reload() {
  758. [web_controller_ reloadWithRendererInitiatedNavigation:NO];
  759. }
  760. void WebStateImpl::RealizedWebState::OnNavigationItemCommitted(
  761. NavigationItem* item) {
  762. if (wk_navigation_util::IsWKInternalUrl(item->GetURL()))
  763. return;
  764. // A committed navigation item indicates that NavigationManager has a new
  765. // valid session history so should invalidate the cached restored session
  766. // history.
  767. restored_session_storage_ = nil;
  768. }
  769. WebState* WebStateImpl::RealizedWebState::GetWebState() {
  770. return owner_;
  771. }
  772. void WebStateImpl::RealizedWebState::SetWebStateUserAgent(
  773. UserAgentType user_agent_type) {
  774. user_agent_type_ = user_agent_type;
  775. }
  776. id<CRWWebViewNavigationProxy>
  777. WebStateImpl::RealizedWebState::GetWebViewNavigationProxy() const {
  778. if (UNLIKELY(web_view_for_testing_))
  779. return web_view_for_testing_;
  780. return [web_controller_ webViewNavigationProxy];
  781. }
  782. void WebStateImpl::RealizedWebState::GoToBackForwardListItem(
  783. WKBackForwardListItem* wk_item,
  784. NavigationItem* item,
  785. NavigationInitiationType type,
  786. bool has_user_gesture) {
  787. return [web_controller_ goToBackForwardListItem:wk_item
  788. navigationItem:item
  789. navigationInitiationType:type
  790. hasUserGesture:has_user_gesture];
  791. }
  792. void WebStateImpl::RealizedWebState::RemoveWebView() {
  793. return [web_controller_ removeWebView];
  794. }
  795. NavigationItemImpl* WebStateImpl::RealizedWebState::GetPendingItem() {
  796. return [web_controller_ lastPendingItemForNewNavigation];
  797. }
  798. #pragma mark - WebStateImpl::RealizedWebState private methods
  799. void WebStateImpl::RealizedWebState::JavaScriptDialogClosed() {
  800. running_javascript_dialog_ = false;
  801. }
  802. void WebStateImpl::RealizedWebState::NotifyObserversAndRemoveWebFrame(
  803. WebFrame* frame) {
  804. for (auto& observer : observers())
  805. observer.WebFrameWillBecomeUnavailable(owner_, frame);
  806. GetWebFramesManager().RemoveFrameWithId(frame->GetFrameId());
  807. }
  808. std::unique_ptr<WebUIIOS> WebStateImpl::RealizedWebState::CreateWebUIIOS(
  809. const GURL& url) {
  810. WebUIIOSControllerFactory* factory =
  811. WebUIIOSControllerFactoryRegistry::GetInstance();
  812. if (!factory)
  813. return nullptr;
  814. std::unique_ptr<WebUIIOS> web_ui = std::make_unique<WebUIIOSImpl>(owner_);
  815. auto controller = factory->CreateWebUIIOSControllerForURL(web_ui.get(), url);
  816. if (!controller)
  817. return nullptr;
  818. web_ui->SetController(std::move(controller));
  819. return web_ui;
  820. }
  821. bool WebStateImpl::RealizedWebState::Configured() const {
  822. return web_controller_ != nil;
  823. }
  824. }