// Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The SFC licenses this file // to you under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "ElementRepository.h" #include "logging.h" #include "errorcodes.h" #include "Element.h" namespace webdriver { ElementRepository::ElementRepository(void) { } ElementRepository::~ElementRepository(void) { } int ElementRepository::GetManagedElement(const std::string& element_id, ElementHandle* element_wrapper) const { LOG(TRACE) << "Entering ElementRepository::GetManagedElement"; ElementMap::const_iterator found_iterator = this->managed_elements_.find(element_id); if (found_iterator == this->managed_elements_.end()) { LOG(DEBUG) << "Unable to find managed element with id " << element_id; return ENOSUCHELEMENT; } *element_wrapper = found_iterator->second; return WD_SUCCESS; } bool ElementRepository::AddManagedElement(ElementHandle element_wrapper) { this->managed_elements_[element_wrapper->element_id()] = element_wrapper; return true; } bool ElementRepository::AddManagedElement(BrowserHandle current_browser, IHTMLElement* element, ElementHandle* element_wrapper) { LOG(TRACE) << "Entering ElementRepository::AddManagedElement"; bool element_already_managed = this->IsElementManaged(element, element_wrapper); if (!element_already_managed) { LOG(DEBUG) << "Element is not yet managed"; HWND containing_window_handle = NULL; if (current_browser != NULL) { containing_window_handle = current_browser->GetContentWindowHandle(); } ElementHandle new_wrapper(new Element(element, containing_window_handle)); this->managed_elements_[new_wrapper->element_id()] = new_wrapper; *element_wrapper = new_wrapper; } else { LOG(DEBUG) << "Element is already managed"; } return !element_already_managed; } bool ElementRepository::IsElementManaged(IHTMLElement* element, ElementHandle* element_wrapper) { // TODO: This method needs much work. If we are already managing a // given element, we don't want to assign it a new ID, but to find // out if we're managing it already, we need to compare to all of // the elements already in our map, which means iterating through // the map. For long-running tests, this means the addition of a // new managed element may take longer and longer as we have no // good algorithm for removing dead elements from the map. ElementMap::iterator it = this->managed_elements_.begin(); for (; it != this->managed_elements_.end(); ++it) { if (it->second->element() == element) { *element_wrapper = it->second; return true; } } return false; } void ElementRepository::RemoveManagedElement(const std::string& element_id) { LOG(TRACE) << "Entering ElementRepository::RemoveManagedElement"; ElementMap::iterator found_iterator = this->managed_elements_.find(element_id); if (found_iterator != this->managed_elements_.end()) { this->managed_elements_.erase(element_id); } else { LOG(DEBUG) << "Unable to find element to remove with id " << element_id; } } void ElementRepository::ListManagedElements() { LOG(TRACE) << "Entering ElementRepository::ListManagedElements"; ElementMap::iterator it = this->managed_elements_.begin(); for (; it != this->managed_elements_.end(); ++it) { LOG(DEBUG) << "Managed element: " << it->first; } } void ElementRepository::ClearCache() { // Logic explanation: We can't just remove the elements from the // managed elements map, within the loop as that would invalidate // the iterator. So we add the keys to a vector, and use the vector // to remove the elements from the map. std::vector bad_elements; ElementMap::const_iterator managed_iterator = this->managed_elements_.begin(); ElementMap::const_iterator last_managed_element = this->managed_elements_.end(); for(; managed_iterator != last_managed_element; ++managed_iterator) { if (!managed_iterator->second->IsAttachedToDom()) { bad_elements.push_back(managed_iterator->first); } } LOG(DEBUG) << "Refreshing managed element cache. Found " << bad_elements.size() << " to remove from cache."; std::vector::const_iterator id_iterator = bad_elements.begin(); std::vector::const_iterator last_id = bad_elements.end(); for (; id_iterator != last_id; ++id_iterator) { this->RemoveManagedElement(*id_iterator); } } void ElementRepository::Clear() { this->managed_elements_.clear(); } } // namespace webdriver