 Issue 5750789393874944:
  [IE] First round of ATL removal  (Closed)
    
  
    Issue 5750789393874944:
  [IE] First round of ATL removal  (Closed) 
  | Index: src/plugin/Wrapper.cpp | 
| =================================================================== | 
| new file mode 100644 | 
| --- /dev/null | 
| +++ b/src/plugin/Wrapper.cpp | 
| @@ -0,0 +1,267 @@ | 
| +#include "Wrapper.h" | 
| +#include "COM_Client.h" | 
| +#include <Shlwapi.h> | 
| +#include <WinInet.h> | 
| + | 
| +#include <memory> | 
| +#include <string> | 
| +#include <sstream> | 
| + | 
| +namespace Wrapper { | 
| + | 
| + std::wstring & Unescape_URL( std::wstring & url ) | 
| 
Oleksandr
2014/06/26 00:48:43
This belongs to Utils.cpp, I think
 
Eric
2014/06/26 15:13:56
Since I started on this file, I've come to think t
 | 
| + { | 
| + DWORD result_length = INTERNET_MAX_URL_LENGTH; | 
| + /* | 
| + * The choice to allocate the result buffer is because the maximum length is larger than 2 Kb. | 
| + */ | 
| + std::unique_ptr< wchar_t > result( new wchar_t[ result_length ] ); | 
| + /* | 
| + * Casting away const here is harmless because we're not using the in-place modification mode of UrlUnescape | 
| + */ | 
| + HRESULT hr = ::UrlUnescapeW( const_cast< wchar_t * >( url.c_str() ), result.get(), & result_length, 0 ); | 
| + if ( hr == S_OK ) { | 
| + url = std::wstring( result.get(), result_length ); | 
| + } | 
| + /* | 
| + * If the call to UrlUnescape fails, we don't alter the string. | 
| + * This matches the behavior of the previous wrapper. | 
| + * Because there's no error handling, however, there might be masked failures in UrlUnescape. | 
| + */ | 
| + return url; | 
| + } | 
| + | 
| + HRESULT Browser::navigate( std::wstring url ) | 
| + { | 
| + /* | 
| + * Try first in a new tab. | 
| + */ | 
| + BSTR_Argument url_arg( url ); | 
| + VARIANT flags; | 
| + flags.vt = VT_I4; | 
| + flags.intVal = navOpenInNewTab; | 
| + HRESULT hr = _browser->Navigate( url_arg, &flags, 0, 0, 0 ); | 
| + if ( !FAILED(hr) ) | 
| + { | 
| + return hr; | 
| + } | 
| + /* | 
| + * The failure code seems to be mostly 0x80004005, an unspecified error from a COM object. | 
| + * What does seem to be consistent is that this error is "sticky", that is, once it starts happening, it keeps happening on that object. | 
| + * There are some related reports on the internet that this happens in other contexts. | 
| + * It's fairly clear this is some kind of defect internal to IE, | 
| + * and there's some reason to believe that this might be from some kind of internal race condition or other multiprocessing failure. | 
| + */ | 
| + /* | 
| + * Try next in a new window. | 
| + */ | 
| + flags.intVal = navOpenInNewWindow; | 
| + /* | 
| + * We're not copying the URL a second time, since the first copy was purely defensive. | 
| + * Nevertheless, if there are problems with this function, it should be verified that url_temp is not getting modified. | 
| + */ | 
| + hr = _browser->Navigate( url_arg, &flags, 0, 0, 0 ); | 
| + return hr; | 
| + } | 
| + | 
| + bool Browser::Location_URL( std::wstring & value ) const | 
| + { | 
| + BSTR result; | 
| + HRESULT hr = _browser->get_LocationURL( &result ); | 
| + if ( hr == S_OK ) | 
| + { | 
| + value = result ? Returned_BSTR( result ) : std::wstring(); | 
| + return true; | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + std::wstring Internet_Bind_Info::bind_string_single( BINDSTRING type ) | 
| + { | 
| + unsigned long n_results; | 
| + LPOLESTR results[10]; | 
| + HRESULT hr = _bind_info->GetBindString( type, results, 10, &n_results ); | 
| + if ( hr == S_OK && n_results > 0) | 
| + { | 
| + return std::wstring( results[0] ); | 
| + } | 
| + return std::wstring(); | 
| + } | 
| + | 
| + /* | 
| + * A return value of S_OK does not indicate that an attribute is present. | 
| + * Instead, the variant type is something other than VT_NULL if present. | 
| + * See comments at MSDN http://msdn.microsoft.com/en-us/library/aa752280%28v=vs.85%29.aspx | 
| + */ | 
| + bool HTML_Element::attribute( std::wstring attr_name, std::wstring & attr_value ) const | 
| + { | 
| + VARIANT result; | 
| + BSTR_Argument name( attr_name ); | 
| + | 
| + _element->getAttribute( name, 0, &result ); | 
| + if ( result.vt == VT_NULL ) | 
| + { | 
| + return false; | 
| + } | 
| + if ( result.vt == VT_BSTR ) | 
| + { | 
| + attr_value = Returned_BSTR( result.bstrVal ); | 
| + } | 
| + else if ( result.vt == VT_I2 ) | 
| + { | 
| + // | 
| + std::wostringstream ss; | 
| + ss << result.iVal; | 
| + attr_value = ss.str(); | 
| + } | 
| + else if ( result.vt == VT_I4 ) | 
| + { | 
| + std::wostringstream ss; | 
| + ss << result.lVal; | 
| + attr_value = ss.str(); | 
| + } | 
| + /* | 
| + * If the result variant does not return one of the above supported types, | 
| + * we return true, indicating the attribute is found, but no attribute value. | 
| + */ | 
| + return true; | 
| + } | 
| + | 
| + /* | 
| + * This implementation relies on the behavior that IE returns a variant of type VT_I4 for integer values. | 
| + */ | 
| + bool HTML_Element::attribute( std::wstring attr_name, int & attr_value ) const | 
| + { | 
| + static_assert( sizeof( int ) >= 4, "Size of 'int' must be at least 4" ); | 
| + VARIANT result; | 
| + BSTR_Argument name( attr_name ); | 
| + | 
| + _element->getAttribute( name, 0, &result ); | 
| + /* | 
| + * VT_I4 and VT_I2 are supported, VT_I2 just to be defensive. | 
| + */ | 
| + if ( result.vt == VT_I4 ) | 
| + { | 
| + attr_value = result.lVal; | 
| + return true; | 
| + } | 
| + else if ( result.vt == VT_I2 ) | 
| + { | 
| + attr_value = result.iVal; | 
| + return true; | 
| + } | 
| + /* | 
| + * Any other return type will return false, | 
| + * whether the attribute is not present or whether it's present but not a (supported) integer type. | 
| + */ | 
| + if ( result.vt == VT_BSTR ) | 
| + { | 
| + /* | 
| + * If we get a BSTR return value, we need to release it, even if we're not using it. | 
| + * The destructor for Returned_BSTR takes care of that | 
| + */ | 
| + Returned_BSTR( result.bstrVal ); | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + bool HTML_Element::id( std::wstring & value ) const | 
| + { | 
| + BSTR result; | 
| + HRESULT hr = _element->get_id( &result ); | 
| + if ( hr == S_OK ) | 
| + { | 
| + value = result ? Returned_BSTR( result ) : std::wstring(); | 
| + return true; | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + bool HTML_Element::class_name( std::wstring & value ) const | 
| + { | 
| + BSTR result; | 
| + HRESULT hr = _element->get_className( &result ); | 
| + /* | 
| + * get_className seems to return S_OK and result==NULL as a valid answer. | 
| + */ | 
| + if ( hr == S_OK ) | 
| + { | 
| + value = result ? Returned_BSTR( result ) : std::wstring(); | 
| + return true; | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + bool HTML_Element::inner_HTML( std::wstring & value ) const | 
| + { | 
| + BSTR result; | 
| + HRESULT hr = _element->get_innerHTML( &result ); | 
| + if ( hr == S_OK ) | 
| + { | 
| + value = result ? Returned_BSTR( result ) : std::wstring(); | 
| + return true; | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + bool HTML_Element::tag_name( std::wstring & value ) const | 
| + { | 
| + BSTR result; | 
| + HRESULT hr = _element->get_tagName( &result ); | 
| + if ( hr == S_OK ) | 
| + { | 
| + value = result ? Returned_BSTR( result ) : std::wstring(); | 
| + return true; | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + bool HTML_Style::display( std::wstring & value ) const | 
| + { | 
| + BSTR result; | 
| + HRESULT hr = _style->get_display( &result ); | 
| + if ( hr == S_OK ) | 
| + { | 
| + value = result ? Returned_BSTR( result ) : std::wstring(); | 
| + return true; | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + bool HTML_Style::assign_display( const std::wstring & value ) | 
| + { | 
| + BSTR_Argument value_arg( value ); | 
| + HRESULT hr = _style->put_display( value_arg ); | 
| + return hr == S_OK; | 
| + } | 
| + | 
| + bool HTML_Style::CSS_text( std::wstring & value ) const | 
| + { | 
| + BSTR result; | 
| + HRESULT hr = _style->get_cssText( &result ); | 
| + if ( hr == S_OK ) | 
| + { | 
| + value = result ? Returned_BSTR( result ) : std::wstring(); | 
| + return true; | 
| + } | 
| + return false; | 
| + } | 
| + | 
| + IDispatch * HTML_Element_Collection::at( long index ) | 
| + { | 
| + VARIANT index_arg; | 
| + index_arg.vt = VT_I4; | 
| + index_arg.lVal = index; | 
| + | 
| + VARIANT nothing; | 
| + nothing.vt = VT_EMPTY; | 
| + | 
| + IDispatch * result; | 
| + HRESULT hr = _elements->item( index_arg, nothing, &result ); | 
| + /* | 
| + * Although item() returns S_OK if the element is not found, | 
| + * it still might return other values and have undocumented effects on 'result'. | 
| + */ | 
| + return ( hr != S_OK ) ? 0 : result; | 
| + } | 
| +} |