16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#ifndef COMPONENTS_OMNIBOX_AUTOCOMPLETE_RESULT_H_ 66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#define COMPONENTS_OMNIBOX_AUTOCOMPLETE_RESULT_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "components/metrics/proto/omnibox_event.pb.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_match.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass AutocompleteInput; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AutocompleteProvider; 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass TemplateURLService; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All matches from all providers for a particular query. This also tracks 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// what the default match should be if the user doesn't manually select another 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// match. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AutocompleteResult { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ACMatches::const_iterator const_iterator; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ACMatches::iterator iterator; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The "Selection" struct is the information we need to select the same match 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in one result set that was selected in another. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Selection { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Selection() 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : provider_affinity(NULL), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_history_what_you_typed_match(false) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the selection entirely. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True when the selection is empty. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool empty() const { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return destination_url.is_empty() && !provider_affinity && 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_history_what_you_typed_match; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The desired destination URL. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL destination_url; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The desired provider. If we can't find a match with the specified 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |destination_url|, we'll use the best match from this provider. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteProvider* provider_affinity; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True when this is the HistoryURLProvider's "what you typed" match. This 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can't be tracked using |destination_url| because its URL changes on every 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // keystroke, so if this is set, we'll preserve the selection by simply 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // choosing the new "what you typed" entry and ignoring |destination_url|. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_history_what_you_typed_match; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Max number of matches we'll show from the various providers. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kMaxMatches; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteResult(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~AutocompleteResult(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copies matches from |old_matches| to provide a consistant result set. See 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // comments in code for specifics. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CopyOldMatches(const AutocompleteInput& input, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteResult& old_matches, 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TemplateURLService* template_url_service); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds a new set of matches to the result set. Does not re-sort. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AppendMatches(const ACMatches& matches); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes duplicates, puts the list in sorted order and culls to leave only 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the best kMaxMatches matches. Sets the default match to the best match 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and updates the alternate nav URL. 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void SortAndCull(const AutocompleteInput& input, 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TemplateURLService* template_url_service); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if at least one match was copied from the last result. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HasCopiedMatches() const; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vector-style accessors/operators. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size() const; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool empty() const; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_iterator begin() const; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator begin(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_iterator end() const; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator end(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the match at the given index. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteMatch& match_at(size_t index) const; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteMatch* match_at(size_t index); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the default match for the query (not necessarily the first). Returns 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // end() if there is no default match. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_iterator default_match() const { return default_match_; } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // Returns true if the top match is a verbatim search or URL match (see 1012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // IsVerbatimType() in autocomplete_match.h), and the next match is not also 1022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // some kind of verbatim match. In this case, the top match will be hidden, 1032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // and nothing in the dropdown will appear selected by default; hitting enter 1042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // will navigate to the (hidden) default match, while pressing the down arrow 1052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // key will select the first visible match, which is actually the second match 1062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // in the result set. 1072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // 1082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // Hiding the top match in these cases is possible because users should 1092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // already know what will happen on hitting enter from the omnibox text 1102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // itself, without needing to see the same text appear again, selected, just 1112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // below their typing. Instead, by hiding the verbatim match, there is one 1122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // less line to skip over in order to visually scan downwards to see other 1132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // suggested matches. This makes it more likely that users will see and 1142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // select useful non-verbatim matches. (Note that hiding the verbatim match 1152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // this way is similar to how most other browsers' address bars behave.) 1162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // 1172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // We avoid hiding when the top two matches are both verbatim in order to 1182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // avoid potential confusion if a user were to see the second match just below 1192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // their typing and assume it would be the default action. 1202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // 1212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // Note that if the top match should be hidden and it is the only match, 1222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // the dropdown should be closed. 1232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch bool ShouldHideTopMatch() const; 1242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Returns true if the top match is a verbatim search or URL match (see 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // IsVerbatimType() in autocomplete_match.h), and the next match is not also 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // some kind of verbatim match. 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool TopMatchIsStandaloneVerbatimMatch() const; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& alternate_nav_url() const { return alternate_nav_url_; } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clears the matches for this result set. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Reset(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Swap(AutocompleteResult* other); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Does a data integrity check on this result. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Validate() const; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Compute the "alternate navigation URL" for a given match. This is obtained 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // by interpreting the user input directly as a URL. See comments on 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // |alternate_nav_url_|. 1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static GURL ComputeAlternateNavUrl(const AutocompleteInput& input, 1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const AutocompleteMatch& match); 1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Sort |matches| by destination, taking into account demotions based on 149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // |page_classification| when resolving ties about which of several 150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // duplicates to keep. The matches are also deduplicated. If 151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // |set_duplicate_matches| is true, the duplicate matches are stored in the 152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // |duplicate_matches| vector of the corresponding AutocompleteMatch. 153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch static void DedupMatchesByDestination( 1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) metrics::OmniboxEventProto::PageClassification page_classification, 155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool set_duplicate_matches, 156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ACMatches* matches); 157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch friend class AutocompleteProviderTest; 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<AutocompleteProvider*, ACMatches> ProviderToMatches; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iterator::difference_type is not defined in the STL that we compile with on 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Android. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef int matches_difference_type; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ACMatches::iterator::difference_type matches_difference_type; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // Returns true if |matches| contains a match with the same destination as 1722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // |match|. 1732385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch static bool HasMatchByDestination(const AutocompleteMatch& match, 1742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch const ACMatches& matches); 1752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // operator=() by another name. 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch void CopyFrom(const AutocompleteResult& rhs); 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populates |provider_to_matches| from |matches_|. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void BuildProviderToMatches(ProviderToMatches* provider_to_matches) const; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copies matches into this result. |old_matches| gives the matches from the 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last result, and |new_matches| the results from this result. 184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch void MergeMatchesByProvider( 1856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) metrics::OmniboxEventProto::PageClassification page_classification, 186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const ACMatches& old_matches, 187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const ACMatches& new_matches); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACMatches matches_; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_iterator default_match_; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The "alternate navigation URL", if any, for this result set. This is a URL 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to try offering as a navigational option in case the user navigated to the 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL of the default match but intended something else. For example, if the 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user's local intranet contains site "foo", and the user types "foo", we 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default to searching for "foo" when the user may have meant to navigate 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there. In cases like this, the default match will point to the "search for 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'foo'" result, and this will contain "http://foo/". 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL alternate_nav_url_; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AutocompleteResult); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif // COMPONENTS_OMNIBOX_AUTOCOMPLETE_RESULT_H_ 206