int IECommandHandler::GetElement(const IECommandExecutor& executor, const std::string& element_id, ElementHandle* element_wrapper) { int status_code = EOBSOLETEELEMENT; ElementHandle candidate_wrapper; int result = executor.GetManagedElement(element_id, &candidate_wrapper); if (result != SUCCESS) { status_code = 404; } else { // Verify that the element is still valid by walking up the // DOM tree until we find no parent or the html tag CComPtr<IHTMLElement> parent(candidate_wrapper->element()); while (parent) { CComQIPtr<IHTMLHtmlElement> html(parent); if (html) { status_code = SUCCESS; *element_wrapper = candidate_wrapper; break; } CComPtr<IHTMLElement> next; HRESULT hr = parent->get_parentElement(&next); if (FAILED(hr)) { //std::cout << hr << " [" << (_bstr_t(_com_error((DWORD) hr).ErrorMessage())) << "]"; } if (next == NULL) { BSTR tag; parent->get_tagName(&tag); //std::cout << "Found null parent of element with tag " << _bstr_t(tag); } parent = next; } if (status_code != SUCCESS) { IECommandExecutor& mutable_executor = const_cast<IECommandExecutor&>(executor); mutable_executor.RemoveManagedElement(element_id); } else { // If the element is attached to the DOM, validate that its document // is the currently-focused document (via frames). BrowserHandle current_browser; executor.GetCurrentBrowser(¤t_browser); CComPtr<IHTMLDocument2> focused_doc; current_browser->GetDocument(&focused_doc); CComPtr<IDispatch> parent_doc_dispatch; parent->get_document(&parent_doc_dispatch); if (!focused_doc.IsEqualObject(parent_doc_dispatch)) { status_code = EOBSOLETEELEMENT; } } } return status_code; }
int IECommandHandler::GetElement(const IECommandExecutor& executor, const std::string& element_id, ElementHandle* element_wrapper) { LOG(TRACE) << "Entering IECommandHandler::GetElement"; ElementHandle candidate_wrapper; int result = executor.GetManagedElement(element_id, &candidate_wrapper); if (result != SUCCESS) { // This bears some explanation. Technically, passing an invalid ID in the // URL for an element command should result in a 404. However, since the // language bindings don't make up their own element IDs, any call from // a language binding is more than likely an ID that the IE driver assigned // it, and it was at one time valid. Therefore, we'll assume that not finding // the element ID in the cache means it's stale. LOG(WARN) << "Unable to get managed element, element not found, assuming stale"; return EOBSOLETEELEMENT; } else { if (!candidate_wrapper->IsAttachedToDom()) { LOG(WARN) << "Found managed element is no longer valid"; IECommandExecutor& mutable_executor = const_cast<IECommandExecutor&>(executor); mutable_executor.RemoveManagedElement(element_id); return EOBSOLETEELEMENT; } else { // If the element is attached to the DOM, validate that its document // is the currently-focused document (via frames). BrowserHandle current_browser; executor.GetCurrentBrowser(¤t_browser); CComPtr<IHTMLDocument2> focused_doc; current_browser->GetDocument(&focused_doc); CComPtr<IDispatch> parent_doc_dispatch; candidate_wrapper->element()->get_document(&parent_doc_dispatch); if (focused_doc.IsEqualObject(parent_doc_dispatch)) { *element_wrapper = candidate_wrapper; return SUCCESS; } else { LOG(WARN) << "Found managed element's document is not currently focused"; } } } return EOBSOLETEELEMENT; }