File: isolated_web_app_test_utils.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (236 lines) | stat: -rw-r--r-- 8,920 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// 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.

#ifndef CHROME_BROWSER_UI_WEB_APPLICATIONS_TEST_ISOLATED_WEB_APP_TEST_UTILS_H_
#define CHROME_BROWSER_UI_WEB_APPLICATIONS_TEST_ISOLATED_WEB_APP_TEST_UTILS_H_

#include <memory>
#include <string>
#include <string_view>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "base/version.h"
#include "chrome/browser/ui/web_applications/web_app_browsertest_base.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_source.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_storage_location.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "components/version_info/channel.h"
#include "components/webapps/browser/installable/installable_metrics.h"
#include "extensions/common/features/feature_channel.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/base/window_open_disposition.h"

class Browser;
class GURL;
class Profile;

namespace content {
class RenderFrameHost;
}  // namespace content

namespace net::test_server {
class EmbeddedTestServer;
}  // namespace net::test_server

namespace url {
class Origin;
}  // namespace url

namespace web_app {

class IsolatedWebAppUrlInfo;

class IsolatedWebAppBrowserTestHarness : public WebAppBrowserTestBase {
 public:
  IsolatedWebAppBrowserTestHarness();
  IsolatedWebAppBrowserTestHarness(const IsolatedWebAppBrowserTestHarness&) =
      delete;
  IsolatedWebAppBrowserTestHarness& operator=(
      const IsolatedWebAppBrowserTestHarness&) = delete;
  ~IsolatedWebAppBrowserTestHarness() override;

 protected:
  std::unique_ptr<net::EmbeddedTestServer> CreateAndStartServer(
      base::FilePath::StringViewType chrome_test_data_relative_root);
  IsolatedWebAppUrlInfo InstallDevModeProxyIsolatedWebApp(
      const url::Origin& origin);
  content::RenderFrameHost* OpenApp(const webapps::AppId& app_id,
                                    std::string_view path = "");
  content::RenderFrameHost* NavigateToURLInNewTab(
      Browser* window,
      const GURL& url,
      WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB);

  Browser* GetBrowserFromFrame(content::RenderFrameHost* frame);

 private:
  base::test::ScopedFeatureList iwa_scoped_feature_list_;
  // Various IsolatedWebAppBrowsing tests fail on official builds because
  // stable channel doesn't enable a required feature.
  // TODO(b/309153867): Remove this when underlying issue is figured out.
  extensions::ScopedCurrentChannel channel_{version_info::Channel::CANARY};
};

class UpdateDiscoveryTaskResultWaiter
    : public IsolatedWebAppUpdateManager::Observer {
  using TaskResultCallback = base::OnceCallback<void(
      IsolatedWebAppUpdateDiscoveryTask::CompletionStatus status)>;

 public:
  UpdateDiscoveryTaskResultWaiter(WebAppProvider& provider,
                                  const webapps::AppId expected_app_id,
                                  TaskResultCallback callback);
  ~UpdateDiscoveryTaskResultWaiter() override;

  // IsolatedWebAppUpdateManager::Observer:
  void OnUpdateDiscoveryTaskCompleted(
      const webapps::AppId& app_id,
      IsolatedWebAppUpdateDiscoveryTask::CompletionStatus status) override;

 private:
  const webapps::AppId expected_app_id_;
  TaskResultCallback callback_;
  const raw_ref<WebAppProvider> provider_;

  base::ScopedObservation<IsolatedWebAppUpdateManager,
                          IsolatedWebAppUpdateManager::Observer>
      observation_{this};
};

class UpdateApplyTaskResultWaiter
    : public IsolatedWebAppUpdateManager::Observer {
  using TaskResultCallback = base::OnceCallback<void(
      IsolatedWebAppUpdateApplyTask::CompletionStatus status)>;

 public:
  UpdateApplyTaskResultWaiter(WebAppProvider& provider,
                              const webapps::AppId expected_app_id,
                              TaskResultCallback callback);
  ~UpdateApplyTaskResultWaiter() override;

  // IsolatedWebAppUpdateManager::Observer:
  void OnUpdateApplyTaskCompleted(
      const webapps::AppId& app_id,
      IsolatedWebAppUpdateApplyTask::CompletionStatus status) override;

 private:
  const webapps::AppId expected_app_id_;
  TaskResultCallback callback_;
  const raw_ref<WebAppProvider> provider_;

  base::ScopedObservation<IsolatedWebAppUpdateManager,
                          IsolatedWebAppUpdateManager::Observer>
      observation_{this};
};

std::unique_ptr<net::EmbeddedTestServer> CreateAndStartDevServer(
    base::FilePath::StringViewType chrome_test_data_relative_root);

IsolatedWebAppUrlInfo InstallDevModeProxyIsolatedWebApp(
    Profile* profile,
    const url::Origin& proxy_origin);

content::RenderFrameHost* OpenIsolatedWebApp(Profile* profile,
                                             const webapps::AppId& app_id,
                                             std::string_view path = "");

void CreateIframe(content::RenderFrameHost* parent_frame,
                  const std::string& iframe_id,
                  const GURL& url,
                  const std::string& permissions_policy);

// Simulates navigating `web_contents` main frame to the provided isolated-app:
// URL for unit tests. `TestWebContents::NavigateAndCommit` won't work for IWAs
// because they require COI headers, but the IsolatedWebAppURLLoaderFactory
// that injects them isn't run in RenderViewHostTestHarness-based unit tests.
void SimulateIsolatedWebAppNavigation(content::WebContents* web_contents,
                                      const GURL& url);

// Commits a pending IWA navigation in `web_contents`. This should be called
// instead of `RenderFrameHostTester::CommitPendingLoad` in IWAs because COI
// headers need to be injected.
void CommitPendingIsolatedWebAppNavigation(content::WebContents* web_contents);

// TODO(cmfcmf): Move more test utils into this `test` namespace
namespace test {
namespace {
using ::testing::AllOf;
using ::testing::ExplainMatchResult;
using ::testing::Field;
using ::testing::Optional;
using ::testing::Pointee;
using ::testing::Property;
}  // namespace

MATCHER_P(IsInIwaRandomDir, profile_directory, "") {
  *result_listener << "where the profile directory is " << profile_directory;
  return arg.DirName().DirName() == profile_directory.Append(kIwaDirName) &&
         arg.BaseName() == base::FilePath(kMainSwbnFileName);
}

MATCHER(FileExists, "") {
  base::ScopedAllowBlockingForTesting allow_blocking;
  return base::PathExists(arg) && !base::DirectoryExists(arg);
}

MATCHER_P(OwnedIwaBundleExists, profile_directory, "") {
  *result_listener << "where the profile directory is " << profile_directory;
  base::FilePath path = arg.GetPath(profile_directory);
  return ExplainMatchResult(
      AllOf(IsInIwaRandomDir(profile_directory), FileExists()), path,
      result_listener);
}

MATCHER_P2(IwaIs, untranslated_name, isolation_data, "") {
  return ExplainMatchResult(
      Pointee(AllOf(
          Property("untranslated_name", &WebApp::untranslated_name,
                   untranslated_name),
          Property("isolation_data", &WebApp::isolation_data, isolation_data))),
      arg, result_listener);
}

MATCHER_P5(IsolationDataIs,
           location,
           version,
           controlled_frame_partitions,
           pending_update_info,
           integrity_block_data,
           "") {
  return ExplainMatchResult(
      Optional(AllOf(
          Property("location", &IsolationData::location, location),
          Property("version", &IsolationData::version, version),
          Property("controlled_frame_partitions",
                   &IsolationData::controlled_frame_partitions,
                   controlled_frame_partitions),
          Property("pending_update_info", &IsolationData::pending_update_info,
                   pending_update_info),
          Property("integrity_block_data", &IsolationData::integrity_block_data,
                   integrity_block_data))),
      arg, result_listener);
}

MATCHER_P3(PendingUpdateInfoIs, location, version, integrity_block_data, "") {
  return ExplainMatchResult(
      Optional(AllOf(
          Field("location", &IsolationData::PendingUpdateInfo::location,
                location),
          Field("version", &IsolationData::PendingUpdateInfo::version, version),
          Field("integrity_block_data",
                &IsolationData::PendingUpdateInfo::integrity_block_data,
                integrity_block_data))),
      arg, result_listener);
}

}  // namespace test

}  // namespace web_app

#endif  // CHROME_BROWSER_UI_WEB_APPLICATIONS_TEST_ISOLATED_WEB_APP_TEST_UTILS_H_