summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhoro <horo@chromium.org>2016-01-25 06:36:45 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-25 14:38:04 +0000
commit9638ad271db786762315556b7c2bc9c0a55c8e76 (patch)
tree3d4d25e42153b553a345935b203188256eea786c
parentf5cdfde9135883c6cd83c81436ebe4888c432b8b (diff)
downloadchromium_src-9638ad271db786762315556b7c2bc9c0a55c8e76.zip
chromium_src-9638ad271db786762315556b7c2bc9c0a55c8e76.tar.gz
chromium_src-9638ad271db786762315556b7c2bc9c0a55c8e76.tar.bz2
Add "Request app banner" context menu in DevTools
BUG=540491 Demo: https://drive.google.com/file/d/0B6skYAFVnosEc1RQRm9KYmxCeXM/view?usp=sharing When the user clicks "Request app banner" context menu, Chrome tries to open "add to homescreen" banner. And if error happens, it will show the detailed information about why the app banner is not opened even if "bypass-app-banner-engagement-checks" flag is not set. RequestAppBanner method from DevTools is handled like this: Android: PageHandler::RequestAppBanner() -> TabWebContentsDelegateAndroid::RequestAppBanner() -> Java TabWebContentsDelegateAndroid.requestAppBanner() -> Java Tab.requestAppBanner() -> Java AppBannerManager.requestAppBanner() -> nativeRequestAppBanner() -> AppBannerManagerAndroid::RequestAppBanner() -> AppBannerManager::TriggerAppBannerFetch() Desktop: PageHandler::RequestAppBanner() -> Browser::RequestAppBanner() -> AppBannerManager::TriggerAppBannerFetch() Review URL: https://codereview.chromium.org/1569893003 Cr-Commit-Position: refs/heads/master@{#371239}
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java6
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java7
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java5
-rw-r--r--chrome/browser/android/banners/app_banner_data_fetcher_android.cc9
-rw-r--r--chrome/browser/android/banners/app_banner_data_fetcher_android.h14
-rw-r--r--chrome/browser/android/banners/app_banner_manager_android.cc45
-rw-r--r--chrome/browser/android/banners/app_banner_manager_android.h16
-rw-r--r--chrome/browser/android/tab_web_contents_delegate_android.cc9
-rw-r--r--chrome/browser/android/tab_web_contents_delegate_android.h1
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher.cc65
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher.h14
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher_browsertest.cc8
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher_desktop.cc7
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher_desktop.h3
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher_unittest.cc5
-rw-r--r--chrome/browser/banners/app_banner_debug_log.cc23
-rw-r--r--chrome/browser/banners/app_banner_debug_log.h7
-rw-r--r--chrome/browser/banners/app_banner_manager.cc30
-rw-r--r--chrome/browser/banners/app_banner_manager.h12
-rw-r--r--chrome/browser/banners/app_banner_manager_desktop.cc7
-rw-r--r--chrome/browser/banners/app_banner_manager_desktop.h3
-rw-r--r--chrome/browser/ui/browser.cc12
-rw-r--r--chrome/browser/ui/browser.h1
-rw-r--r--components/web_contents_delegate_android/web_contents_delegate_android.cc6
-rw-r--r--components/web_contents_delegate_android/web_contents_delegate_android.h1
-rw-r--r--content/browser/devtools/protocol/page_handler.cc8
-rw-r--r--content/browser/devtools/protocol/page_handler.h1
-rw-r--r--content/public/browser/web_contents_delegate.cc4
-rw-r--r--content/public/browser/web_contents_delegate.h3
-rw-r--r--third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js5
-rw-r--r--third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js18
-rw-r--r--third_party/WebKit/Source/devtools/front_end/emulation/module.json12
-rw-r--r--third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js33
-rw-r--r--third_party/WebKit/Source/devtools/front_end/screencast/module.json13
-rw-r--r--third_party/WebKit/Source/devtools/protocol.json8
35 files changed, 322 insertions, 99 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
index 1bfaac7..cd0a59a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
@@ -137,6 +137,11 @@ public class AppBannerManager extends EmptyTabObserver {
};
}
+ /** Requests the app banner. This method is called from the DevTools. */
+ public void requestAppBanner() {
+ nativeRequestAppBanner(mNativePointer);
+ }
+
/** Enables or disables the app banners for testing. */
@VisibleForTesting
static void setIsEnabledForTesting(boolean state) {
@@ -173,6 +178,7 @@ public class AppBannerManager extends EmptyTabObserver {
WebContents webContents);
private native boolean nativeOnAppDetailsRetrieved(long nativeAppBannerManagerAndroid,
AppData data, String title, String packageName, String imageUrl);
+ private native void nativeRequestAppBanner(long nativeAppBannerManagerAndroid);
// Testing methods.
private static native void nativeSetTimeDeltaForTesting(int days);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index f48cd88..c275d80 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -2233,6 +2233,13 @@ public final class Tab implements ViewGroup.OnHierarchyChangeListener,
}
}
+ /** Requests the app banner. This method is called from the DevTools. */
+ protected boolean requestAppBanner() {
+ if (mAppBannerManager == null) return false;
+ mAppBannerManager.requestAppBanner();
+ return true;
+ }
+
@CalledByNative
private void clearNativePtr() {
assert mNativeTabAndroid != 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
index a745b58..f9b0c58 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
@@ -353,6 +353,11 @@ public class TabWebContentsDelegateAndroid extends WebContentsDelegateAndroid {
return success;
}
+ @CalledByNative
+ private boolean requestAppBanner() {
+ return mTab.requestAppBanner();
+ }
+
@Override
public void activateContents() {
boolean activityIsDestroyed = false;
diff --git a/chrome/browser/android/banners/app_banner_data_fetcher_android.cc b/chrome/browser/android/banners/app_banner_data_fetcher_android.cc
index 873d31a..e367f54 100644
--- a/chrome/browser/android/banners/app_banner_data_fetcher_android.cc
+++ b/chrome/browser/android/banners/app_banner_data_fetcher_android.cc
@@ -23,14 +23,15 @@ AppBannerDataFetcherAndroid::AppBannerDataFetcherAndroid(
int ideal_icon_size_in_dp,
int minimum_icon_size_in_dp,
int ideal_splash_image_size_in_dp,
- int minimum_splash_image_size_in_dp)
+ int minimum_splash_image_size_in_dp,
+ bool is_debug_mode)
: AppBannerDataFetcher(web_contents,
weak_delegate,
ideal_icon_size_in_dp,
- minimum_icon_size_in_dp),
+ minimum_icon_size_in_dp,
+ is_debug_mode),
ideal_splash_image_size_in_dp_(ideal_splash_image_size_in_dp),
- minimum_splash_image_size_in_dp_(minimum_splash_image_size_in_dp) {
-}
+ minimum_splash_image_size_in_dp_(minimum_splash_image_size_in_dp) {}
AppBannerDataFetcherAndroid::~AppBannerDataFetcherAndroid() {
}
diff --git a/chrome/browser/android/banners/app_banner_data_fetcher_android.h b/chrome/browser/android/banners/app_banner_data_fetcher_android.h
index db26df0..058415c 100644
--- a/chrome/browser/android/banners/app_banner_data_fetcher_android.h
+++ b/chrome/browser/android/banners/app_banner_data_fetcher_android.h
@@ -15,13 +15,13 @@ namespace banners {
// WebContents. Extends the regular fetch to add support for Android apps.
class AppBannerDataFetcherAndroid : public AppBannerDataFetcher {
public:
- AppBannerDataFetcherAndroid(
- content::WebContents* web_contents,
- base::WeakPtr<Delegate> weak_delegate,
- int ideal_icon_size_in_dp,
- int minimum_icon_size_in_dp,
- int ideal_splash_image_size_in_dp,
- int minimum_splash_image_size_in_dp);
+ AppBannerDataFetcherAndroid(content::WebContents* web_contents,
+ base::WeakPtr<Delegate> weak_delegate,
+ int ideal_icon_size_in_dp,
+ int minimum_icon_size_in_dp,
+ int ideal_splash_image_size_in_dp,
+ int minimum_splash_image_size_in_dp,
+ bool is_debug_mode);
// Saves information about the Android app being promoted by the current page,
// then continues the creation pipeline.
diff --git a/chrome/browser/android/banners/app_banner_manager_android.cc b/chrome/browser/android/banners/app_banner_manager_android.cc
index 36b4045..b1915cc 100644
--- a/chrome/browser/android/banners/app_banner_manager_android.cc
+++ b/chrome/browser/android/banners/app_banner_manager_android.cc
@@ -56,8 +56,9 @@ void AppBannerManagerAndroid::ReplaceWebContents(
bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
const GURL& url,
- const std::string& id) {
- if (!CheckPlatformAndId(platform, id))
+ const std::string& id,
+ bool is_debug_mode) {
+ if (!CheckPlatformAndId(platform, id, is_debug_mode))
return false;
banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED);
@@ -70,8 +71,8 @@ bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
if (id_from_app_url.size() && id != id_from_app_url) {
- banners::OutputDeveloperDebugMessage(web_contents(),
- banners::kIgnoredIdsDoNotMatch);
+ banners::OutputDeveloperDebugMessage(
+ web_contents(), banners::kIgnoredIdsDoNotMatch, is_debug_mode);
return false;
}
@@ -99,27 +100,31 @@ bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
}
bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
- const std::string& id) {
+ const std::string& id,
+ bool is_debug_mode) {
if (platform != kPlayPlatform) {
banners::OutputDeveloperDebugMessage(
- web_contents(), platform + banners::kIgnoredNotSupportedOnAndroid);
+ web_contents(), platform + banners::kIgnoredNotSupportedOnAndroid,
+ is_debug_mode);
return false;
}
if (id.empty()) {
- banners::OutputDeveloperDebugMessage(web_contents(), banners::kIgnoredNoId);
+ banners::OutputDeveloperDebugMessage(web_contents(), banners::kIgnoredNoId,
+ is_debug_mode);
return false;
}
return true;
}
-bool AppBannerManagerAndroid::CheckFetcherMatchesContents() {
+bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) {
if (!web_contents())
return false;
if (!data_fetcher() ||
data_fetcher()->validated_url() != web_contents()->GetURL()) {
banners::OutputDeveloperNotShownMessage(
- web_contents(), banners::kUserNavigatedBeforeBannerShown);
+ web_contents(), banners::kUserNavigatedBeforeBannerShown,
+ is_debug_mode);
return false;
}
return true;
@@ -142,14 +147,14 @@ std::string AppBannerManagerAndroid::ExtractQueryValueForName(
}
AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher(
- base::WeakPtr<Delegate> weak_delegate) {
+ base::WeakPtr<Delegate> weak_delegate,
+ bool is_debug_mode) {
return new AppBannerDataFetcherAndroid(
- web_contents(),
- weak_delegate,
+ web_contents(), weak_delegate,
ShortcutHelper::GetIdealHomescreenIconSizeInDp(),
ShortcutHelper::GetMinimumHomescreenIconSizeInDp(),
ShortcutHelper::GetIdealSplashImageSizeInDp(),
- ShortcutHelper::GetMinimumSplashImageSizeInDp());
+ ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode);
}
bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
@@ -159,13 +164,13 @@ bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
const JavaParamRef<jstring>& japp_title,
const JavaParamRef<jstring>& japp_package,
const JavaParamRef<jstring>& jicon_url) {
- if (!CheckFetcherMatchesContents())
+ AppBannerDataFetcherAndroid* android_fetcher =
+ static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get());
+ if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode()))
return false;
GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url));
- AppBannerDataFetcherAndroid* android_fetcher =
- static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get());
return android_fetcher->ContinueFetching(
ConvertJavaStringToUTF16(env, japp_title),
ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url);
@@ -177,6 +182,14 @@ bool AppBannerManagerAndroid::IsFetcherActive(
return AppBannerManager::IsFetcherActive();
}
+void AppBannerManagerAndroid::RequestAppBanner(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ AppBannerManager::RequestAppBanner(web_contents()->GetMainFrame(),
+ web_contents()->GetLastCommittedURL(),
+ true);
+}
+
// static
bool AppBannerManagerAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
diff --git a/chrome/browser/android/banners/app_banner_manager_android.h b/chrome/browser/android/banners/app_banner_manager_android.h
index 1d60907..69a2b78 100644
--- a/chrome/browser/android/banners/app_banner_manager_android.h
+++ b/chrome/browser/android/banners/app_banner_manager_android.h
@@ -52,19 +52,27 @@ class AppBannerManagerAndroid : public AppBannerManager {
const base::android::JavaParamRef<jstring>& japp_package,
const base::android::JavaParamRef<jstring>& jicon_url);
+ // Requests the app banner. This method is called from the DevTools.
+ void RequestAppBanner(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& jobj);
+
protected:
AppBannerDataFetcher* CreateAppBannerDataFetcher(
- base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate) override;
+ base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate,
+ bool is_debug_mode) override;
private:
// AppBannerDataFetcher::Delegate overrides.
bool HandleNonWebApp(const std::string& platform,
const GURL& url,
- const std::string& id) override;
+ const std::string& id,
+ bool is_debug_mode) override;
- bool CheckPlatformAndId(const std::string& platform, const std::string& id);
+ bool CheckPlatformAndId(const std::string& platform,
+ const std::string& id,
+ bool is_debug_mode);
- bool CheckFetcherMatchesContents();
+ bool CheckFetcherMatchesContents(bool is_debug_mode);
std::string ExtractQueryValueForName(const GURL& url,
const std::string& name);
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index 664328e..ce94633 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -423,6 +423,15 @@ void TabWebContentsDelegateAndroid::AddNewContents(
delete new_contents;
}
+bool TabWebContentsDelegateAndroid::RequestAppBanner(
+ content::WebContents* web_contents) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
+ if (obj.is_null())
+ return false;
+ return Java_TabWebContentsDelegateAndroid_requestAppBanner(env, obj.obj());
+}
+
} // namespace android
} // namespace chrome
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.h b/chrome/browser/android/tab_web_contents_delegate_android.h
index 47b4234..383b198 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.h
+++ b/chrome/browser/android/tab_web_contents_delegate_android.h
@@ -87,6 +87,7 @@ class TabWebContentsDelegateAndroid
const gfx::Rect& initial_rect,
bool user_gesture,
bool* was_blocked) override;
+ bool RequestAppBanner(content::WebContents* web_contents) override;
private:
// NotificationObserver implementation.
diff --git a/chrome/browser/banners/app_banner_data_fetcher.cc b/chrome/browser/banners/app_banner_data_fetcher.cc
index 321e8d3..d953485 100644
--- a/chrome/browser/banners/app_banner_data_fetcher.cc
+++ b/chrome/browser/banners/app_banner_data_fetcher.cc
@@ -71,11 +71,11 @@ void AppBannerDataFetcher::SetTimeDeltaForTesting(int days) {
gTimeDeltaForTesting = base::TimeDelta::FromDays(days);
}
-AppBannerDataFetcher::AppBannerDataFetcher(
- content::WebContents* web_contents,
- base::WeakPtr<Delegate> delegate,
- int ideal_icon_size_in_dp,
- int minimum_icon_size_in_dp)
+AppBannerDataFetcher::AppBannerDataFetcher(content::WebContents* web_contents,
+ base::WeakPtr<Delegate> delegate,
+ int ideal_icon_size_in_dp,
+ int minimum_icon_size_in_dp,
+ bool is_debug_mode)
: WebContentsObserver(web_contents),
weak_delegate_(delegate),
ideal_icon_size_in_dp_(ideal_icon_size_in_dp),
@@ -83,6 +83,9 @@ AppBannerDataFetcher::AppBannerDataFetcher(
is_active_(false),
was_canceled_by_page_(false),
page_requested_prompt_(false),
+ is_debug_mode_(is_debug_mode ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kBypassAppBannerEngagementChecks)),
event_request_id_(-1) {
DCHECK(minimum_icon_size_in_dp <= ideal_icon_size_in_dp);
}
@@ -184,7 +187,8 @@ void AppBannerDataFetcher::OnBannerPromptReply(
!page_requested_prompt_) {
was_canceled_by_page_ = true;
referrer_ = referrer;
- OutputDeveloperNotShownMessage(web_contents, kRendererRequestCancel);
+ OutputDeveloperNotShownMessage(web_contents, kRendererRequestCancel,
+ is_debug_mode_);
return;
}
@@ -250,7 +254,7 @@ void AppBannerDataFetcher::OnDidHasManifest(bool has_manifest) {
if (!CheckFetcherIsStillAlive(web_contents) || !has_manifest) {
if (!has_manifest)
- OutputDeveloperNotShownMessage(web_contents, kNoManifest);
+ OutputDeveloperNotShownMessage(web_contents, kNoManifest, is_debug_mode_);
Cancel();
return;
@@ -268,7 +272,8 @@ void AppBannerDataFetcher::OnDidGetManifest(
return;
}
if (manifest.IsEmpty()) {
- OutputDeveloperNotShownMessage(web_contents, kManifestEmpty);
+ OutputDeveloperNotShownMessage(web_contents, kManifestEmpty,
+ is_debug_mode_);
Cancel();
return;
}
@@ -278,12 +283,13 @@ void AppBannerDataFetcher::OnDidGetManifest(
for (const auto& application : manifest.related_applications) {
std::string platform = base::UTF16ToUTF8(application.platform.string());
std::string id = base::UTF16ToUTF8(application.id.string());
- if (weak_delegate_->HandleNonWebApp(platform, application.url, id))
+ if (weak_delegate_->HandleNonWebApp(platform, application.url, id,
+ is_debug_mode_))
return;
}
}
- if (!IsManifestValidForWebApp(manifest, web_contents)) {
+ if (!IsManifestValidForWebApp(manifest, web_contents, is_debug_mode_)) {
Cancel();
return;
}
@@ -293,9 +299,9 @@ void AppBannerDataFetcher::OnDidGetManifest(
if (IsWebAppInstalled(web_contents->GetBrowserContext(),
manifest.start_url) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kBypassAppBannerEngagementChecks)) {
- OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded);
+ !is_debug_mode_) {
+ OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded,
+ is_debug_mode_);
Cancel();
return;
}
@@ -327,7 +333,8 @@ void AppBannerDataFetcher::OnDidCheckHasServiceWorker(
if (!has_service_worker) {
TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER);
- OutputDeveloperNotShownMessage(web_contents, kNoMatchingServiceWorker);
+ OutputDeveloperNotShownMessage(web_contents, kNoMatchingServiceWorker,
+ is_debug_mode_);
Cancel();
return;
}
@@ -345,7 +352,8 @@ void AppBannerDataFetcher::OnHasServiceWorker(
gfx::Screen::GetScreenFor(web_contents->GetNativeView()));
if (!FetchAppIcon(web_contents, icon_url)) {
- OutputDeveloperNotShownMessage(web_contents, kCannotDetermineBestIcon);
+ OutputDeveloperNotShownMessage(web_contents, kCannotDetermineBestIcon,
+ is_debug_mode_);
Cancel();
}
}
@@ -370,16 +378,18 @@ void AppBannerDataFetcher::OnAppIconFetched(const SkBitmap& bitmap) {
return;
}
if (bitmap.drawsNothing()) {
- OutputDeveloperNotShownMessage(web_contents, kNoIconAvailable);
+ OutputDeveloperNotShownMessage(web_contents, kNoIconAvailable,
+ is_debug_mode_);
Cancel();
return;
}
RecordCouldShowBanner();
- if (!CheckIfShouldShowBanner()) {
+ if (!is_debug_mode_ && !CheckIfShouldShowBanner()) {
// At this point, the only possible case is that the banner has been added
// to the homescreen, given all of the other checks that have been made.
- OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded);
+ OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded,
+ is_debug_mode_);
Cancel();
return;
}
@@ -419,8 +429,8 @@ bool AppBannerDataFetcher::CheckIfShouldShowBanner() {
bool AppBannerDataFetcher::CheckFetcherIsStillAlive(
content::WebContents* web_contents) {
if (!is_active_) {
- OutputDeveloperNotShownMessage(web_contents,
- kUserNavigatedBeforeBannerShown);
+ OutputDeveloperNotShownMessage(
+ web_contents, kUserNavigatedBeforeBannerShown, is_debug_mode_);
return false;
}
if (!web_contents) {
@@ -432,22 +442,25 @@ bool AppBannerDataFetcher::CheckFetcherIsStillAlive(
// static
bool AppBannerDataFetcher::IsManifestValidForWebApp(
const content::Manifest& manifest,
- content::WebContents* web_contents) {
+ content::WebContents* web_contents,
+ bool is_debug_mode) {
if (manifest.IsEmpty()) {
- OutputDeveloperNotShownMessage(web_contents, kManifestEmpty);
+ OutputDeveloperNotShownMessage(web_contents, kManifestEmpty, is_debug_mode);
return false;
}
if (!manifest.start_url.is_valid()) {
- OutputDeveloperNotShownMessage(web_contents, kStartURLNotValid);
+ OutputDeveloperNotShownMessage(web_contents, kStartURLNotValid,
+ is_debug_mode);
return false;
}
if (manifest.name.is_null() && manifest.short_name.is_null()) {
- OutputDeveloperNotShownMessage(web_contents,
- kManifestMissingNameOrShortName);
+ OutputDeveloperNotShownMessage(
+ web_contents, kManifestMissingNameOrShortName, is_debug_mode);
return false;
}
if (!DoesManifestContainRequiredIcon(manifest)) {
- OutputDeveloperNotShownMessage(web_contents, kManifestMissingSuitableIcon);
+ OutputDeveloperNotShownMessage(web_contents, kManifestMissingSuitableIcon,
+ is_debug_mode);
return false;
}
return true;
diff --git a/chrome/browser/banners/app_banner_data_fetcher.h b/chrome/browser/banners/app_banner_data_fetcher.h
index fe943f2..194bf0b 100644
--- a/chrome/browser/banners/app_banner_data_fetcher.h
+++ b/chrome/browser/banners/app_banner_data_fetcher.h
@@ -49,7 +49,8 @@ class AppBannerDataFetcher : public base::RefCountedThreadSafe<
// handled, and the fetcher needs to remain active and wait for a callback.
virtual bool HandleNonWebApp(const std::string& platform,
const GURL& url,
- const std::string& id) = 0;
+ const std::string& id,
+ bool is_debug_mode) = 0;
};
// Returns the current time.
@@ -61,7 +62,8 @@ class AppBannerDataFetcher : public base::RefCountedThreadSafe<
AppBannerDataFetcher(content::WebContents* web_contents,
base::WeakPtr<Delegate> weak_delegate,
int ideal_icon_size_in_dp,
- int minimum_icon_size_in_dp);
+ int minimum_icon_size_in_dp,
+ bool is_debug_mode);
// Begins creating a banner for the URL being displayed by the Delegate's
// WebContents.
@@ -89,6 +91,10 @@ class AppBannerDataFetcher : public base::RefCountedThreadSafe<
// by calling prompt() on the beforeinstallprompt Javascript event.
bool page_requested_prompt() { return page_requested_prompt_; }
+ // Returns true when it was created by the user action in DevTools or
+ // "bypass-app-banner-engagement-checks" flag is set.
+ bool is_debug_mode() const { return is_debug_mode_; }
+
// Returns the type of transition which triggered this fetch.
ui::PageTransition transition_type() { return transition_type_; }
@@ -172,7 +178,8 @@ class AppBannerDataFetcher : public base::RefCountedThreadSafe<
// Returns whether the given Manifest is following the requirements to show
// a web app banner.
static bool IsManifestValidForWebApp(const content::Manifest& manifest,
- content::WebContents* web_contents);
+ content::WebContents* web_contents,
+ bool is_debug_mode);
const base::WeakPtr<Delegate> weak_delegate_;
const int ideal_icon_size_in_dp_;
@@ -181,6 +188,7 @@ class AppBannerDataFetcher : public base::RefCountedThreadSafe<
bool is_active_;
bool was_canceled_by_page_;
bool page_requested_prompt_;
+ const bool is_debug_mode_;
ui::PageTransition transition_type_;
int event_request_id_;
scoped_ptr<SkBitmap> app_icon_;
diff --git a/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc b/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc
index c868268..57d3883 100644
--- a/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc
+++ b/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc
@@ -73,7 +73,8 @@ class AppBannerDataFetcherBrowserTest : public InProcessBrowserTest,
bool HandleNonWebApp(const std::string& platform,
const GURL& url,
- const std::string& id) override {
+ const std::string& id,
+ bool is_debug_mode) override {
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
non_web_platform_ = platform;
return false;
@@ -95,9 +96,8 @@ class AppBannerDataFetcherBrowserTest : public InProcessBrowserTest,
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
scoped_refptr<AppBannerDataFetcherDesktop> fetcher(
- new AppBannerDataFetcherDesktop(web_contents,
- weak_factory_.GetWeakPtr(),
- 128, 128));
+ new AppBannerDataFetcherDesktop(
+ web_contents, weak_factory_.GetWeakPtr(), 128, 128, false));
base::HistogramTester histograms;
base::RunLoop run_loop;
diff --git a/chrome/browser/banners/app_banner_data_fetcher_desktop.cc b/chrome/browser/banners/app_banner_data_fetcher_desktop.cc
index 5cc7fa8..ae69cff5 100644
--- a/chrome/browser/banners/app_banner_data_fetcher_desktop.cc
+++ b/chrome/browser/banners/app_banner_data_fetcher_desktop.cc
@@ -23,12 +23,13 @@ AppBannerDataFetcherDesktop::AppBannerDataFetcherDesktop(
content::WebContents* web_contents,
base::WeakPtr<Delegate> weak_delegate,
int ideal_icon_size_in_dp,
- int minimum_icon_size_in_dp)
+ int minimum_icon_size_in_dp,
+ bool is_debug_mode)
: AppBannerDataFetcher(web_contents,
weak_delegate,
ideal_icon_size_in_dp,
- minimum_icon_size_in_dp) {
-}
+ minimum_icon_size_in_dp,
+ is_debug_mode) {}
AppBannerDataFetcherDesktop::~AppBannerDataFetcherDesktop() {
}
diff --git a/chrome/browser/banners/app_banner_data_fetcher_desktop.h b/chrome/browser/banners/app_banner_data_fetcher_desktop.h
index 1915e880..3bef84a 100644
--- a/chrome/browser/banners/app_banner_data_fetcher_desktop.h
+++ b/chrome/browser/banners/app_banner_data_fetcher_desktop.h
@@ -22,7 +22,8 @@ class AppBannerDataFetcherDesktop : public AppBannerDataFetcher {
AppBannerDataFetcherDesktop(content::WebContents* web_contents,
base::WeakPtr<Delegate> weak_delegate,
int ideal_icon_size_in_dp,
- int minimum_icon_size_in_dp);
+ int minimum_icon_size_in_dp,
+ bool is_debug_mode);
// Callback for finishing bookmark app creation
void FinishCreateBookmarkApp(const extensions::Extension* extension,
diff --git a/chrome/browser/banners/app_banner_data_fetcher_unittest.cc b/chrome/browser/banners/app_banner_data_fetcher_unittest.cc
index 3b68086..4be44fe 100644
--- a/chrome/browser/banners/app_banner_data_fetcher_unittest.cc
+++ b/chrome/browser/banners/app_banner_data_fetcher_unittest.cc
@@ -36,7 +36,10 @@ class AppBannerDataFetcherUnitTest : public testing::Test {
// The second argument is the web_contents pointer, which is used for
// developer debug logging to the console. The logging is skipped inside the
// method if a null web_contents pointer is provided, so this is safe.
- return AppBannerDataFetcher::IsManifestValidForWebApp(manifest, nullptr);
+ // The third argument is the is_debug_mode boolean value, which is true only
+ // when it is triggered by the developer's action in DevTools.
+ return AppBannerDataFetcher::IsManifestValidForWebApp(manifest, nullptr,
+ false);
}
};
diff --git a/chrome/browser/banners/app_banner_debug_log.cc b/chrome/browser/banners/app_banner_debug_log.cc
index e1b06f9..99e26f7 100644
--- a/chrome/browser/banners/app_banner_debug_log.cc
+++ b/chrome/browser/banners/app_banner_debug_log.cc
@@ -4,8 +4,6 @@
#include "chrome/browser/banners/app_banner_debug_log.h"
-#include "base/command_line.h"
-#include "chrome/common/chrome_switches.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -33,6 +31,7 @@ const char kManifestMissingNameOrShortName[] =
const char kManifestMissingSuitableIcon[] =
"manifest does not contain a suitable icon - PNG format of at least "
"144x144px is required, and the sizes attribute must be set";
+const char kNotLoadedInMainFrame[] = "page not loaded in the main frame";
const char kNotServedFromSecureOrigin[] =
"page not served from a secure origin";
// The leading space is intentional as another string is prepended.
@@ -44,19 +43,19 @@ const char kIgnoredIdsDoNotMatch[] =
"manifest, but they do not match";
void OutputDeveloperNotShownMessage(content::WebContents* web_contents,
- const std::string& message) {
- OutputDeveloperDebugMessage(web_contents, "not shown: " + message);
+ const std::string& message,
+ bool is_debug_mode) {
+ OutputDeveloperDebugMessage(web_contents, "not shown: " + message,
+ is_debug_mode);
}
void OutputDeveloperDebugMessage(content::WebContents* web_contents,
- const std::string& message) {
- std::string log_message = "App banner " + message;
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kBypassAppBannerEngagementChecks) &&
- web_contents) {
- web_contents->GetMainFrame()->AddMessageToConsole(
- content::CONSOLE_MESSAGE_LEVEL_DEBUG, log_message);
- }
+ const std::string& message,
+ bool is_debug_mode) {
+ if (!is_debug_mode || !web_contents)
+ return;
+ web_contents->GetMainFrame()->AddMessageToConsole(
+ content::CONSOLE_MESSAGE_LEVEL_DEBUG, "App banner " + message);
}
} // namespace banners
diff --git a/chrome/browser/banners/app_banner_debug_log.h b/chrome/browser/banners/app_banner_debug_log.h
index c5767c8..0d07908 100644
--- a/chrome/browser/banners/app_banner_debug_log.h
+++ b/chrome/browser/banners/app_banner_debug_log.h
@@ -25,6 +25,7 @@ extern const char kUserNavigatedBeforeBannerShown[];
extern const char kStartURLNotValid[];
extern const char kManifestMissingNameOrShortName[];
extern const char kManifestMissingSuitableIcon[];
+extern const char kNotLoadedInMainFrame[];
extern const char kNotServedFromSecureOrigin[];
extern const char kIgnoredNotSupportedOnAndroid[];
extern const char kIgnoredNoId[];
@@ -33,12 +34,14 @@ extern const char kIgnoredIdsDoNotMatch[];
// Logs a message to the main console if a banner could not be shown
// and the engagement checks have been bypassed.
void OutputDeveloperNotShownMessage(content::WebContents* web_contents,
- const std::string& message);
+ const std::string& message,
+ bool is_debug_mode);
// Logs a debugging message to the main console if the engagement checks have
// been bypassed.
void OutputDeveloperDebugMessage(content::WebContents* web_contents,
- const std::string& message);
+ const std::string& message,
+ bool is_debug_mode);
} // namespace banners
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc
index e984f2d..6fe5b9c 100644
--- a/chrome/browser/banners/app_banner_manager.cc
+++ b/chrome/browser/banners/app_banner_manager.cc
@@ -70,14 +70,19 @@ void AppBannerManager::DidNavigateMainFrame(
last_transition_type_ = params.transition;
}
-void AppBannerManager::DidFinishLoad(
+void AppBannerManager::RequestAppBanner(
content::RenderFrameHost* render_frame_host,
- const GURL& validated_url) {
- if (render_frame_host->GetParent())
+ const GURL& validated_url,
+ bool is_debug_mode) {
+ if (render_frame_host->GetParent()) {
+ OutputDeveloperNotShownMessage(web_contents(), kNotLoadedInMainFrame,
+ is_debug_mode);
return;
+ }
if (data_fetcher_.get() && data_fetcher_->is_active() &&
- URLsAreForTheSamePage(data_fetcher_->validated_url(), validated_url)) {
+ URLsAreForTheSamePage(data_fetcher_->validated_url(), validated_url) &&
+ !is_debug_mode) {
return;
}
@@ -85,18 +90,29 @@ void AppBannerManager::DidFinishLoad(
// URL is invalid.
if (!content::IsOriginSecure(validated_url) &&
!gDisableSecureCheckForTesting) {
- OutputDeveloperNotShownMessage(web_contents(), kNotServedFromSecureOrigin);
+ OutputDeveloperNotShownMessage(web_contents(), kNotServedFromSecureOrigin,
+ is_debug_mode);
return;
}
// Kick off the data retrieval pipeline.
- data_fetcher_ = CreateAppBannerDataFetcher(weak_factory_.GetWeakPtr());
+ data_fetcher_ =
+ CreateAppBannerDataFetcher(weak_factory_.GetWeakPtr(), is_debug_mode);
data_fetcher_->Start(validated_url, last_transition_type_);
}
+void AppBannerManager::DidFinishLoad(
+ content::RenderFrameHost* render_frame_host,
+ const GURL& validated_url) {
+ // The third argument is the is_debug_mode boolean value, which is true only
+ // when it is triggered by the developer's action in DevTools.
+ RequestAppBanner(render_frame_host, validated_url, false /* is_debug_mode */);
+}
+
bool AppBannerManager::HandleNonWebApp(const std::string& platform,
const GURL& url,
- const std::string& id) {
+ const std::string& id,
+ bool is_debug_mode) {
return false;
}
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h
index c11b4cb..efcf332 100644
--- a/chrome/browser/banners/app_banner_manager.h
+++ b/chrome/browser/banners/app_banner_manager.h
@@ -39,6 +39,12 @@ class AppBannerManager : public content::WebContentsObserver,
// Returns whether or not the URLs match for everything except for the ref.
static bool URLsAreForTheSamePage(const GURL& first, const GURL& second);
+ // Requests an app banner. Set |is_debug_mode| when it is triggered by the
+ // developer's action in DevTools.
+ void RequestAppBanner(content::RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ bool is_debug_mode);
+
AppBannerManager();
~AppBannerManager() override;
@@ -49,7 +55,8 @@ class AppBannerManager : public content::WebContentsObserver,
// Creates an AppBannerDataFetcher, which constructs an app banner.
virtual AppBannerDataFetcher* CreateAppBannerDataFetcher(
- base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate) = 0;
+ base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate,
+ bool is_debug_mode) = 0;
// Return whether the AppBannerDataFetcher is active.
bool IsFetcherActive();
@@ -68,7 +75,8 @@ class AppBannerManager : public content::WebContentsObserver,
// AppBannerDataFetcher::Delegate overrides.
bool HandleNonWebApp(const std::string& platform,
const GURL& url,
- const std::string& id) override;
+ const std::string& id,
+ bool is_debug_mode) override;
// Cancels an active DataFetcher, stopping its banners from appearing.
void CancelActiveFetcher();
diff --git a/chrome/browser/banners/app_banner_manager_desktop.cc b/chrome/browser/banners/app_banner_manager_desktop.cc
index d3aa3bf..01b8e80 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.cc
+++ b/chrome/browser/banners/app_banner_manager_desktop.cc
@@ -31,10 +31,11 @@ bool AppBannerManagerDesktop::IsEnabled() {
}
AppBannerDataFetcher* AppBannerManagerDesktop::CreateAppBannerDataFetcher(
- base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate) {
+ base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate,
+ bool is_debug_mode) {
return new AppBannerDataFetcherDesktop(web_contents(), weak_delegate,
- kMinimumIconSize,
- kMinimumIconSize);
+ kMinimumIconSize, kMinimumIconSize,
+ is_debug_mode);
}
AppBannerManagerDesktop::AppBannerManagerDesktop(
diff --git a/chrome/browser/banners/app_banner_manager_desktop.h b/chrome/browser/banners/app_banner_manager_desktop.h
index fc40997..c45a821 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.h
+++ b/chrome/browser/banners/app_banner_manager_desktop.h
@@ -21,7 +21,8 @@ class AppBannerManagerDesktop
protected:
AppBannerDataFetcher* CreateAppBannerDataFetcher(
- base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate) override;
+ base::WeakPtr<AppBannerDataFetcher::Delegate> weak_delegate,
+ bool is_debug_mode) override;
private:
explicit AppBannerManagerDesktop(content::WebContents* web_contents);
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 996e70c..acc57b4d 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -36,6 +36,7 @@
#include "chrome/browser/background/background_contents.h"
#include "chrome/browser/background/background_contents_service.h"
#include "chrome/browser/background/background_contents_service_factory.h"
+#include "chrome/browser/banners/app_banner_manager_desktop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/character_encoding.h"
@@ -1446,6 +1447,17 @@ scoped_ptr<content::BluetoothChooser> Browser::RunBluetoothChooser(
return std::move(bluetooth_chooser_desktop);
}
+bool Browser::RequestAppBanner(content::WebContents* web_contents) {
+ banners::AppBannerManagerDesktop* manager =
+ banners::AppBannerManagerDesktop::FromWebContents(web_contents);
+ if (manager) {
+ manager->RequestAppBanner(web_contents->GetMainFrame(),
+ web_contents->GetLastCommittedURL(), true);
+ return true;
+ }
+ return false;
+}
+
bool Browser::IsMouseLocked() const {
return exclusive_access_manager_->mouse_lock_controller()->IsMouseLocked();
}
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 13ec6b4..daeb5ae 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -473,6 +473,7 @@ class Browser : public TabStripModelObserver,
content::WebContents* web_contents,
const content::BluetoothChooser::EventHandler& event_handler,
const GURL& origin) override;
+ bool RequestAppBanner(content::WebContents* web_contents) override;
bool is_type_tabbed() const { return type_ == TYPE_TABBED; }
bool is_type_popup() const { return type_ == TYPE_POPUP; }
diff --git a/components/web_contents_delegate_android/web_contents_delegate_android.cc b/components/web_contents_delegate_android/web_contents_delegate_android.cc
index a95a269..34fc617 100644
--- a/components/web_contents_delegate_android/web_contents_delegate_android.cc
+++ b/components/web_contents_delegate_android/web_contents_delegate_android.cc
@@ -428,6 +428,12 @@ void WebContentsDelegateAndroid::MoveValidationMessage(
rwhv->GetRenderWidgetHost(), anchor_in_root_view);
}
}
+
+bool WebContentsDelegateAndroid::RequestAppBanner(
+ content::WebContents* web_contents) {
+ return false;
+}
+
// ----------------------------------------------------------------------------
// Native JNI methods
// ----------------------------------------------------------------------------
diff --git a/components/web_contents_delegate_android/web_contents_delegate_android.h b/components/web_contents_delegate_android/web_contents_delegate_android.h
index 1105673..f2ed5d9 100644
--- a/components/web_contents_delegate_android/web_contents_delegate_android.h
+++ b/components/web_contents_delegate_android/web_contents_delegate_android.h
@@ -112,6 +112,7 @@ class WebContentsDelegateAndroid : public content::WebContentsDelegate {
void HideValidationMessage(content::WebContents* web_contents) override;
void MoveValidationMessage(content::WebContents* web_contents,
const gfx::Rect& anchor_in_root_view) override;
+ bool RequestAppBanner(content::WebContents* web_contents) override;
protected:
base::android::ScopedJavaLocalRef<jobject> GetJavaDelegate(JNIEnv* env) const;
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc
index 7e79a72..e717572 100644
--- a/content/browser/devtools/protocol/page_handler.cc
+++ b/content/browser/devtools/protocol/page_handler.cc
@@ -357,6 +357,14 @@ Response PageHandler::SetColorPickerEnabled(bool enabled) {
return Response::OK();
}
+Response PageHandler::RequestAppBanner(bool* result) {
+ WebContentsImpl* web_contents = GetWebContents();
+ if (!web_contents)
+ return Response::InternalError("Could not connect to view");
+ *result = web_contents->GetDelegate()->RequestAppBanner(web_contents);
+ return Response::OK();
+}
+
WebContentsImpl* PageHandler::GetWebContents() {
return host_ ?
static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) :
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h
index 02b685a..d45e581 100644
--- a/content/browser/devtools/protocol/page_handler.h
+++ b/content/browser/devtools/protocol/page_handler.h
@@ -77,6 +77,7 @@ class PageHandler : public NotificationObserver {
const std::string& security_origin);
Response SetColorPickerEnabled(bool enabled);
+ Response RequestAppBanner(bool* result);
private:
WebContentsImpl* GetWebContents();
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 0a1d3f1..165488f 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -259,4 +259,8 @@ void WebContentsDelegate::ShowCertificateViewerInDevTools(
int cert_id) {
}
+bool WebContentsDelegate::RequestAppBanner(content::WebContents* web_contents) {
+ return false;
+}
+
} // namespace content
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index ed46e43..4145d4a 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -523,6 +523,9 @@ class CONTENT_EXPORT WebContentsDelegate {
// compositor proto. This is used in Blimp mode.
virtual void ForwardCompositorProto(const std::vector<uint8_t>& proto) {}
+ // Requests the app banner. This method is called from the DevTools.
+ virtual bool RequestAppBanner(content::WebContents* web_contents);
+
protected:
virtual ~WebContentsDelegate();
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
index cd7c402..e90169c 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
@@ -373,6 +373,11 @@ WebInspector.DeviceModeModel.prototype = {
this._target = null;
},
+ requestAppBanner: function()
+ {
+ this._target.pageAgent().requestAppBanner();
+ },
+
_scaleSettingChanged: function()
{
this._calculateAndEmulate(true);
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
index 24f99c2..5411b80 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
@@ -635,6 +635,7 @@ WebInspector.DeviceModeView.Toolbar.prototype = {
contextMenu.appendCheckboxItem(WebInspector.UIString("Show media queries"), this._toggleMediaInspector.bind(this), this._showMediaInspectorSetting.get(), this._model.type() === WebInspector.DeviceModeModel.Type.None);
contextMenu.appendCheckboxItem(WebInspector.UIString("Show rulers"), this._toggleRulers.bind(this), this._showRulersSetting.get(), this._model.type() === WebInspector.DeviceModeModel.Type.None);
contextMenu.appendItem(WebInspector.UIString("Configure network\u2026"), this._openNetworkConfig.bind(this), false);
+ contextMenu.appendItemsAtLocation("deviceModeMenu");
},
_toggleMediaInspector: function()
@@ -1030,9 +1031,15 @@ WebInspector.DeviceModeView.ActionDelegate.prototype = {
*/
handleAction: function(context, actionId)
{
- if (actionId === "emulation.toggle-device-mode" && WebInspector.DeviceModeView._wrapperInstance) {
- WebInspector.DeviceModeView._wrapperInstance._toggleDeviceMode();
- return true;
+ if (WebInspector.DeviceModeView._wrapperInstance) {
+ if (actionId === "emulation.toggle-device-mode") {
+ WebInspector.DeviceModeView._wrapperInstance._toggleDeviceMode();
+ return true;
+ }
+ if (actionId === "emulation.request-app-banner") {
+ WebInspector.DeviceModeView._wrapperInstance._requestAppBanner();
+ return true;
+ }
}
return false;
}
@@ -1085,5 +1092,10 @@ WebInspector.DeviceModeView.Wrapper.prototype = {
}
},
+ _requestAppBanner: function()
+ {
+ this._deviceModeView._model.requestAppBanner();
+ },
+
__proto__: WebInspector.VBox.prototype
}
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/module.json b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
index fa6d8bf..8cafc67 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
@@ -97,6 +97,18 @@
"persistence": "closeable",
"order": 100,
"className": "WebInspector.SensorsView"
+ },
+ {
+ "type": "@WebInspector.ActionDelegate",
+ "actionId": "emulation.request-app-banner",
+ "className": "WebInspector.DeviceModeView.ActionDelegate",
+ "title": "Request app banner"
+ },
+ {
+ "type": "context-menu-item",
+ "location": "deviceModeMenu/tools",
+ "order": 10,
+ "actionId": "emulation.request-app-banner"
}
],
"dependencies": [
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
index f9571bc..2f0cd91 100644
--- a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
+++ b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
@@ -92,6 +92,12 @@ WebInspector.ScreencastApp.prototype = {
this._rootSplitWidget.showBoth();
else
this._rootSplitWidget.hideMain();
+ },
+
+ _requestAppBanner: function()
+ {
+ if (this._target && this._target.pageAgent())
+ this._target.pageAgent().requestAppBanner();
}
};
@@ -128,6 +134,33 @@ WebInspector.ScreencastApp.ToolbarButtonProvider.prototype = {
}
}
+
+/**
+ * @constructor
+ * @implements {WebInspector.ActionDelegate}
+ */
+WebInspector.ScreencastApp.ActionDelegate = function()
+{
+};
+
+WebInspector.ScreencastApp.ActionDelegate.prototype = {
+ /**
+ * @override
+ * @param {!WebInspector.Context} context
+ * @param {string} actionId
+ * @return {boolean}
+ */
+ handleAction: function(context, actionId)
+ {
+ if (actionId === "screencast.request-app-banner") {
+ WebInspector.ScreencastApp._instance()._requestAppBanner()
+ return true;
+ }
+ return false;
+ }
+};
+
+
/**
* @constructor
* @implements {WebInspector.AppProvider}
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/module.json b/third_party/WebKit/Source/devtools/front_end/screencast/module.json
index 9365d5a..ed35304 100644
--- a/third_party/WebKit/Source/devtools/front_end/screencast/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/screencast/module.json
@@ -10,6 +10,19 @@
"className": "WebInspector.ScreencastApp.ToolbarButtonProvider",
"order": 1,
"location": "main-toolbar-left"
+ },
+ {
+ "type": "@WebInspector.ActionDelegate",
+ "actionId": "screencast.request-app-banner",
+ "className": "WebInspector.ScreencastApp.ActionDelegate",
+ "title": "Request app banner"
+ },
+ {
+ "type": "context-menu-item",
+ "condition": "remoteFrontend",
+ "location": "mainMenu/tools",
+ "order": 10,
+ "actionId": "screencast.request-app-banner"
}
],
"dependencies": [
diff --git a/third_party/WebKit/Source/devtools/protocol.json b/third_party/WebKit/Source/devtools/protocol.json
index bb97598..e3b5a0b 100644
--- a/third_party/WebKit/Source/devtools/protocol.json
+++ b/third_party/WebKit/Source/devtools/protocol.json
@@ -451,6 +451,14 @@
],
"hidden": true,
"description": "Sets overlay message."
+ },
+ {
+ "name": "requestAppBanner",
+ "returns": [
+ { "name": "result", "type": "boolean" }
+ ],
+ "hidden": true,
+ "handlers": ["browser"]
}
],
"events": [