1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "extensions/test/background_page_watcher.h"
6 
7 #include "base/auto_reset.h"
8 #include "base/check_op.h"
9 #include "base/run_loop.h"
10 #include "base/scoped_observer.h"
11 #include "content/public/browser/render_frame_host.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "content/public/browser/render_view_host.h"
14 #include "content/public/browser/web_contents.h"
15 #include "extensions/browser/extension_host.h"
16 #include "extensions/browser/process_manager.h"
17 #include "extensions/common/extension.h"
18 
19 namespace extensions {
20 
BackgroundPageWatcher(ProcessManager * process_manager,const Extension * extension)21 BackgroundPageWatcher::BackgroundPageWatcher(ProcessManager* process_manager,
22                                              const Extension* extension)
23     : process_manager_(process_manager),
24       extension_id_(extension->id()),
25       is_waiting_for_open_(false),
26       is_waiting_for_close_(false) {}
27 
~BackgroundPageWatcher()28 BackgroundPageWatcher::~BackgroundPageWatcher() {}
29 
WaitForOpen()30 void BackgroundPageWatcher::WaitForOpen() {
31   WaitForOpenState(true);
32 }
33 
WaitForClose()34 void BackgroundPageWatcher::WaitForClose() {
35   WaitForOpenState(false);
36 }
37 
WaitForOpenState(bool wait_for_open)38 void BackgroundPageWatcher::WaitForOpenState(bool wait_for_open) {
39   if (IsBackgroundPageOpen() == wait_for_open)
40     return;
41   ScopedObserver<ProcessManager, ProcessManagerObserver> observer(this);
42   observer.Add(process_manager_);
43   bool* flag = wait_for_open ? &is_waiting_for_open_ : &is_waiting_for_close_;
44   base::AutoReset<bool> set_flag(flag, true);
45   base::RunLoop run_loop;
46   base::AutoReset<base::OnceClosure> set_quit_run_loop(&quit_run_loop_,
47                                                        run_loop.QuitClosure());
48   run_loop.Run();
49   DCHECK_EQ(wait_for_open, IsBackgroundPageOpen());
50 }
51 
IsBackgroundPageOpen()52 bool BackgroundPageWatcher::IsBackgroundPageOpen() {
53   ExtensionHost* host =
54       process_manager_->GetBackgroundHostForExtension(extension_id_);
55   if (!host)
56     return false;
57   content::RenderProcessHost* rph =
58       host->host_contents()->GetMainFrame()->GetProcess();
59   return rph && rph->IsInitializedAndNotDead();
60 }
61 
OnExtensionFrameRegistered(const std::string & extension_id,content::RenderFrameHost * rfh)62 void BackgroundPageWatcher::OnExtensionFrameRegistered(
63     const std::string& extension_id,
64     content::RenderFrameHost* rfh) {
65   if (is_waiting_for_open_ && extension_id == extension_id_ &&
66       IsBackgroundPageOpen())
67     std::move(quit_run_loop_).Run();
68 }
69 
OnExtensionFrameUnregistered(const std::string & extension_id,content::RenderFrameHost * rfh)70 void BackgroundPageWatcher::OnExtensionFrameUnregistered(
71     const std::string& extension_id,
72     content::RenderFrameHost* rfh) {
73   if (is_waiting_for_close_ && extension_id == extension_id_ &&
74       !IsBackgroundPageOpen())
75     std::move(quit_run_loop_).Run();
76 }
77 
78 }  // namespace extensions
79