Chromium Code Reviews| 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..40d3d6f356dff85a631a8e113fea42dc1877712a |
| --- /dev/null |
| +++ b/content/browser/payments/payment_app_info_fetcher.cc |
| @@ -0,0 +1,170 @@ |
| +// 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" |
| + |
| +// TODO(gogerald): Choose appropriate icon size dynamically on different |
| +// platforms. |
| +#define PAYMENT_APP_IDEAL_ICON_SIZE 64 |
| +#define PAYMENT_APP_MINIMUM_ICON_SIZE 0 |
|
please use gerrit instead
2017/06/29 21:15:39
Use constants instead of #define.
gogerald1
2017/06/30 02:55:22
Done.
|
| + |
| +namespace content { |
| + |
| +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 = |
| + GetProviderHostIds(service_worker_context.get(), context_url.GetOrigin()); |
| + DCHECK_GT(provider_hosts->size(), 0U); |
| + |
| + 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); |
| + |
| + 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, PAYMENT_APP_IDEAL_ICON_SIZE, |
| + PAYMENT_APP_MINIMUM_ICON_SIZE, 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, PAYMENT_APP_IDEAL_ICON_SIZE, |
| + PAYMENT_APP_MINIMUM_ICON_SIZE, |
| + 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_)); |
| +} |
| + |
| +std::unique_ptr<std::vector<std::pair<int, int>>> |
| +PaymentAppInfoFetcher::GetProviderHostIds( |
| + ServiceWorkerContextWrapper* service_worker_context, |
| + const GURL& origin) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + std::unique_ptr<std::vector<std::pair<int, int>>> render_frames( |
| + new std::vector<std::pair<int, int>>()); |
| + |
| + for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
| + service_worker_context->context()->GetClientProviderHostIterator( |
| + origin); |
| + !it->IsAtEnd(); it->Advance()) { |
| + ServiceWorkerProviderHost* provider_host = it->GetProviderHost(); |
| + render_frames->push_back( |
| + std::make_pair(provider_host->process_id(), provider_host->frame_id())); |
| + } |
| + |
| + return render_frames; |
| +} |
| + |
| +} // namespace content |