forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextension_background_page_waiter.cc
122 lines (103 loc) · 4.56 KB
/
extension_background_page_waiter.cc
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
// Copyright 2020 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 "extensions/test/extension_background_page_waiter.h"
#include "base/scoped_observer.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_host_observer.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_manager_observer.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
ExtensionBackgroundPageWaiter::ExtensionBackgroundPageWaiter(
content::BrowserContext* browser_context,
const Extension& extension)
: browser_context_(browser_context),
extension_(base::WrapRefCounted(&extension)) {}
ExtensionBackgroundPageWaiter::~ExtensionBackgroundPageWaiter() = default;
void ExtensionBackgroundPageWaiter::Wait() {
if (browser_context_->IsOffTheRecord() &&
!IncognitoInfo::IsSplitMode(extension_.get())) {
ADD_FAILURE() << "Trying to wait for an incognito background page from a "
<< "spanning mode extension. Use the on-the-record context.";
}
if (!BackgroundInfo::HasBackgroundPage(extension_.get()))
return; // No background page to wait for!
if (extension_->is_hosted_app()) {
// Little known fact: hosted apps can have background pages. They are
// handled separately in BackgroundContents[Service], and don't use the
// same infrastructure. They're also deprecated. Don't worry about them.
// (If we see flakiness in loading hosted apps, we could potentially
// rejigger this to accommodate for them as well, but it's unclear if it's
// a problem that needs solving.)
return;
}
ProcessManager* process_manager = ProcessManager::Get(browser_context_);
ExtensionHost* extension_host =
process_manager->GetBackgroundHostForExtension(extension_->id());
if (!extension_host) {
// If the extension has a lazy background page, it's possible that it's
// already been loaded and unloaded. As a proxy for this, check if there
// are registered events.
// This isn't a perfect solution, because
// a) We might be waiting on a subsequent background page load, and
// b) The extension might not register any events (which would normally be
// a bug in event page-based extensions, but not always).
// But, it's a decent proxy for now.
if (BackgroundInfo::HasLazyBackgroundPage(extension_.get()) &&
EventRouter::Get(browser_context_)
->HasRegisteredEvents(extension_->id())) {
return;
}
WaitForExtensionHostCreation();
extension_host =
process_manager->GetBackgroundHostForExtension(extension_->id());
}
ASSERT_TRUE(extension_host);
if (extension_host->has_loaded_once()) {
// The background host exists and has loaded; we're done.
return;
}
WaitForExtensionHostReady(extension_host);
}
void ExtensionBackgroundPageWaiter::WaitForExtensionHostCreation() {
process_manager_observer_.Add(ProcessManager::Get(browser_context_));
host_created_run_loop_.Run();
}
void ExtensionBackgroundPageWaiter::WaitForExtensionHostReady(
ExtensionHost* host) {
extension_host_observer_.Add(host);
host_ready_run_loop_.Run();
}
void ExtensionBackgroundPageWaiter::OnBackgroundHostCreated(
ExtensionHost* host) {
if (host->extension_id() != extension_->id() ||
host->browser_context() != browser_context_) {
return;
}
process_manager_observer_.RemoveAll();
host_created_run_loop_.QuitWhenIdle();
}
void ExtensionBackgroundPageWaiter::OnExtensionHostDidStopFirstLoad(
const ExtensionHost* host) {
ASSERT_EQ(extension_->id(), host->extension_id());
ASSERT_TRUE(host->has_loaded_once());
extension_host_observer_.RemoveAll();
host_ready_run_loop_.QuitWhenIdle();
}
void ExtensionBackgroundPageWaiter::OnExtensionHostDestroyed(
ExtensionHost* host) {
// This is only called while we're waiting for the host to be ready (since
// we remove ourselves as an observer when it's done).
DCHECK(host_ready_run_loop_.running());
ASSERT_EQ(extension_->id(), host->extension_id());
ADD_FAILURE() << "Extension host for " << extension_->name()
<< "was destroyed before it finished loading.";
ASSERT_TRUE(extension_host_observer_.IsObserving(host));
extension_host_observer_.Remove(host);
}
} // namespace extensions