| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #include "Wrapper.h" | |
| 2 #include "COM_Client.h" | |
| 3 #include <Shlwapi.h> | |
| 4 #include <WinInet.h> | |
| 5 | |
| 6 #include <memory> | |
| 7 #include <string> | |
| 8 #include <sstream> | |
| 9 | |
| 10 namespace Wrapper { | |
| 11 | |
| 12 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
| |
| 13 { | |
| 14 DWORD result_length = INTERNET_MAX_URL_LENGTH; | |
| 15 /* | |
| 16 * The choice to allocate the result buffer is because the maximum length is larger than 2 Kb. | |
| 17 */ | |
| 18 std::unique_ptr< wchar_t > result( new wchar_t[ result_length ] ); | |
| 19 /* | |
| 20 * Casting away const here is harmless because we're not using the in-place modification mode of UrlUnescape | |
| 21 */ | |
| 22 HRESULT hr = ::UrlUnescapeW( const_cast< wchar_t * >( url.c_str() ), result. get(), & result_length, 0 ); | |
| 23 if ( hr == S_OK ) { | |
| 24 url = std::wstring( result.get(), result_length ); | |
| 25 } | |
| 26 /* | |
| 27 * If the call to UrlUnescape fails, we don't alter the string. | |
| 28 * This matches the behavior of the previous wrapper. | |
| 29 * Because there's no error handling, however, there might be masked failure s in UrlUnescape. | |
| 30 */ | |
| 31 return url; | |
| 32 } | |
| 33 | |
| 34 HRESULT Browser::navigate( std::wstring url ) | |
| 35 { | |
| 36 /* | |
| 37 * Try first in a new tab. | |
| 38 */ | |
| 39 BSTR_Argument url_arg( url ); | |
| 40 VARIANT flags; | |
| 41 flags.vt = VT_I4; | |
| 42 flags.intVal = navOpenInNewTab; | |
| 43 HRESULT hr = _browser->Navigate( url_arg, &flags, 0, 0, 0 ); | |
| 44 if ( !FAILED(hr) ) | |
| 45 { | |
| 46 return hr; | |
| 47 } | |
| 48 /* | |
| 49 * The failure code seems to be mostly 0x80004005, an unspecified error from a COM object. | |
| 50 * What does seem to be consistent is that this error is "sticky", that is, once it starts happening, it keeps happening on that object. | |
| 51 * There are some related reports on the internet that this happens in other contexts. | |
| 52 * It's fairly clear this is some kind of defect internal to IE, | |
| 53 * and there's some reason to believe that this might be from some kind of internal race condition or other multiprocessing failure. | |
| 54 */ | |
| 55 /* | |
| 56 * Try next in a new window. | |
| 57 */ | |
| 58 flags.intVal = navOpenInNewWindow; | |
| 59 /* | |
| 60 * We're not copying the URL a second time, since the first copy was purely defensive. | |
| 61 * Nevertheless, if there are problems with this function, it should be ver ified that url_temp is not getting modified. | |
| 62 */ | |
| 63 hr = _browser->Navigate( url_arg, &flags, 0, 0, 0 ); | |
| 64 return hr; | |
| 65 } | |
| 66 | |
| 67 bool Browser::Location_URL( std::wstring & value ) const | |
| 68 { | |
| 69 BSTR result; | |
| 70 HRESULT hr = _browser->get_LocationURL( &result ); | |
| 71 if ( hr == S_OK ) | |
| 72 { | |
| 73 value = result ? Returned_BSTR( result ) : std::wstring(); | |
| 74 return true; | |
| 75 } | |
| 76 return false; | |
| 77 } | |
| 78 | |
| 79 std::wstring Internet_Bind_Info::bind_string_single( BINDSTRING type ) | |
| 80 { | |
| 81 unsigned long n_results; | |
| 82 LPOLESTR results[10]; | |
| 83 HRESULT hr = _bind_info->GetBindString( type, results, 10, &n_results ); | |
| 84 if ( hr == S_OK && n_results > 0) | |
| 85 { | |
| 86 return std::wstring( results[0] ); | |
| 87 } | |
| 88 return std::wstring(); | |
| 89 } | |
| 90 | |
| 91 /* | |
| 92 * A return value of S_OK does not indicate that an attribute is present. | |
| 93 * Instead, the variant type is something other than VT_NULL if present. | |
| 94 * See comments at MSDN http://msdn.microsoft.com/en-us/library/aa752280%28v=v s.85%29.aspx | |
| 95 */ | |
| 96 bool HTML_Element::attribute( std::wstring attr_name, std::wstring & attr_valu e ) const | |
| 97 { | |
| 98 VARIANT result; | |
| 99 BSTR_Argument name( attr_name ); | |
| 100 | |
| 101 _element->getAttribute( name, 0, &result ); | |
| 102 if ( result.vt == VT_NULL ) | |
| 103 { | |
| 104 return false; | |
| 105 } | |
| 106 if ( result.vt == VT_BSTR ) | |
| 107 { | |
| 108 attr_value = Returned_BSTR( result.bstrVal ); | |
| 109 } | |
| 110 else if ( result.vt == VT_I2 ) | |
| 111 { | |
| 112 // | |
| 113 std::wostringstream ss; | |
| 114 ss << result.iVal; | |
| 115 attr_value = ss.str(); | |
| 116 } | |
| 117 else if ( result.vt == VT_I4 ) | |
| 118 { | |
| 119 std::wostringstream ss; | |
| 120 ss << result.lVal; | |
| 121 attr_value = ss.str(); | |
| 122 } | |
| 123 /* | |
| 124 * If the result variant does not return one of the above supported types, | |
| 125 * we return true, indicating the attribute is found, but no attribute val ue. | |
| 126 */ | |
| 127 return true; | |
| 128 } | |
| 129 | |
| 130 /* | |
| 131 * This implementation relies on the behavior that IE returns a variant of typ e VT_I4 for integer values. | |
| 132 */ | |
| 133 bool HTML_Element::attribute( std::wstring attr_name, int & attr_value ) const | |
| 134 { | |
| 135 static_assert( sizeof( int ) >= 4, "Size of 'int' must be at least 4" ); | |
| 136 VARIANT result; | |
| 137 BSTR_Argument name( attr_name ); | |
| 138 | |
| 139 _element->getAttribute( name, 0, &result ); | |
| 140 /* | |
| 141 * VT_I4 and VT_I2 are supported, VT_I2 just to be defensive. | |
| 142 */ | |
| 143 if ( result.vt == VT_I4 ) | |
| 144 { | |
| 145 attr_value = result.lVal; | |
| 146 return true; | |
| 147 } | |
| 148 else if ( result.vt == VT_I2 ) | |
| 149 { | |
| 150 attr_value = result.iVal; | |
| 151 return true; | |
| 152 } | |
| 153 /* | |
| 154 * Any other return type will return false, | |
| 155 * whether the attribute is not present or whether it's present but not a (supported) integer type. | |
| 156 */ | |
| 157 if ( result.vt == VT_BSTR ) | |
| 158 { | |
| 159 /* | |
| 160 * If we get a BSTR return value, we need to release it, even if we're not using it. | |
| 161 * The destructor for Returned_BSTR takes care of that | |
| 162 */ | |
| 163 Returned_BSTR( result.bstrVal ); | |
| 164 } | |
| 165 return false; | |
| 166 } | |
| 167 | |
| 168 bool HTML_Element::id( std::wstring & value ) const | |
| 169 { | |
| 170 BSTR result; | |
| 171 HRESULT hr = _element->get_id( &result ); | |
| 172 if ( hr == S_OK ) | |
| 173 { | |
| 174 value = result ? Returned_BSTR( result ) : std::wstring(); | |
| 175 return true; | |
| 176 } | |
| 177 return false; | |
| 178 } | |
| 179 | |
| 180 bool HTML_Element::class_name( std::wstring & value ) const | |
| 181 { | |
| 182 BSTR result; | |
| 183 HRESULT hr = _element->get_className( &result ); | |
| 184 /* | |
| 185 * get_className seems to return S_OK and result==NULL as a valid answer. | |
| 186 */ | |
| 187 if ( hr == S_OK ) | |
| 188 { | |
| 189 value = result ? Returned_BSTR( result ) : std::wstring(); | |
| 190 return true; | |
| 191 } | |
| 192 return false; | |
| 193 } | |
| 194 | |
| 195 bool HTML_Element::inner_HTML( std::wstring & value ) const | |
| 196 { | |
| 197 BSTR result; | |
| 198 HRESULT hr = _element->get_innerHTML( &result ); | |
| 199 if ( hr == S_OK ) | |
| 200 { | |
| 201 value = result ? Returned_BSTR( result ) : std::wstring(); | |
| 202 return true; | |
| 203 } | |
| 204 return false; | |
| 205 } | |
| 206 | |
| 207 bool HTML_Element::tag_name( std::wstring & value ) const | |
| 208 { | |
| 209 BSTR result; | |
| 210 HRESULT hr = _element->get_tagName( &result ); | |
| 211 if ( hr == S_OK ) | |
| 212 { | |
| 213 value = result ? Returned_BSTR( result ) : std::wstring(); | |
| 214 return true; | |
| 215 } | |
| 216 return false; | |
| 217 } | |
| 218 | |
| 219 bool HTML_Style::display( std::wstring & value ) const | |
| 220 { | |
| 221 BSTR result; | |
| 222 HRESULT hr = _style->get_display( &result ); | |
| 223 if ( hr == S_OK ) | |
| 224 { | |
| 225 value = result ? Returned_BSTR( result ) : std::wstring(); | |
| 226 return true; | |
| 227 } | |
| 228 return false; | |
| 229 } | |
| 230 | |
| 231 bool HTML_Style::assign_display( const std::wstring & value ) | |
| 232 { | |
| 233 BSTR_Argument value_arg( value ); | |
| 234 HRESULT hr = _style->put_display( value_arg ); | |
| 235 return hr == S_OK; | |
| 236 } | |
| 237 | |
| 238 bool HTML_Style::CSS_text( std::wstring & value ) const | |
| 239 { | |
| 240 BSTR result; | |
| 241 HRESULT hr = _style->get_cssText( &result ); | |
| 242 if ( hr == S_OK ) | |
| 243 { | |
| 244 value = result ? Returned_BSTR( result ) : std::wstring(); | |
| 245 return true; | |
| 246 } | |
| 247 return false; | |
| 248 } | |
| 249 | |
| 250 IDispatch * HTML_Element_Collection::at( long index ) | |
| 251 { | |
| 252 VARIANT index_arg; | |
| 253 index_arg.vt = VT_I4; | |
| 254 index_arg.lVal = index; | |
| 255 | |
| 256 VARIANT nothing; | |
| 257 nothing.vt = VT_EMPTY; | |
| 258 | |
| 259 IDispatch * result; | |
| 260 HRESULT hr = _elements->item( index_arg, nothing, &result ); | |
| 261 /* | |
| 262 * Although item() returns S_OK if the element is not found, | |
| 263 * it still might return other values and have undocumented effects on 're sult'. | |
| 264 */ | |
| 265 return ( hr != S_OK ) ? 0 : result; | |
| 266 } | |
| 267 } | |
| OLD | NEW |