OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/test/chromedriver/chrome/navigation_tracker.h" | 5 #include "chrome/test/chromedriver/chrome/navigation_tracker.h" |
6 | 6 |
7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "chrome/test/chromedriver/chrome/devtools_client.h" | 9 #include "chrome/test/chromedriver/chrome/devtools_client.h" |
10 #include "chrome/test/chromedriver/chrome/status.h" | 10 #include "chrome/test/chromedriver/chrome/status.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 loading_state_(known_state), | 25 loading_state_(known_state), |
26 browser_info_(browser_info) { | 26 browser_info_(browser_info) { |
27 client_->AddListener(this); | 27 client_->AddListener(this); |
28 } | 28 } |
29 | 29 |
30 NavigationTracker::~NavigationTracker() {} | 30 NavigationTracker::~NavigationTracker() {} |
31 | 31 |
32 Status NavigationTracker::IsPendingNavigation(const std::string& frame_id, | 32 Status NavigationTracker::IsPendingNavigation(const std::string& frame_id, |
33 bool* is_pending) { | 33 bool* is_pending) { |
34 if (loading_state_ == kUnknown) { | 34 if (loading_state_ == kUnknown) { |
| 35 scoped_ptr<base::DictionaryValue> result; |
| 36 |
| 37 // In the case that a http request is sent to server to fetch the page |
| 38 // content and the server hasn't responded at all, a dummy page is created |
| 39 // for the new window. In such case, the baseURL will be empty. |
| 40 base::DictionaryValue empty_params; |
| 41 Status status = client_->SendCommandAndGetResult( |
| 42 "DOM.getDocument", empty_params, &result); |
| 43 std::string base_url; |
| 44 if (status.IsError() || !result->GetString("root.baseURL", &base_url)) |
| 45 return Status(kUnknownError, "cannot determine loading status", status); |
| 46 if (base_url.empty()) { |
| 47 *is_pending = true; |
| 48 loading_state_ = kLoading; |
| 49 return Status(kOk); |
| 50 } |
| 51 |
35 // If the loading state is unknown (which happens after first connecting), | 52 // If the loading state is unknown (which happens after first connecting), |
36 // force loading to start and set the state to loading. This will | 53 // force loading to start and set the state to loading. This will |
37 // cause a frame start event to be received, and the frame stop event | 54 // cause a frame start event to be received, and the frame stop event |
38 // will not be received until all frames are loaded. | 55 // will not be received until all frames are loaded. |
39 // Loading is forced to start by attaching a temporary iframe. | 56 // Loading is forced to start by attaching a temporary iframe. |
40 // Forcing loading to start is not necessary if the main frame is not yet | 57 // Forcing loading to start is not necessary if the main frame is not yet |
41 // loaded. | 58 // loaded. |
42 const char kStartLoadingIfMainFrameNotLoading[] = | 59 const char kStartLoadingIfMainFrameNotLoading[] = |
43 "var isLoaded = document.readyState == 'complete' ||" | 60 "var isLoaded = document.readyState == 'complete' ||" |
44 " document.readyState == 'interactive';" | 61 " document.readyState == 'interactive';" |
45 "if (isLoaded) {" | 62 "if (isLoaded) {" |
46 " var frame = document.createElement('iframe');" | 63 " var frame = document.createElement('iframe');" |
47 " frame.src = 'about:blank';" | 64 " frame.src = 'about:blank';" |
48 " document.body.appendChild(frame);" | 65 " document.body.appendChild(frame);" |
49 " window.setTimeout(function() {" | 66 " window.setTimeout(function() {" |
50 " document.body.removeChild(frame);" | 67 " document.body.removeChild(frame);" |
51 " }, 0);" | 68 " }, 0);" |
52 "}"; | 69 "}"; |
53 base::DictionaryValue params; | 70 base::DictionaryValue params; |
54 params.SetString("expression", kStartLoadingIfMainFrameNotLoading); | 71 params.SetString("expression", kStartLoadingIfMainFrameNotLoading); |
55 scoped_ptr<base::DictionaryValue> result; | 72 status = client_->SendCommandAndGetResult( |
56 Status status = client_->SendCommandAndGetResult( | |
57 "Runtime.evaluate", params, &result); | 73 "Runtime.evaluate", params, &result); |
58 if (status.IsError()) | 74 if (status.IsError()) |
59 return Status(kUnknownError, "cannot determine loading status", status); | 75 return Status(kUnknownError, "cannot determine loading status", status); |
60 | 76 |
61 // Between the time the JavaScript is evaluated and SendCommandAndGetResult | 77 // Between the time the JavaScript is evaluated and SendCommandAndGetResult |
62 // returns, OnEvent may have received info about the loading state. | 78 // returns, OnEvent may have received info about the loading state. |
63 // This is only possible during a nested command. Only set the loading state | 79 // This is only possible during a nested command. Only set the loading state |
64 // if the loading state is still unknown. | 80 // if the loading state is still unknown. |
65 if (loading_state_ == kUnknown) | 81 if (loading_state_ == kUnknown) |
66 loading_state_ = kLoading; | 82 loading_state_ = kLoading; |
67 } | 83 } |
68 *is_pending = loading_state_ == kLoading; | 84 *is_pending = loading_state_ == kLoading; |
69 if (frame_id.empty()) | 85 if (frame_id.empty()) { |
70 *is_pending |= scheduled_frame_set_.size() > 0; | 86 *is_pending |= scheduled_frame_set_.size() > 0; |
71 else | 87 *is_pending |= pending_frame_set_.size() > 0; |
| 88 } else { |
72 *is_pending |= scheduled_frame_set_.count(frame_id) > 0; | 89 *is_pending |= scheduled_frame_set_.count(frame_id) > 0; |
| 90 *is_pending |= pending_frame_set_.count(frame_id) > 0; |
| 91 } |
73 return Status(kOk); | 92 return Status(kOk); |
74 } | 93 } |
75 | 94 |
76 Status NavigationTracker::OnConnected(DevToolsClient* client) { | 95 Status NavigationTracker::OnConnected(DevToolsClient* client) { |
77 ResetLoadingState(kUnknown); | 96 ResetLoadingState(kUnknown); |
78 | 97 |
79 // Enable page domain notifications to allow tracking navigation state. | 98 // Enable page domain notifications to allow tracking navigation state. |
80 base::DictionaryValue empty_params; | 99 base::DictionaryValue empty_params; |
81 return client_->SendCommand("Page.enable", empty_params); | 100 return client_->SendCommand("Page.enable", empty_params); |
82 } | 101 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 loading_state_ = kLoading; | 220 loading_state_ = kLoading; |
202 } | 221 } |
203 return Status(kOk); | 222 return Status(kOk); |
204 } | 223 } |
205 | 224 |
206 void NavigationTracker::ResetLoadingState(LoadingState loading_state) { | 225 void NavigationTracker::ResetLoadingState(LoadingState loading_state) { |
207 loading_state_ = loading_state; | 226 loading_state_ = loading_state; |
208 pending_frame_set_.clear(); | 227 pending_frame_set_.clear(); |
209 scheduled_frame_set_.clear(); | 228 scheduled_frame_set_.clear(); |
210 } | 229 } |
OLD | NEW |