Skip to content

Commit a72463d

Browse files
committed
Implement NavigationWatcher
1 parent d490ad1 commit a72463d

File tree

4 files changed

+95
-38
lines changed

4 files changed

+95
-38
lines changed

lib/PuppeteerSharp/Frame.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class Frame
1515
private object _context = null;
1616
private string _url = string.Empty;
1717
private List<WaitTask> _waitTasks;
18-
private List<string> _lifecycleEvents;
18+
private bool _detached;
1919

2020
public Frame(Session client, Page page, Frame parentFrame, string frameId)
2121
{
@@ -32,7 +32,7 @@ public Frame(Session client, Page page, Frame parentFrame, string frameId)
3232
SetDefaultContext(null);
3333

3434
_waitTasks = new List<WaitTask>();
35-
_lifecycleEvents = new List<string>();
35+
LifecycleEvents = new List<string>();
3636
}
3737

3838
#region Properties
@@ -43,6 +43,7 @@ public Frame(Session client, Page page, Frame parentFrame, string frameId)
4343
public string Id { get; internal set; }
4444
public string LoaderId { get; set; }
4545
public TaskCompletionSource<ExecutionContext> ContextResolveTaskWrapper { get; internal set; }
46+
public List<string> LifecycleEvents { get; internal set; }
4647

4748
#endregion
4849

@@ -93,7 +94,12 @@ internal Task<ElementHandle> AddScriptTag(dynamic options)
9394

9495
internal void OnLifecycleEvent(string loaderId, string name)
9596
{
96-
throw new NotImplementedException();
97+
if (name == "init")
98+
{
99+
LoaderId = loaderId;
100+
LifecycleEvents.Clear();
101+
}
102+
LifecycleEvents.Add(name);
97103
}
98104

99105
internal void Navigated(FramePayload framePayload)
@@ -122,8 +128,17 @@ internal void SetDefaultContext(ExecutionContext context)
122128

123129
internal void Detach()
124130
{
125-
throw new NotImplementedException();
131+
foreach (var waitTask in _waitTasks)
132+
{
133+
waitTask.Termiante(new Exception("waitForSelector failed: frame got detached."));
134+
}
135+
_detached = true;
136+
if (_parentFrame != null)
137+
{
138+
_parentFrame.ChildFrames.Remove(this);
139+
}
140+
_parentFrame = null;
141+
#endregion
126142
}
127-
#endregion
128143
}
129-
}
144+
}

lib/PuppeteerSharp/NavigationWatcher.cs

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace PuppeteerSharp
1111
internal class NavigationWatcher
1212
{
1313
private FrameManager _frameManager;
14-
private Frame _mainFrame;
14+
private Frame _frame;
1515
private dynamic _options;
1616
private static readonly Dictionary<string, string> _puppeteerToProtocolLifecycle = new Dictionary<string, string>()
1717
{
@@ -24,16 +24,17 @@ internal class NavigationWatcher
2424
private int _timeout;
2525
private string _initialLoaderId;
2626
private Task _navigationPromise;
27+
private Timer _timer = null;
2728

2829
public NavigationWatcher(FrameManager frameManager, Frame mainFrame, int timeout, dynamic options)
2930
{
3031
var waitUntil = new[] { "load" };
3132

32-
if (options.waitUntil is Array)
33+
if (options != null && options.waitUntil is Array)
3334
{
3435
waitUntil = options.waitUntil;
3536
}
36-
else if (options.waitUntil is string)
37+
else if (options != null && options.waitUntil is string)
3738
{
3839
waitUntil = new string[] { options.waitUntil.ToString() };
3940
}
@@ -46,7 +47,7 @@ public NavigationWatcher(FrameManager frameManager, Frame mainFrame, int timeout
4647
});
4748

4849
_frameManager = frameManager;
49-
_mainFrame = mainFrame;
50+
_frame = mainFrame;
5051
_options = options;
5152
_initialLoaderId = mainFrame.LoaderId;
5253
_timeout = timeout;
@@ -75,40 +76,72 @@ public NavigationWatcher(FrameManager frameManager, Frame mainFrame, int timeout
7576
#region Public methods
7677
public void Cancel()
7778
{
78-
throw new NotImplementedException();
79+
CleanUp();
7980
}
8081
#endregion
81-
#region Private methods
82-
void FrameManager_LifecycleEvent(object sender, PuppeteerSharp.FrameEventArgs e)
83-
{
82+
#region Private methods
8483

85-
}
86-
87-
private void CleanUp()
88-
{
89-
throw new NotImplementedException();
90-
}
91-
92-
private Task CreateTimeoutTask()
93-
{
94-
var wrapper = new TaskCompletionSource<bool>();
95-
96-
if (_timeout == 0)
84+
void FrameManager_LifecycleEvent(object sender, FrameEventArgs e)
85+
{
86+
// We expect navigation to commit.
87+
if (_frame.LoaderId == _initialLoaderId)
9788
{
98-
wrapper.SetResult(true);
89+
return;
9990
}
100-
else
91+
if (!CheckLifecycle(_frame, _expectedLifecycle))
10192
{
102-
Timer timer = null;
103-
timer = new Timer((state) =>
104-
{
105-
wrapper.SetException(
106-
new ChromeProcessException($"Navigation Timeout Exceeded: '{_timeout}'ms exceeded"));
107-
timer.Dispose();
108-
}, null, _timeout, 0);
93+
return;
10994
}
11095

111-
return wrapper.Task;
96+
LifeCycleCompleteTaskWrapper.SetResult(true);
97+
}
98+
99+
private bool CheckLifecycle(Frame frame, IEnumerable<string> expectedLifecycle)
100+
{
101+
foreach (var item in expectedLifecycle)
102+
{
103+
if (!frame.LifecycleEvents.Contains(item))
104+
{
105+
return false;
106+
}
107+
}
108+
foreach (var child in frame.ChildFrames)
109+
{
110+
if (!CheckLifecycle(child, expectedLifecycle))
111+
{
112+
return false;
113+
}
114+
}
115+
return true;
116+
}
117+
118+
private void CleanUp()
119+
{
120+
_frameManager.LifecycleEvent -= FrameManager_LifecycleEvent;
121+
_frameManager.FrameDetached -= FrameManager_LifecycleEvent;
122+
_timer?.Dispose();
123+
}
124+
125+
private Task CreateTimeoutTask()
126+
{
127+
var wrapper = new TaskCompletionSource<bool>();
128+
129+
if (_timeout == 0)
130+
{
131+
wrapper.SetResult(true);
132+
}
133+
else
134+
{
135+
_timer = new Timer((state) =>
136+
{
137+
wrapper.SetException(
138+
new ChromeProcessException($"Navigation Timeout Exceeded: '{_timeout}'ms exceeded"));
139+
_timer.Dispose();
140+
_timer = null;
141+
}, null, _timeout, 0);
142+
}
143+
144+
return wrapper.Task;
112145
}
113146
#endregion
114147
}

lib/PuppeteerSharp/Page.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class Page
1818
private ViewPortOptions _viewport;
1919
private Mouse _mouse;
2020
private Dictionary<string, Func<object>> _pageBindings;
21-
21+
private const int DefaultNavigationTimeout = 30000;
2222

2323
private Page(Session client, FrameTree frameTree, bool ignoreHTTPSErrors, TaskQueue screenshotTaskQueue)
2424
{
@@ -252,7 +252,11 @@ public async Task<dynamic> GoToAsync(string url, Dictionary<string, string> opti
252252
_networkManager.RequestCreated += createRequestEventListener;
253253

254254
var mainFrame = _frameManager.MainFrame;
255-
var watcher = new NavigationWatcher(_frameManager, mainFrame, options);
255+
var timeout = options != null && options.ContainsKey("timeout") ?
256+
Convert.ToInt32(options["timeout"]) :
257+
DefaultNavigationTimeout;
258+
259+
var watcher = new NavigationWatcher(_frameManager, mainFrame, timeout, options);
256260

257261
var navigateTask = Navigate(_client, url, referrer);
258262

lib/PuppeteerSharp/WaitTask.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,10 @@ internal void Rerun()
88
{
99
throw new NotImplementedException();
1010
}
11+
12+
internal void Termiante(Exception exception)
13+
{
14+
throw new NotImplementedException();
15+
}
1116
}
1217
}

0 commit comments

Comments
 (0)