| 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 |