This source file includes following definitions.
- num_frames_pending_
- num_frames_pending_
- IsPendingNavigation
- OnConnected
- OnEvent
- OnCommandSuccess
- ResetLoadingState
#include "chrome/test/chromedriver/chrome/navigation_tracker.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/test/chromedriver/chrome/devtools_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
NavigationTracker::NavigationTracker(DevToolsClient* client, int build_no)
: client_(client),
loading_state_(kUnknown),
build_no_(build_no),
num_frames_pending_(0) {
client_->AddListener(this);
}
NavigationTracker::NavigationTracker(DevToolsClient* client,
LoadingState known_state,
int build_no)
: client_(client),
loading_state_(known_state),
build_no_(build_no),
num_frames_pending_(0) {
client_->AddListener(this);
}
NavigationTracker::~NavigationTracker() {}
Status NavigationTracker::IsPendingNavigation(const std::string& frame_id,
bool* is_pending) {
if (loading_state_ == kUnknown) {
const char kStartLoadingIfMainFrameNotLoading[] =
"var isLoaded = document.readyState == 'complete' ||"
" document.readyState == 'interactive';"
"if (isLoaded) {"
" var frame = document.createElement('iframe');"
" frame.src = 'about:blank';"
" document.body.appendChild(frame);"
" window.setTimeout(function() {"
" document.body.removeChild(frame);"
" }, 0);"
"}";
base::DictionaryValue params;
params.SetString("expression", kStartLoadingIfMainFrameNotLoading);
scoped_ptr<base::DictionaryValue> result;
Status status = client_->SendCommandAndGetResult(
"Runtime.evaluate", params, &result);
if (status.IsError())
return Status(kUnknownError, "cannot determine loading status", status);
if (loading_state_ == kUnknown)
loading_state_ = kLoading;
}
*is_pending = loading_state_ == kLoading;
if (frame_id.empty())
*is_pending |= scheduled_frame_set_.size() > 0;
else
*is_pending |= scheduled_frame_set_.count(frame_id) > 0;
return Status(kOk);
}
Status NavigationTracker::OnConnected(DevToolsClient* client) {
ResetLoadingState(kUnknown);
base::DictionaryValue empty_params;
return client_->SendCommand("Page.enable", empty_params);
}
Status NavigationTracker::OnEvent(DevToolsClient* client,
const std::string& method,
const base::DictionaryValue& params) {
if (method == "Page.frameStartedLoading") {
loading_state_ = kLoading;
num_frames_pending_++;
} else if (method == "Page.frameStoppedLoading") {
num_frames_pending_--;
if (num_frames_pending_ <= 0 || build_no_ <= 1916) {
num_frames_pending_ = 0;
loading_state_ = kNotLoading;
}
} else if (method == "Page.frameScheduledNavigation") {
double delay;
if (!params.GetDouble("delay", &delay))
return Status(kUnknownError, "missing or invalid 'delay'");
std::string frame_id;
if (!params.GetString("frameId", &frame_id))
return Status(kUnknownError, "missing or invalid 'frameId'");
if (delay > 1)
return Status(kOk);
scheduled_frame_set_.insert(frame_id);
} else if (method == "Page.frameClearedScheduledNavigation") {
std::string frame_id;
if (!params.GetString("frameId", &frame_id))
return Status(kUnknownError, "missing or invalid 'frameId'");
scheduled_frame_set_.erase(frame_id);
} else if (method == "Page.frameNavigated") {
const base::Value* unused_value;
if (!params.Get("frame.parentId", &unused_value)) {
num_frames_pending_ = 0;
scheduled_frame_set_.clear();
}
} else if (method == "Inspector.targetCrashed") {
ResetLoadingState(kNotLoading);
}
return Status(kOk);
}
Status NavigationTracker::OnCommandSuccess(DevToolsClient* client,
const std::string& method) {
if (method == "Page.navigate" && loading_state_ != kLoading) {
loading_state_ = kUnknown;
base::DictionaryValue params;
params.SetString("expression", "document.URL");
scoped_ptr<base::DictionaryValue> result;
Status status = client_->SendCommandAndGetResult(
"Runtime.evaluate", params, &result);
std::string url;
if (status.IsError() || !result->GetString("result.value", &url))
return Status(kUnknownError, "cannot determine loading status", status);
if (loading_state_ == kUnknown && url.empty())
loading_state_ = kLoading;
}
return Status(kOk);
}
void NavigationTracker::ResetLoadingState(LoadingState loading_state) {
loading_state_ = loading_state;
num_frames_pending_ = 0;
scheduled_frame_set_.clear();
}