1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/automation/automation_tab_helper.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <algorithm> 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/navigation_controller.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/automation_messages.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ipc/ipc_message.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ipc/ipc_message_macros.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTabEventObserver::TabEventObserver() { } 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTabEventObserver::~TabEventObserver() { 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < event_sources_.size(); ++i) { 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event_sources_[i]) 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_sources_[i]->RemoveObserver(this); 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TabEventObserver::StartObserving(AutomationTabHelper* tab_helper) { 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_helper->AddObserver(this); 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_sources_.push_back(tab_helper->AsWeakPtr()); 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TabEventObserver::StopObserving(AutomationTabHelper* tab_helper) { 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_helper->RemoveObserver(this); 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EventSourceVector::iterator iter = 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::find(event_sources_.begin(), event_sources_.end(), tab_helper); 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (iter != event_sources_.end()) 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_sources_.erase(iter); 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAutomationTabHelper::AutomationTabHelper(TabContents* tab_contents) 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : TabContentsObserver(tab_contents), 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen is_loading_(false) { 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAutomationTabHelper::~AutomationTabHelper() { } 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::AddObserver(TabEventObserver* observer) { 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen observers_.AddObserver(observer); 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::RemoveObserver(TabEventObserver* observer) { 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen observers_.RemoveObserver(observer); 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool AutomationTabHelper::has_pending_loads() const { 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return is_loading_ || !pending_client_redirects_.empty(); 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::DidStartLoading() { 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (is_loading_) { 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // DidStartLoading is often called twice. Once when the renderer sends a 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // load start message, and once when the browser calls it directly as a 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // result of some user-initiated navigation. 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "Received DidStartLoading while loading already started."; 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool had_pending_loads = has_pending_loads(); 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen is_loading_ = true; 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!had_pending_loads) { 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FOR_EACH_OBSERVER(TabEventObserver, observers_, 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnFirstPendingLoad(tab_contents())); 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::DidStopLoading() { 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!is_loading_) { 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(WARNING) << "Received DidStopLoading while loading already stopped."; 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen is_loading_ = false; 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!has_pending_loads()) { 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FOR_EACH_OBSERVER(TabEventObserver, observers_, 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnNoMorePendingLoads(tab_contents())); 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::RenderViewGone() { 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnTabOrRenderViewDestroyed(tab_contents()); 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::TabContentsDestroyed(TabContents* tab_contents) { 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnTabOrRenderViewDestroyed(tab_contents); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::OnTabOrRenderViewDestroyed( 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContents* tab_contents) { 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (has_pending_loads()) { 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen is_loading_ = false; 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_client_redirects_.clear(); 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FOR_EACH_OBSERVER(TabEventObserver, observers_, 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnNoMorePendingLoads(tab_contents)); 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool AutomationTabHelper::OnMessageReceived(const IPC::Message& message) { 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool handled = true; 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool msg_is_good = true; 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_BEGIN_MESSAGE_MAP_EX(AutomationTabHelper, message, msg_is_good) 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_MESSAGE_HANDLER(AutomationMsg_WillPerformClientRedirect, 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnWillPerformClientRedirect) 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_MESSAGE_HANDLER(AutomationMsg_DidCompleteOrCancelClientRedirect, 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDidCompleteOrCancelClientRedirect) 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_MESSAGE_UNHANDLED(handled = false) 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_END_MESSAGE_MAP_EX() 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!msg_is_good) { 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(ERROR) << "Failed to deserialize an IPC message"; 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return handled; 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::OnWillPerformClientRedirect( 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 frame_id, double delay_seconds) { 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Ignore all non-zero delays. 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(kkania): Handle timed redirects. 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (delay_seconds > 0) { 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(WARNING) << "Ignoring timed redirect scheduled for " << delay_seconds 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " seconds later. Will not wait for the redirect to occur"; 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool first_pending_load = !has_pending_loads(); 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_client_redirects_.insert(frame_id); 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (first_pending_load) { 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FOR_EACH_OBSERVER(TabEventObserver, observers_, 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnFirstPendingLoad(tab_contents())); 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutomationTabHelper::OnDidCompleteOrCancelClientRedirect(int64 frame_id) { 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::set<int64>::iterator iter = 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_client_redirects_.find(frame_id); 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // It is possible that we did not track the redirect becasue it had a non-zero 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // delay. See the comment in |OnWillPerformClientRedirect|. 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (iter != pending_client_redirects_.end()) { 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_client_redirects_.erase(iter); 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!has_pending_loads()) { 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FOR_EACH_OBSERVER(TabEventObserver, observers_, 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnNoMorePendingLoads(tab_contents())); 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 149