int ElementFinder::FindElementsByCssSelector(const IESessionWindow& session, const ElementHandle parent_wrapper, const std::wstring& criteria, Json::Value* found_elements) { int result = ENOSUCHELEMENT; BrowserHandle browser; result = session.GetCurrentBrowser(&browser); if (result != SUCCESS) { return result; } std::wstring script_source(L"(function() { return function(){"); script_source += atoms::SIZZLE; script_source += L"\n"; script_source += L"var root = arguments[1] ? arguments[1] : document.documentElement;"; script_source += L"if (root['querySelectorAll']) { return root.querySelectorAll(arguments[0]); } "; script_source += L"var results = []; Sizzle(arguments[0], root, results);"; script_source += L"return results;"; script_source += L"};})();"; CComPtr<IHTMLDocument2> doc; browser->GetDocument(&doc); Script script_wrapper(doc, script_source, 2); script_wrapper.AddArgument(criteria); if (parent_wrapper) { // Use a copy for the parent element? CComPtr<IHTMLElement> parent(parent_wrapper->element()); IHTMLElement* parent_element_copy; HRESULT hr = parent.CopyTo(&parent_element_copy); script_wrapper.AddArgument(parent_element_copy); } result = script_wrapper.Execute(); CComVariant snapshot = script_wrapper.result(); std::wstring get_element_count_script = L"(function(){return function() {return arguments[0].length;}})();"; Script get_element_count_script_wrapper(doc, get_element_count_script, 1); get_element_count_script_wrapper.AddArgument(snapshot); result = get_element_count_script_wrapper.Execute(); if (result == SUCCESS) { if (!get_element_count_script_wrapper.ResultIsInteger()) { result = EUNEXPECTEDJSERROR; } else { long length = get_element_count_script_wrapper.result().lVal; std::wstring get_next_element_script = L"(function(){return function() {return arguments[0][arguments[1]];}})();"; for (long i = 0; i < length; ++i) { Script get_element_script_wrapper(doc, get_next_element_script, 2); get_element_script_wrapper.AddArgument(snapshot); get_element_script_wrapper.AddArgument(i); result = get_element_script_wrapper.Execute(); Json::Value json_element; get_element_script_wrapper.ConvertResultToJsonValue(session, &json_element); found_elements->append(json_element); } } } return result; }
int ElementFinder::FindElementsUsingSizzle(const IECommandExecutor& executor, const ElementHandle parent_wrapper, const std::wstring& criteria, Json::Value* found_elements) { LOG(TRACE) << "Entering ElementFinder::FindElementsUsingSizzle"; int result; if (criteria == L"") { // Apparently, Sizzle will happily return an empty array for an empty // string as the selector. We do not want this. return ENOSUCHELEMENT; } BrowserHandle browser; result = executor.GetCurrentBrowser(&browser); if (result != WD_SUCCESS) { LOG(WARN) << "Unable to get browser"; return result; } std::wstring script_source(L"(function() { return function(){ if (!window.Sizzle) {"); script_source += atoms::asString(atoms::SIZZLE); script_source += L"}\n"; script_source += L"var root = arguments[1] ? arguments[1] : document.documentElement;"; script_source += L"if (root['querySelectorAll']) { return root.querySelectorAll(arguments[0]); } "; script_source += L"var results = []; try { Sizzle(arguments[0], root, results); } catch(ex) { results = null; }"; script_source += L"return results;"; script_source += L"};})();"; CComPtr<IHTMLDocument2> doc; browser->GetDocument(&doc); Script script_wrapper(doc, script_source, 2); script_wrapper.AddArgument(criteria); if (parent_wrapper) { // Use a copy for the parent element? CComPtr<IHTMLElement> parent(parent_wrapper->element()); script_wrapper.AddArgument(parent); } result = script_wrapper.Execute(); if (result == WD_SUCCESS) { CComVariant snapshot = script_wrapper.result(); if (snapshot.vt == VT_NULL || snapshot.vt == VT_EMPTY) { // We explicitly caught an error from Sizzle. Return ENOSUCHELEMENT. return ENOSUCHELEMENT; } std::wstring get_element_count_script = L"(function(){return function() {return arguments[0].length;}})();"; Script get_element_count_script_wrapper(doc, get_element_count_script, 1); get_element_count_script_wrapper.AddArgument(snapshot); result = get_element_count_script_wrapper.Execute(); if (result == WD_SUCCESS) { *found_elements = Json::Value(Json::arrayValue); if (!get_element_count_script_wrapper.ResultIsInteger()) { LOG(WARN) << "Found elements count is not integer"; result = EUNEXPECTEDJSERROR; } else { long length = get_element_count_script_wrapper.result().lVal; std::wstring get_next_element_script = L"(function(){return function() {return arguments[0][arguments[1]];}})();"; for (long i = 0; i < length; ++i) { Script get_element_script_wrapper(doc, get_next_element_script, 2); get_element_script_wrapper.AddArgument(snapshot); get_element_script_wrapper.AddArgument(i); result = get_element_script_wrapper.Execute(); if (result == WD_SUCCESS) { Json::Value json_element; get_element_script_wrapper.ConvertResultToJsonValue(executor, &json_element); found_elements->append(json_element); } else { LOG(WARN) << "Unable to get " << i << " found element"; } } } } else { LOG(WARN) << "Unable to get count of found elements"; result = EUNEXPECTEDJSERROR; } } else { LOG(WARN) << "Execution returned error"; } return result; }
int ElementFinder::FindElementsByXPath(const IESessionWindow& session, const ElementHandle parent_wrapper, const std::wstring& criteria, Json::Value* found_elements) { int result = ENOSUCHELEMENT; BrowserHandle browser; result = session.GetCurrentBrowser(&browser); if (result != SUCCESS) { return result; } result = this->InjectXPathEngine(browser); // TODO(simon): Why does the injecting sometimes fail? if (result != SUCCESS) { return result; } // Call it std::wstring query; if (parent_wrapper) { query += L"(function() { return function() {var res = document.__webdriver_evaluate(arguments[0], arguments[1], null, 7, null); return res;};})();"; } else { query += L"(function() { return function() {var res = document.__webdriver_evaluate(arguments[0], document, null, 7, null); return res;};})();"; } CComPtr<IHTMLDocument2> doc; browser->GetDocument(&doc); Script script_wrapper(doc, query, 2); script_wrapper.AddArgument(criteria); if (parent_wrapper) { // Use a copy for the parent element? CComPtr<IHTMLElement> parent(parent_wrapper->element()); IHTMLElement* parent_element_copy; HRESULT hr = parent.CopyTo(&parent_element_copy); script_wrapper.AddArgument(parent_element_copy); } result = script_wrapper.Execute(); CComVariant snapshot = script_wrapper.result(); std::wstring get_element_count_script = L"(function(){return function() {return arguments[0].snapshotLength;}})();"; Script get_element_count_script_wrapper(doc, get_element_count_script, 1); get_element_count_script_wrapper.AddArgument(snapshot); result = get_element_count_script_wrapper.Execute(); if (result == SUCCESS) { if (!get_element_count_script_wrapper.ResultIsInteger()) { result = EUNEXPECTEDJSERROR; } else { long length = get_element_count_script_wrapper.result().lVal; std::wstring get_next_element_script(L"(function(){return function() {return arguments[0].iterateNext();}})();"); for (long i = 0; i < length; ++i) { Script get_element_script_wrapper(doc, get_next_element_script, 2); get_element_script_wrapper.AddArgument(snapshot); get_element_script_wrapper.AddArgument(i); result = get_element_script_wrapper.Execute(); Json::Value json_element; get_element_script_wrapper.ConvertResultToJsonValue(session, &json_element); found_elements->append(json_element); } } } return result; }