Skip to content

Commit

Permalink
Resolve the beforeinstallprompt event's promise.
Browse files Browse the repository at this point in the history
This resolves the promise sent with the beforeinstallprompt banner,
after the banner is shown and either dismissed or accepted.

BUG=460945

Review URL: https://codereview.chromium.org/1120543002

Cr-Commit-Position: refs/heads/master@{#328505}
  • Loading branch information
benwells authored and Commit bot committed May 6, 2015
1 parent 4fb7be4 commit 04ab5b9
Show file tree
Hide file tree
Showing 17 changed files with 202 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ infobars::InfoBar* AppBannerDataFetcherAndroid::CreateBanner(
infobars::InfoBar* infobar = nullptr;
if (native_app_data_.is_null()) {
scoped_ptr<AppBannerInfoBarDelegate> delegate(
new AppBannerInfoBarDelegate(title,
new AppBannerInfoBarDelegate(event_request_id(),
title,
new SkBitmap(*icon),
web_app_data()));

Expand All @@ -59,7 +60,8 @@ infobars::InfoBar* AppBannerDataFetcherAndroid::CreateBanner(
RecordDidShowBanner("AppBanner.WebApp.Shown");
} else {
scoped_ptr<AppBannerInfoBarDelegate> delegate(
new AppBannerInfoBarDelegate(title,
new AppBannerInfoBarDelegate(event_request_id(),
title,
new SkBitmap(*icon),
native_app_data_,
native_app_package_));
Expand Down
24 changes: 24 additions & 0 deletions chrome/browser/android/banners/app_banner_infobar_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/ui/android/infobars/app_banner_infobar.h"
#include "chrome/common/render_messages.h"
#include "chrome/grit/generated_resources.h"
#include "components/rappor/rappor_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/manifest.h"
#include "jni/AppBannerInfoBarDelegate_jni.h"
#include "ui/gfx/android/java_bitmap.h"
Expand All @@ -33,23 +36,27 @@ using base::android::ConvertUTF16ToJavaString;
namespace banners {

AppBannerInfoBarDelegate::AppBannerInfoBarDelegate(
int event_request_id,
const base::string16& app_title,
SkBitmap* app_icon,
const content::Manifest& web_app_data)
: app_title_(app_title),
app_icon_(app_icon),
event_request_id_(event_request_id),
web_app_data_(web_app_data) {
DCHECK(!web_app_data.IsEmpty());
CreateJavaDelegate();
}

AppBannerInfoBarDelegate::AppBannerInfoBarDelegate(
int event_request_id,
const base::string16& app_title,
SkBitmap* app_icon,
const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
const std::string& native_app_package)
: app_title_(app_title),
app_icon_(app_icon),
event_request_id_(event_request_id),
native_app_data_(native_app_data),
native_app_package_(native_app_package) {
DCHECK(!native_app_data_.is_null());
Expand Down Expand Up @@ -126,6 +133,16 @@ void AppBannerInfoBarDelegate::CreateJavaDelegate() {
reinterpret_cast<intptr_t>(this)));
}

void AppBannerInfoBarDelegate::SendBannerAccepted(
content::WebContents* web_contents,
const std::string& platform) {
web_contents->GetMainFrame()->Send(
new ChromeViewMsg_AppBannerAccepted(
web_contents->GetMainFrame()->GetRoutingID(),
event_request_id_,
platform));
}

gfx::Image AppBannerInfoBarDelegate::GetIcon() const {
return gfx::Image::CreateFrom1xBitmap(*app_icon_.get());
}
Expand All @@ -138,6 +155,11 @@ void AppBannerInfoBarDelegate::InfoBarDismissed() {

TrackDismissEvent(DISMISS_EVENT_CLOSE_BUTTON);

web_contents->GetMainFrame()->Send(
new ChromeViewMsg_AppBannerDismissed(
web_contents->GetMainFrame()->GetRoutingID(),
event_request_id_));

if (!native_app_data_.is_null()) {
AppBannerSettingsHelper::RecordBannerEvent(
web_contents, web_contents->GetURL(),
Expand Down Expand Up @@ -197,6 +219,7 @@ bool AppBannerInfoBarDelegate::Accept() {
} else {
TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED);
}
SendBannerAccepted(web_contents, "play");
return was_opened;
} else if (!web_app_data_.IsEmpty()) {
AppBannerSettingsHelper::RecordBannerEvent(
Expand All @@ -215,6 +238,7 @@ bool AppBannerInfoBarDelegate::Accept() {
*app_icon_.get()));

TrackInstallEvent(INSTALL_EVENT_WEB_APP_INSTALLED);
SendBannerAccepted(web_contents, "web");
rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(),
"AppBanner.WebApp.Installed",
web_contents->GetURL());
Expand Down
9 changes: 9 additions & 0 deletions chrome/browser/android/banners/app_banner_infobar_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include "ui/gfx/image/image.h"
#include "url/gurl.h"

namespace content {
class WebContents;
}

namespace infobars {
class InfoBarManager;
} // namespace infobars
Expand All @@ -25,12 +29,14 @@ class AppBannerInfoBarDelegate : public ConfirmInfoBarDelegate {
public:
// Delegate for promoting a web app.
AppBannerInfoBarDelegate(
int event_request_id,
const base::string16& app_title,
SkBitmap* app_icon,
const content::Manifest& web_app_data);

// Delegate for promoting an Android app.
AppBannerInfoBarDelegate(
int event_request_id,
const base::string16& app_title,
SkBitmap* app_icon,
const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
Expand All @@ -54,6 +60,8 @@ class AppBannerInfoBarDelegate : public ConfirmInfoBarDelegate {

private:
void CreateJavaDelegate();
void SendBannerAccepted(content::WebContents* web_contents,
const std::string& platform);

// ConfirmInfoBarDelegate:
gfx::Image GetIcon() const override;
Expand All @@ -68,6 +76,7 @@ class AppBannerInfoBarDelegate : public ConfirmInfoBarDelegate {
base::string16 app_title_;
scoped_ptr<SkBitmap> app_icon_;

int event_request_id_;
content::Manifest web_app_data_;

base::android::ScopedJavaGlobalRef<jobject> native_app_data_;
Expand Down
10 changes: 5 additions & 5 deletions chrome/browser/banners/app_banner_data_fetcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ AppBannerDataFetcher::AppBannerDataFetcher(
: WebContentsObserver(web_contents),
ideal_icon_size_(ideal_icon_size),
weak_delegate_(delegate),
is_active_(false) {
is_active_(false),
event_request_id_(-1) {
}

void AppBannerDataFetcher::Start(const GURL& validated_url) {
Expand Down Expand Up @@ -139,15 +140,13 @@ void AppBannerDataFetcher::OnBannerPromptReply(
int request_id,
blink::WebAppBannerPromptReply reply) {
content::WebContents* web_contents = GetWebContents();
if (!is_active_ || !web_contents || request_id != gCurrentRequestID) {
if (!is_active_ || !web_contents || request_id != event_request_id_) {
Cancel();
return;
}

// The renderer might have requested the prompt to be canceled.
if (reply == blink::WebAppBannerPromptReply::Cancel) {
// TODO(mlamouri,benwells): we should probably record that to behave
// differently with regard to showing the banner.
Cancel();
return;
}
Expand Down Expand Up @@ -320,10 +319,11 @@ void AppBannerDataFetcher::ShowBanner(const SkBitmap* icon) {
}

app_icon_.reset(new SkBitmap(*icon));
event_request_id_ = ++gCurrentRequestID;
web_contents->GetMainFrame()->Send(
new ChromeViewMsg_AppBannerPromptRequest(
web_contents->GetMainFrame()->GetRoutingID(),
++gCurrentRequestID,
event_request_id_,
GetBannerType()));
}

Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/banners/app_banner_data_fetcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class AppBannerDataFetcher
virtual std::string GetAppIdentifier();
const content::Manifest& web_app_data() { return web_app_data_; }
void set_app_title(const base::string16& title) { app_title_ = title; }
int event_request_id() { return event_request_id_; }

// Fetches the icon at the given URL asynchronously, returning |false| if a
// load could not be started.
Expand Down Expand Up @@ -145,6 +146,7 @@ class AppBannerDataFetcher
const base::WeakPtr<Delegate> weak_delegate_;
ObserverList<Observer> observer_list_;
bool is_active_;
int event_request_id_;
scoped_ptr<chrome::BitmapFetcher> bitmap_fetcher_;
scoped_ptr<SkBitmap> app_icon_;

Expand Down
2 changes: 2 additions & 0 deletions chrome/chrome_renderer.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
{
'variables': {
'chrome_renderer_sources': [
'renderer/banners/app_banner_client.cc',
'renderer/banners/app_banner_client.h',
'renderer/benchmarking_extension.cc',
'renderer/benchmarking_extension.h',
'renderer/chrome_content_renderer_client.cc',
Expand Down
9 changes: 9 additions & 0 deletions chrome/common/render_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,15 @@ IPC_MESSAGE_ROUTED2(ChromeViewMsg_AppBannerPromptRequest,
int /* request_id */,
std::string /* platform */)

// Tells the renderer that a banner has been accepted.
IPC_MESSAGE_ROUTED2(ChromeViewMsg_AppBannerAccepted,
int32_t /* request_id */,
std::string /* platform */)

// Tells the renderer that a banner has been dismissed.
IPC_MESSAGE_ROUTED1(ChromeViewMsg_AppBannerDismissed,
int32_t /* request_id */)

// Notification that the page has an OpenSearch description document
// associated with it.
IPC_MESSAGE_ROUTED3(ChromeViewHostMsg_PageHasOSDD,
Expand Down
62 changes: 62 additions & 0 deletions chrome/renderer/banners/app_banner_client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2015 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 "chrome/renderer/banners/app_banner_client.h"

#include "chrome/common/render_messages.h"
#include "ipc/ipc_message.h"
#include "third_party/WebKit/public/platform/WebString.h"

using blink::WebString;

AppBannerClient::AppBannerClient(content::RenderFrame* render_frame)
: content::RenderFrameObserver(render_frame) {
}

AppBannerClient::~AppBannerClient() {
}

bool AppBannerClient::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AppBannerClient, message)
IPC_MESSAGE_HANDLER(ChromeViewMsg_AppBannerAccepted, OnBannerAccepted);
IPC_MESSAGE_HANDLER(ChromeViewMsg_AppBannerDismissed, OnBannerDismissed);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}

void AppBannerClient::registerBannerCallbacks(
int request_id,
blink::WebAppBannerCallbacks* callbacks) {
banner_callbacks_.AddWithID(callbacks, request_id);
}

void AppBannerClient::ResolveEvent(
int request_id,
const std::string& platform,
const blink::WebAppBannerPromptResult::Outcome& outcome) {
blink::WebAppBannerCallbacks* callbacks =
banner_callbacks_.Lookup(request_id);
if (!callbacks)
return;

scoped_ptr<blink::WebAppBannerPromptResult> result(
new blink::WebAppBannerPromptResult(
blink::WebString::fromUTF8(platform),
outcome));
callbacks->onSuccess(result.release());
banner_callbacks_.Remove(request_id);
}

void AppBannerClient::OnBannerAccepted(int request_id,
const std::string& platform) {
ResolveEvent(request_id, platform,
blink::WebAppBannerPromptResult::Outcome::Accepted);
}

void AppBannerClient::OnBannerDismissed(int request_id) {
ResolveEvent(request_id, "",
blink::WebAppBannerPromptResult::Outcome::Dismissed);
}
46 changes: 46 additions & 0 deletions chrome/renderer/banners/app_banner_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2015 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.

#ifndef CHROME_RENDERER_BANNERS_APP_BANNER_CLIENT_H_
#define CHROME_RENDERER_BANNERS_APP_BANNER_CLIENT_H_

#include <stdint.h>
#include <string>

#include "base/id_map.h"
#include "content/public/renderer/render_frame_observer.h"
#include "third_party/WebKit/public/platform/modules/app_banner/WebAppBannerClient.h"
#include "third_party/WebKit/public/platform/modules/app_banner/WebAppBannerPromptResult.h"

namespace IPC {
class Message;
} // namespace IPC

class AppBannerClient : public content::RenderFrameObserver,
public blink::WebAppBannerClient {
public:
explicit AppBannerClient(content::RenderFrame* render_frame);
virtual ~AppBannerClient();

private:
// content::RenderFrame::Observer implementation.
bool OnMessageReceived(const IPC::Message& message) override;

// WebAppBannerClient implementation.
void registerBannerCallbacks(int request_id,
blink::WebAppBannerCallbacks*) override;

void ResolveEvent(int request_id,
const std::string& platform,
const blink::WebAppBannerPromptResult::Outcome& outcome);
void OnBannerAccepted(int request_id, const std::string& platform);
void OnBannerDismissed(int request_id);

IDMap<blink::WebAppBannerCallbacks, IDMapOwnPointer>
banner_callbacks_;

DISALLOW_COPY_AND_ASSIGN(AppBannerClient);
};

#endif // CHROME_RENDERER_BANNERS_APP_BANNER_CLIENT_H_
8 changes: 8 additions & 0 deletions chrome/renderer/chrome_content_renderer_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/locale_settings.h"
#include "chrome/grit/renderer_resources.h"
#include "chrome/renderer/banners/app_banner_client.h"
#include "chrome/renderer/benchmarking_extension.h"
#include "chrome/renderer/chrome_render_frame_observer.h"
#include "chrome/renderer/chrome_render_process_observer.h"
Expand Down Expand Up @@ -1647,3 +1648,10 @@ void ChromeContentRendererClient::RecordRapporURL(const std::string& metric,
const GURL& url) {
RenderThread::Get()->Send(new ChromeViewHostMsg_RecordRapporURL(metric, url));
}

scoped_ptr<blink::WebAppBannerClient>
ChromeContentRendererClient::CreateAppBannerClient(
content::RenderFrame* render_frame) {
return scoped_ptr<blink::WebAppBannerClient>(
new AppBannerClient(render_frame));
}
2 changes: 2 additions & 0 deletions chrome/renderer/chrome_content_renderer_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
void RecordRappor(const std::string& metric,
const std::string& sample) override;
void RecordRapporURL(const std::string& metric, const GURL& url) override;
scoped_ptr<blink::WebAppBannerClient> CreateAppBannerClient(
content::RenderFrame* render_frame) override;

#if defined(ENABLE_EXTENSIONS)
// Takes ownership.
Expand Down
5 changes: 4 additions & 1 deletion chrome/renderer/chrome_render_frame_observer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,14 @@ void ChromeRenderFrameObserver::DidFinishDocumentLoad() {

void ChromeRenderFrameObserver::OnAppBannerPromptRequest(
int request_id, const std::string& platform) {
// App banner prompt requests are handled in the general chrome render frame
// observer, not the AppBannerClient, as the AppBannerClient is created lazily
// by blink and may not exist when the request is sent.
blink::WebAppBannerPromptReply reply = blink::WebAppBannerPromptReply::None;
blink::WebString web_platform(base::UTF8ToUTF16(platform));
blink::WebVector<blink::WebString> web_platforms(&web_platform, 1);
render_frame()->GetWebFrame()->willShowInstallBannerPrompt(
web_platforms, &reply);
request_id, web_platforms, &reply);

Send(new ChromeViewHostMsg_AppBannerPromptReply(
routing_id(), request_id, reply));
Expand Down
Loading

0 comments on commit 04ab5b9

Please sign in to comment.