Index: content/browser/payments/payment_app_info_fetcher.cc |
diff --git a/content/browser/payments/payment_app_info_fetcher.cc b/content/browser/payments/payment_app_info_fetcher.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f4d68e87d696e6587138409d3daf4b4ec1f5939c |
--- /dev/null |
+++ b/content/browser/payments/payment_app_info_fetcher.cc |
@@ -0,0 +1,157 @@ |
+// Copyright 2017 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 "content/browser/payments/payment_app_info_fetcher.h" |
+ |
+#include "base/base64.h" |
+#include "base/bind_helpers.h" |
+#include "content/browser/frame_host/render_frame_host_impl.h" |
+#include "content/browser/service_worker/service_worker_context_wrapper.h" |
+#include "content/browser/web_contents/web_contents_impl.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/manifest_icon_downloader.h" |
+#include "content/public/browser/manifest_icon_selector.h" |
+#include "ui/gfx/image/image.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+// TODO(gogerald): Choose appropriate icon size dynamically on different |
+// platforms. |
+const int kPaymentAppIdealIconSize = 64; |
+const int kPaymentAppMinimumIconSize = 0; |
+ |
+} // namespace |
+ |
+PaymentAppInfoFetcher::PaymentAppInfoFetcher() |
+ : context_process_id_(-1), context_frame_id_(-1) {} |
+PaymentAppInfoFetcher::~PaymentAppInfoFetcher() {} |
+ |
+void PaymentAppInfoFetcher::Start( |
+ const GURL& context_url, |
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, |
+ PaymentAppInfoFetchCallback callback) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ context_url_ = context_url; |
+ callback_ = std::move(callback); |
+ |
+ std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts = |
+ service_worker_context->GetProviderHostIds(context_url.GetOrigin()); |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::BindOnce(&PaymentAppInfoFetcher::StartFromUIThread, this, |
+ std::move(provider_hosts))); |
+} |
+ |
+void PaymentAppInfoFetcher::StartFromUIThread( |
+ const std::unique_ptr<std::vector<std::pair<int, int>>>& provider_hosts) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ |
+ if (provider_hosts->size() == 0U) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ return; |
+ } |
+ |
+ for (const auto& frame : *provider_hosts) { |
+ RenderFrameHostImpl* render_frame_host = |
+ RenderFrameHostImpl::FromID(frame.first, frame.second); |
+ if (!render_frame_host) |
+ continue; |
+ |
+ WebContentsImpl* web_content = static_cast<WebContentsImpl*>( |
+ WebContents::FromRenderFrameHost(render_frame_host)); |
+ if (!web_content || web_content->IsHidden() || |
+ context_url_.spec().compare( |
+ web_content->GetLastCommittedURL().spec()) != 0) { |
+ continue; |
+ } |
+ |
+ context_process_id_ = frame.first; |
+ context_frame_id_ = frame.second; |
+ |
+ web_content->GetManifest(base::Bind( |
+ &PaymentAppInfoFetcher::FetchPaymentAppManifestCallback, this)); |
+ return; |
+ } |
+ |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+} |
+ |
+void PaymentAppInfoFetcher::FetchPaymentAppManifestCallback( |
+ const GURL& url, |
+ const Manifest& manifest) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ |
+ if (url.is_empty() || manifest.IsEmpty()) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ return; |
+ } |
+ |
+ if (manifest.name.is_null() || |
+ !base::UTF16ToUTF8(manifest.name.string().c_str(), |
+ manifest.name.string().length(), |
+ &fetched_payment_app_name_)) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ return; |
+ } |
+ |
+ GURL icon_url = ManifestIconSelector::FindBestMatchingIcon( |
+ manifest.icons, kPaymentAppIdealIconSize, kPaymentAppMinimumIconSize, |
+ Manifest::Icon::ANY); |
+ if (!icon_url.is_valid()) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ return; |
+ } |
+ |
+ RenderFrameHostImpl* render_frame_host = |
+ RenderFrameHostImpl::FromID(context_process_id_, context_frame_id_); |
+ if (!render_frame_host) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ return; |
+ } |
+ |
+ WebContents* web_content = |
+ WebContents::FromRenderFrameHost(render_frame_host); |
+ if (!web_content) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ return; |
+ } |
+ |
+ if (!content::ManifestIconDownloader::Download( |
+ web_content, icon_url, kPaymentAppIdealIconSize, |
+ kPaymentAppMinimumIconSize, |
+ base::Bind(&PaymentAppInfoFetcher::OnIconFetched, this))) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ } |
+} |
+ |
+void PaymentAppInfoFetcher::OnIconFetched(const SkBitmap& icon) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ |
+ if (icon.drawsNothing()) { |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+ return; |
+ } |
+ |
+ gfx::Image decoded_image = gfx::Image::CreateFrom1xBitmap(icon); |
+ scoped_refptr<base::RefCountedMemory> raw_data = decoded_image.As1xPNGBytes(); |
+ base::Base64Encode( |
+ base::StringPiece(raw_data->front_as<char>(), raw_data->size()), |
+ &fetched_payment_app_icon_); |
+ PostPaymentAppInfoFetchResultToIOThread(); |
+} |
+ |
+void PaymentAppInfoFetcher::PostPaymentAppInfoFetchResultToIOThread() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::BindOnce(std::move(callback_), fetched_payment_app_name_, |
+ fetched_payment_app_icon_)); |
+} |
+ |
+} // namespace content |