1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// found in the LICENSE file. 4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/history/url_utils.h" 6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include <algorithm> 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "url/gurl.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace history { 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace { 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Comparator to enforce '\0' < '?' < '#' < '/' < other characters. 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int GetURLCharPriority(char ch) { 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) switch (ch) { 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case '\0': return 0; 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case '?': return 1; 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case '#': return 2; 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case '/': return 3; 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return 4; 24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace 27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Instead of splitting URLs and extract path components, we can implement 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// CanonicalURLStringCompare() using string operations only. The key idea is, 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// treating '/' to be less than any valid path characters would make it behave 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// as a separator, so e.g., "test" < "test-case" would be enforced by 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// "test/..." < "test-case/...". We also force "?" < "/", so "test?query" < 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// "test/stuff". Since the routine is merely lexicographical string comparison 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// with remapping of chracter ordering, so it is a valid strict-weak ordering. 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool CanonicalURLStringCompare(const std::string& s1, const std::string& s2) { 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string::value_type* ch1 = s1.c_str(); 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string::value_type* ch2 = s2.c_str(); 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) while (*ch1 && *ch2 && *ch1 == *ch2) { 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ++ch1; 40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ++ch2; 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int pri_diff = GetURLCharPriority(*ch1) - GetURLCharPriority(*ch2); 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We want false to be returned if |pri_diff| > 0. 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return (pri_diff != 0) ? pri_diff < 0 : *ch1 < *ch2; 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool HaveSameSchemeHostAndPort(const GURL&url1, const GURL& url2) { 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return url1.scheme() == url2.scheme() && url1.host() == url2.host() && 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) url1.port() == url2.port(); 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsPathPrefix(const std::string& p1, const std::string& p2) { 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (p1.length() > p2.length()) 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::pair<std::string::const_iterator, std::string::const_iterator> 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) first_diff = std::mismatch(p1.begin(), p1.end(), p2.begin()); 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Necessary condition: |p1| is a string prefix of |p2|. 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (first_diff.first != p1.end()) 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; // E.g.: (|p1| = "/test", |p2| = "/exam") => false. 60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |p1| is string prefix. 62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (first_diff.second == p2.end()) // Is exact match? 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; // E.g.: ("/test", "/test") => true. 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |p1| is strict string prefix, check full match of last path component. 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!p1.empty() && *p1.rbegin() == '/') // Ends in '/'? 66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; // E.g.: ("/test/", "/test/stuff") => true. 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Finally, |p1| does not end in "/": check first extra character in |p2|. 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // E.g.: ("/test", "/test/stuff") => true; ("/test", "/testing") => false. 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return *(first_diff.second) == '/'; 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)GURL ToggleHTTPAndHTTPS(const GURL& url) { 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string new_scheme; 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (url.SchemeIs("http")) 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new_scheme = "https"; 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else if (url.SchemeIs("https")) 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new_scheme = "http"; 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else 801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return GURL::EmptyGURL(); 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu url::Component comp; 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) comp.len = new_scheme.length(); 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GURL::Replacements replacement; 841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) replacement.SetScheme(new_scheme.c_str(), comp); 851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return url.ReplaceComponents(replacement); 861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace history 89