<html>
    <head>
      <base href="https://bugs.webkit.org/" />
    </head>
    <body><span class="vcard"><a class="email" href="mailto:darin&#64;apple.com" title="Darin Adler &lt;darin&#64;apple.com&gt;"> <span class="fn">Darin Adler</span></a>
</span> changed
              <a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - We should also store the time information for recent searches"
   href="https://bugs.webkit.org/show_bug.cgi?id=148388">bug 148388</a>
        <br>
             <table border="1" cellspacing="0" cellpadding="8">
          <tr>
            <th>What</th>
            <th>Removed</th>
            <th>Added</th>
          </tr>

         <tr>
           <td style="text-align:right;">Attachment #262212 Flags</td>
           <td>review?
           </td>
           <td>review-
           </td>
         </tr></table>
      <p>
        <div>
            <b><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - We should also store the time information for recent searches"
   href="https://bugs.webkit.org/show_bug.cgi?id=148388#c28">Comment # 28</a>
              on <a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - We should also store the time information for recent searches"
   href="https://bugs.webkit.org/show_bug.cgi?id=148388">bug 148388</a>
              from <span class="vcard"><a class="email" href="mailto:darin&#64;apple.com" title="Darin Adler &lt;darin&#64;apple.com&gt;"> <span class="fn">Darin Adler</span></a>
</span></b>
        <pre>Comment on <span class=""><a href="attachment.cgi?id=262212&amp;action=diff" name="attach_262212" title="Patch v4">attachment 262212</a> <a href="attachment.cgi?id=262212&amp;action=edit" title="Patch v4">[details]</a></span>
Patch v4

View in context: <a href="https://bugs.webkit.org/attachment.cgi?id=262212&amp;action=review">https://bugs.webkit.org/attachment.cgi?id=262212&amp;action=review</a>

Looks generally good, but review- because of the incorrect code to read from disk (see below for details)

<span class="quote">&gt; Source/WebCore/platform/SearchPopupMenu.h:40
&gt; +typedef struct RecentSearchItem {
&gt; +    RecentSearchItem() { }
&gt; +
&gt; +    RecentSearchItem(const String&amp; searchString, std::chrono::system_clock::time_point time)
&gt; +        : searchString(searchString), time(time) { }
&gt; +
&gt; +    String searchString;
&gt; +    std::chrono::system_clock::time_point time;
&gt; +} RecentSearchItem;</span >

This typedef struct X {} X; pattern is completely unnecessary in C++. Just struct X { } is fine. There is no need to create constructors for a struct like this in modern C++. I also don’t think there’s a good reason to call this searchString and time rather than searchString and searchTime or just string and time. And further, there’s no reason to call this both recent searches and recent search items. I don’t think the word items adds much. So this should be:

    struct RecentSearch {
        String string;
        std::chrono::system_clock::time_point time;
    };

<span class="quote">&gt; Source/WebCore/platform/win/SearchPopupMenuWin.cpp:94
&gt; +            searchItems.append(RecentSearchItem((String)(CFStringRef)item, std::chrono::system_clock::time_point::min()));</span >

The cast to CFStringRef here is not helpful since item is already a CFStringRef. The C-style cast to String here is not something we normally do. I suggest a C++ style cast. Passing min() here requires a comment; it’s not obvious why ti’s OK. And we should use aggregate syntax for this struct. So please add a comment explaining why min is correct and write something more like this:

    searchItems.append({ String{ item }, std::chrono::system_clock::time_point::min() });

<span class="quote">&gt; Source/WebCore/rendering/RenderSearchField.cpp:94
&gt; +    m_recentSearches.insert(0, RecentSearchItem(value, std::chrono::system_clock::now()));</span >

Please use aggregate syntax rather than constructor syntax:

    m_recentSearches.insert(0, { value, std::chrono::system_clock::now() });

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:52
&gt; +static NSMutableDictionary *readSearchFieldRecentSearchesPlist()
&gt; +{
&gt; +    return [[NSMutableDictionary alloc] initWithContentsOfFile:searchFieldRecentSearchesPlistPath()];
&gt; +}</span >

This function is dangerous. It returns a newly created Objective-C object, but doesn’t use autorelease, nor wrap the pointer in a RetainPtr, nor does it follow the create/copy rule for naming functions that create new objects without autoreleasing them. I suggest using RetainPtr for the result here so we don’t leak memory.

I’m also not sure that [NSMutableDictionary initWithContentsOfFile:] is safe to use on an untrusted file. We need to instead use an appropriate API that doesn’t allow objects of arbitrary classes.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:78
&gt; +    NSMutableDictionary *recentSearchesPlist = readSearchFieldRecentSearchesPlist();</span >

Here we leak the contents of this file. That’s why we need to use a RetainPtr or autorelease.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:80
&gt; +        [recentSearchesPlist[itemsKey] removeObjectForKey:name];</span >

This won’t compile when targeting older versions of OS X, so we need to use objectForKey here instead of array subscripting syntax.

This code assumes that type of the key in the property list that we read in from will be a mutable dictionary and we can call removeObjectForKey on it. We don’t have a guarantee of that. We need to check the type of the object to see that it‘s a dictionary before modifying it, and we also need to make a mutable copy of the dictionary unless we are using an API that guarantees that any dictionaries it creates when reading the file are created mutable, which we currently are not doing.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:84
&gt; +            NSTimeInterval timeInterval = duration_cast&lt;duration&lt;double&gt;&gt;(searchItem.time.time_since_epoch()).count();</span >

I’d like to see a helper function template to convert a duration object into an NSDate rather than writing this out here. It’s also not good that the code that creates the interval since 1970 is on a different line than the code that create the NSDate.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:88
&gt; +            NSDictionary *recentSearch = &#64;{
&gt; +                searchStringKey: searchItem.searchString,
&gt; +                dateKey: [NSDate dateWithTimeIntervalSince1970:timeInterval]
&gt; +            };</span >

I’m pretty sure that the dictionary literal syntax is not supported in all tools that we use for the versions of OS X that we currently target with WebKit. This might need to use method calls instead. Unless I am mistaken.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:94
&gt; +            [recentSearchesPlist[itemsKey] setObject:&#64;{ searchesKey: items.get() } forKey:name];</span >

Same problem here as in the removeObjectForKey: call above, and same issue with literals.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:96
&gt; +            recentSearchesPlist = [&#64;{ itemsKey: &#64;{ name: &#64;{ searchesKey: items.get() } } } mutableCopy];</span >

Same issue with literals. Doesn’t seem to good to make a mutable copy here. Wasteful.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:99
&gt; +    [recentSearchesPlist writeToFile:searchFieldRecentSearchesPlistPath() atomically:YES];</span >

Using atomically:YES is costly in performance and in NAND life. We should be sure this is necessary.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:112
&gt; +    NSArray *recentSearches = [[[recentSearchesPlist objectForKey:itemsKey] objectForKey:name] objectForKey:searchesKey];</span >

Same comment about calling objectForKey: on an object of unknown type as above.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:115
&gt; +            system_clock::time_point searchItemTime = system_clock::time_point(duration_cast&lt;system_clock::duration&gt;(duration&lt;double&gt;(dynamic_objc_cast&lt;NSDate&gt;(item[dateKey]).timeIntervalSince1970)));</span >

Same comment about using helper functions to convert between NSDate and time points as above.

<span class="quote">&gt; Source/WebKit/mac/WebCoreSupport/SearchPopupMenuMac.mm:116
&gt; +            searchItems.append(WebCore::RecentSearchItem((String)item[searchStringKey], searchItemTime));</span >

Same comment about aggregate syntax.

<span class="quote">&gt; Source/WebKit2/UIProcess/Cocoa/WebPageProxyCocoa.mm:38
&gt; +static NSString * const dateKey = &#64;&quot;date&quot;;
&gt; +static NSString * const itemsKey = &#64;&quot;items&quot;;
&gt; +static NSString * const searchesKey = &#64;&quot;searches&quot;;
&gt; +static NSString * const searchStringKey = &#64;&quot;searchString&quot;;</span >

Seems quite bad to literally have copied and pasted code for WebKit 1 and WebKit 2. Please find a way to share more of the code.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are the assignee for the bug.</li>
      </ul>
    </body>
</html>