blob: c12f2a800d2e85b0c09bcadd22e0abbd2c893edc [file] [log] [blame]
// 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.
#include <string>
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h"
#include "chrome/browser/sharesheet/sharesheet_service.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
#include "chrome/browser/ui/web_applications/web_app_browsertest_base.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "ui/base/base_window.h"
#include "url/gurl.h"
namespace {
content::EvalJsResult ReadTextContent(content::WebContents* web_contents,
const char* id) {
const std::string script =
base::StringPrintf("document.getElementById('%s').textContent", id);
return content::EvalJs(web_contents, script);
}
class ScopedSharesheetAppSelection {
public:
explicit ScopedSharesheetAppSelection(const std::string& app_id) {
SetSelectedSharesheetApp(app_id);
}
ScopedSharesheetAppSelection(const ScopedSharesheetAppSelection&) = delete;
ScopedSharesheetAppSelection& operator=(const ScopedSharesheetAppSelection&) =
delete;
~ScopedSharesheetAppSelection() { SetSelectedSharesheetApp(std::string()); }
private:
static void SetSelectedSharesheetApp(const std::string& app_id) {
sharesheet::SharesheetService::SetSelectedAppForTesting(
base::UTF8ToUTF16(app_id));
}
};
} // namespace
namespace web_app {
class ShareToTargetBrowserTest : public WebAppBrowserTestBase,
public testing::WithParamInterface<
apps::test::LinkCapturingFeatureVersion> {
public:
ShareToTargetBrowserTest() {
scoped_feature_list_.InitWithFeaturesAndParameters(
apps::test::GetFeaturesToEnableLinkCapturingUX(GetParam()), {});
}
std::string ExecuteShare(const std::string& script) {
const GURL url = https_server()->GetURL("/webshare/index.html");
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
content::WebContents* const contents =
browser()->tab_strip_model()->GetActiveWebContents();
return content::EvalJs(contents, script).ExtractString();
}
content::WebContents* ShareToTarget(const std::string& script) {
ui_test_utils::AllBrowserTabAddedWaiter waiter;
EXPECT_EQ("share succeeded", ExecuteShare(script));
content::WebContents* contents = waiter.Wait();
EXPECT_TRUE(content::WaitForLoadStop(contents));
// For Ash builds, we could verify no files have been added to Recent Files.
return contents;
}
void InstallWebAppFromManifest(const GURL& app_url) {
DCHECK(app_id_.empty());
app_id_ = web_app::InstallWebAppFromManifest(browser(), app_url);
// Enabling link capturing to ensure it doesn't interfere.
EXPECT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id_),
base::ok());
}
const webapps::AppId& app_id() const { return app_id_; }
private:
// WebAppBrowserTestBase:
void TearDownOnMainThread() override {
if (!app_id_.empty()) {
CloseAppWindows(app_id_);
}
WebAppBrowserTestBase::TearDownOnMainThread();
}
static void CloseAppWindows(const webapps::AppId& app_id) {
ForEachCurrentBrowserWindowInterfaceOrderedByActivation(
[&app_id](BrowserWindowInterface* browser) {
const web_app::AppBrowserController* const app_controller =
browser->GetAppBrowserController();
if (app_controller && app_controller->app_id() == app_id) {
browser->GetWindow()->Close();
}
return true;
});
}
webapps::AppId app_id_;
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_P(ShareToTargetBrowserTest, ShareToPosterWebApp) {
const GURL app_url = https_server()->GetURL("/web_share_target/poster.html");
InstallWebAppFromManifest(app_url);
ScopedSharesheetAppSelection selection(app_id());
// Poster web app does not accept image shares.
EXPECT_EQ("share failed: AbortError: Share canceled",
ExecuteShare("share_single_file()"));
content::WebContents* web_contents = ShareToTarget("share_title()");
EXPECT_EQ("Subject", ReadTextContent(web_contents, "headline"));
web_contents = ShareToTarget("share_url()");
EXPECT_EQ("https://example.com/", ReadTextContent(web_contents, "link"));
}
IN_PROC_BROWSER_TEST_P(ShareToTargetBrowserTest, ShareToChartsWebApp) {
const GURL app_url = https_server()->GetURL("/web_share_target/charts.html");
InstallWebAppFromManifest(app_url);
ScopedSharesheetAppSelection selection(app_id());
content::WebContents* web_contents = ShareToTarget("share_single_file()");
EXPECT_EQ("************", ReadTextContent(web_contents, "notes"));
web_contents = ShareToTarget("share_url()");
EXPECT_EQ("https://example.com/", ReadTextContent(web_contents, "link"));
}
IN_PROC_BROWSER_TEST_P(ShareToTargetBrowserTest, ShareImage) {
const GURL app_url =
https_server()->GetURL("/web_share_target/multimedia.html");
InstallWebAppFromManifest(app_url);
ScopedSharesheetAppSelection selection(app_id());
content::WebContents* web_contents = ShareToTarget("share_single_file()");
EXPECT_EQ(std::string(12, '*'), ReadTextContent(web_contents, "image"));
EXPECT_EQ("sample.webp", ReadTextContent(web_contents, "image_filename"));
}
IN_PROC_BROWSER_TEST_P(ShareToTargetBrowserTest, ShareMultimedia) {
const GURL app_url =
https_server()->GetURL("/web_share_target/multimedia.html");
InstallWebAppFromManifest(app_url);
ScopedSharesheetAppSelection selection(app_id());
content::WebContents* web_contents = ShareToTarget("share_multiple_files()");
EXPECT_EQ(std::string(345, '*'), ReadTextContent(web_contents, "audio"));
EXPECT_EQ(std::string(67890, '*'), ReadTextContent(web_contents, "video"));
EXPECT_EQ(std::string(1, '*'), ReadTextContent(web_contents, "image"));
EXPECT_EQ("sam.ple.mp3", ReadTextContent(web_contents, "audio_filename"));
EXPECT_EQ("sample.mp4", ReadTextContent(web_contents, "video_filename"));
EXPECT_EQ("sam_ple.gif", ReadTextContent(web_contents, "image_filename"));
}
IN_PROC_BROWSER_TEST_P(ShareToTargetBrowserTest, ShareToPartialWild) {
const GURL app_url =
https_server()->GetURL("/web_share_target/partial-wild.html");
InstallWebAppFromManifest(app_url);
ScopedSharesheetAppSelection selection(app_id());
// Partial Wild does not accept text shares.
EXPECT_EQ("share failed: AbortError: Share canceled",
ExecuteShare("share_title()"));
content::WebContents* web_contents = ShareToTarget("share_single_file()");
EXPECT_EQ("************", ReadTextContent(web_contents, "graphs"));
}
INSTANTIATE_TEST_SUITE_P(
All,
ShareToTargetBrowserTest,
// Ensure share target still works with navigation capturing v2.
testing::Values(apps::test::LinkCapturingFeatureVersion::kV1DefaultOff,
apps::test::LinkCapturingFeatureVersion::kV2DefaultOff,
apps::test::LinkCapturingFeatureVersion::
kV2DefaultOffCaptureExistingFrames),
apps::test::LinkCapturingVersionToString);
} // namespace web_app