| // Copyright 2022 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/chrome/browser/follow/model/follow_java_script_feature.h" |
| |
| #import "ios/web/public/js_messaging/web_frames_manager.h" |
| #import "ios/web/public/web_state.h" |
| #import "net/base/apple/url_conversions.h" |
| |
| namespace { |
| const char kRSSLinkScript[] = "rss_link"; |
| const char kGetRSSLinkFunction[] = "rssLink.getRSSLinks"; |
| // The timeout for any JavaScript call in this file. |
| const double kJavaScriptExecutionTimeoutInMs = 500.0; |
| |
| } // namespace |
| |
| // static |
| FollowJavaScriptFeature* FollowJavaScriptFeature::GetInstance() { |
| static base::NoDestructor<FollowJavaScriptFeature> instance; |
| return instance.get(); |
| } |
| |
| FollowJavaScriptFeature::FollowJavaScriptFeature() |
| : JavaScriptFeature( |
| web::ContentWorld::kIsolatedWorld, |
| {FeatureScript::CreateWithFilename( |
| kRSSLinkScript, |
| FeatureScript::InjectionTime::kDocumentStart, |
| FeatureScript::TargetFrames::kMainFrame, |
| FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)}), |
| weak_ptr_factory_(this) {} |
| |
| FollowJavaScriptFeature::~FollowJavaScriptFeature() = default; |
| |
| void FollowJavaScriptFeature::GetWebPageURLs(web::WebState* web_state, |
| ResultCallback callback) { |
| web::WebFrame* main_frame = GetWebFramesManager(web_state)->GetMainWebFrame(); |
| if (!main_frame) { |
| std::move(callback).Run(nil); |
| return; |
| } |
| CallJavaScriptFunction( |
| main_frame, kGetRSSLinkFunction, |
| /* parameters= */ {}, |
| base::BindOnce(&FollowJavaScriptFeature::HandleResponse, |
| weak_ptr_factory_.GetWeakPtr(), |
| web_state->GetLastCommittedURL(), std::move(callback)), |
| base::Milliseconds(kJavaScriptExecutionTimeoutInMs)); |
| } |
| |
| void FollowJavaScriptFeature::HandleResponse(const GURL& url, |
| ResultCallback callback, |
| const base::Value* response) { |
| NSMutableArray<NSURL*>* rss_urls = nil; |
| if (response && response->is_list()) { |
| for (const auto& link : response->GetList()) { |
| if (link.is_string()) { |
| NSURL* nsurl = net::NSURLWithGURL(GURL(link.GetString())); |
| if (nsurl) { |
| if (!rss_urls) { |
| rss_urls = [[NSMutableArray alloc] init]; |
| } |
| |
| [rss_urls addObject:nsurl]; |
| } |
| } |
| } |
| } |
| |
| WebPageURLs* web_page_urls = |
| [[WebPageURLs alloc] initWithURL:net::NSURLWithGURL(url) |
| RSSURLs:rss_urls]; |
| |
| std::move(callback).Run(web_page_urls); |
| } |