Coverage Report - com.mattunderscore.http.headers.useragent.parser.IOSBrowserParser
 
Classes in this File Line Coverage Branch Coverage Complexity
IOSBrowserParser
49%
53/107
56%
33/58
16
 
 1  
 /* Copyright © 2013 Matthew Champion
 2  
 All rights reserved.
 3  
 
 4  
 Redistribution and use in source and binary forms, with or without
 5  
 modification, are permitted provided that the following conditions are met:
 6  
     * Redistributions of source code must retain the above copyright
 7  
       notice, this list of conditions and the following disclaimer.
 8  
     * Redistributions in binary form must reproduce the above copyright
 9  
       notice, this list of conditions and the following disclaimer in the
 10  
       documentation and/or other materials provided with the distribution.
 11  
     * Neither the name of mattunderscore.com nor the
 12  
       names of its contributors may be used to endorse or promote products
 13  
       derived from this software without specific prior written permission.
 14  
 
 15  
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 16  
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 17  
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 18  
 DISCLAIMED. IN NO EVENT SHALL MATTHEW CHAMPION BE LIABLE FOR ANY
 19  
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 20  
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 21  
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 22  
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23  
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 24  
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 25  
 
 26  
 package com.mattunderscore.http.headers.useragent.parser;
 27  
 
 28  
 import static com.mattunderscore.http.headers.useragent.parser.ParsingUtils.nextElement;
 29  
 import static com.mattunderscore.http.headers.useragent.parser.ParsingUtils.nextElementStart;
 30  
 
 31  
 import com.mattunderscore.http.headers.useragent.details.application.Browser;
 32  
 import com.mattunderscore.http.headers.useragent.details.application.Firefox;
 33  
 import com.mattunderscore.http.headers.useragent.details.application.LikeFirefox;
 34  
 import com.mattunderscore.http.headers.useragent.details.application.Opera;
 35  
 import com.mattunderscore.http.headers.useragent.details.application.Safari;
 36  
 import com.mattunderscore.http.headers.useragent.details.application.SafariBased;
 37  
 import com.mattunderscore.http.headers.useragent.details.platform.AppleMobileFirmware;
 38  
 import com.mattunderscore.http.headers.useragent.details.platform.BlackBerryOS;
 39  
 import com.mattunderscore.http.headers.useragent.details.platform.Gecko;
 40  
 import com.mattunderscore.http.headers.useragent.details.platform.LayoutEngine;
 41  
 import com.mattunderscore.http.headers.useragent.details.platform.LikeGecko;
 42  
 import com.mattunderscore.http.headers.useragent.details.platform.Presto;
 43  
 
 44  
 /**
 45  
  * Parser for iOS user agent strings
 46  
  * @author Matt Champion
 47  
  * @since 0.2.7
 48  
  */
 49  
 /*package*/ class IOSBrowserParser implements TokensParser
 50  
 {
 51  
     /*package*/ IOSBrowserParser()
 52  2
     {
 53  2
     }
 54  
 
 55  
     /**
 56  
      * Parses the remaining tokens for an iOS Browser.
 57  
      * @param state
 58  
      */
 59  
     @Override
 60  
     public void parseTokens(ParsingState state)
 61  
     {
 62  14
         String remainingHeader = state.getRemaining();
 63  126
         while (!"".equals(remainingHeader))
 64  
         {
 65  112
             String oldHeader = remainingHeader;
 66  112
             if (remainingHeader.startsWith("AppleWebKit"))
 67  
             {
 68  14
                 String version = nextElement(remainingHeader.substring(12));
 69  14
                 state.addDetail(new LayoutEngine("AppleWebKit",version));
 70  14
                 remainingHeader = remainingHeader.substring(12 + version.length());
 71  14
             }
 72  98
             else if (remainingHeader.startsWith("KHTML"))
 73  
             {
 74  14
                 if ("/".equals(remainingHeader.substring(5,6)))
 75  
                 {
 76  0
                     String version = nextElement(remainingHeader.substring(6));
 77  0
                     state.addDetail(new LayoutEngine("KHTML",version));
 78  0
                     remainingHeader = remainingHeader.substring(6 + version.length());
 79  0
                 }
 80  
                 else
 81  
                 {
 82  14
                     state.addDetail(new LayoutEngine("KHTML","like"));
 83  14
                     remainingHeader = remainingHeader.substring(6);
 84  
                 }
 85  
             }
 86  84
             else if (remainingHeader.startsWith("Mobile"))
 87  
             {
 88  14
                 if (state.isIPad() || state.isIPhone() ||
 89  2
                         state.isIPod() || state.isIPhoneSimulator())
 90  
                 {
 91  14
                     String version = nextElement(remainingHeader.substring(7));
 92  14
                     state.addDetail(new AppleMobileFirmware(version));
 93  14
                     remainingHeader = remainingHeader.substring(7 + version.length());
 94  14
                 }
 95  
                 else
 96  
                 {
 97  0
                     remainingHeader = remainingHeader.substring(6);
 98  
                 }
 99  
             }
 100  70
             else if (remainingHeader.startsWith("like"))
 101  
             {
 102  14
                 remainingHeader = remainingHeader.substring(5);
 103  14
                 if (remainingHeader.startsWith("Gecko"))
 104  
                 {
 105  14
                     state.addDetail(new LikeGecko());
 106  14
                     remainingHeader = remainingHeader.substring(5);
 107  
                 }
 108  0
                 else if (remainingHeader.startsWith("Firefox"))
 109  
                 {
 110  0
                     String version = nextElement(remainingHeader.substring(8));
 111  0
                     state.addDetail(new LikeFirefox(version));
 112  0
                     remainingHeader = remainingHeader.substring(8 + version.length());
 113  0
                 }
 114  
             }
 115  56
             else if (remainingHeader.startsWith("Gecko"))
 116  
             {
 117  0
                 String trail = nextElement(remainingHeader.substring(6));
 118  0
                 String rv = state.getValue("rv");
 119  0
                 if (rv != null)
 120  
                 {
 121  0
                     state.addDetail(new Gecko(rv,trail));
 122  0
                     remainingHeader = remainingHeader.substring(6 + trail.length());
 123  
                 }
 124  
                 else
 125  
                 {
 126  0
                     state.addDetail(new Gecko());
 127  0
                     remainingHeader = remainingHeader.substring(6);
 128  
                 }
 129  0
             }
 130  56
             else if (remainingHeader.startsWith("Presto"))
 131  
             {
 132  0
                 String version = nextElement(remainingHeader.substring(7));
 133  0
                 state.addDetail(new Presto(version));
 134  0
                 remainingHeader = remainingHeader.substring(7 + version.length());
 135  
             }
 136  112
             if (remainingHeader.startsWith("Chrome"))
 137  
             {
 138  0
                 String version = nextElement(remainingHeader.substring(7));
 139  0
                 state.addDetail(new Browser("Chrome",version));
 140  0
                 remainingHeader = remainingHeader.substring(7 + version.length());
 141  0
                 if (remainingHeader.startsWith(" Safari"))
 142  
                 {
 143  0
                     String buildNumber = nextElement(remainingHeader.substring(8));
 144  0
                     state.addDetail(new SafariBased(buildNumber));
 145  0
                     remainingHeader = remainingHeader.substring(8 + buildNumber.length());
 146  
                 }
 147  0
             }
 148  112
             else if (remainingHeader.startsWith("Opera"))
 149  
             {
 150  0
                 String version = nextElement(remainingHeader.substring(6));
 151  0
                 if (!version.equals("9.80"))
 152  
                 {
 153  0
                     state.addDetail(new Opera(version));
 154  0
                     remainingHeader = remainingHeader.substring(6 + version.length());
 155  0
                     state.setOperaSet(true);
 156  
                 }
 157  
                 else
 158  
                 {
 159  0
                     state.setOperaClaim(version);
 160  0
                     remainingHeader = remainingHeader.substring(6 + version.length());
 161  
                 }
 162  0
             }
 163  112
             else if (remainingHeader.startsWith("Firefox"))
 164  
             {
 165  0
                 String version = nextElement(remainingHeader.substring(8));
 166  0
                 state.addDetail(new Firefox(version));
 167  0
                 remainingHeader = remainingHeader.substring(8 + version.length());
 168  0
             }
 169  112
             else if (remainingHeader.startsWith("Version"))
 170  
             {
 171  14
                 String version = nextElement(remainingHeader.substring(8));
 172  14
                 if (state.getOperaClaim() != null)
 173  
                 {
 174  0
                     state.addDetail(new Opera(version,state.getOperaClaim()));
 175  0
                     remainingHeader = remainingHeader.substring(8 + version.length());
 176  0
                     state.setOperaSet(true);
 177  
                 }
 178  14
                 else if (state.isBlackBerry())
 179  
                 {
 180  0
                     state.addDetail(new BlackBerryOS(version));
 181  0
                     remainingHeader = remainingHeader.substring(8 + version.length());
 182  
                 }
 183  
                 else
 184  
                 {
 185  14
                     state.addKeyValuePair("Version", version);
 186  14
                     remainingHeader = remainingHeader.substring(8 + version.length());
 187  
                 }
 188  14
             }
 189  98
             else if (remainingHeader.startsWith("Safari"))
 190  
             {
 191  14
                 if (state.isBlackBerry())
 192  
                 {
 193  0
                     String buildNumber = nextElement(remainingHeader.substring(7));
 194  0
                     state.addDetail(new SafariBased(buildNumber));
 195  0
                     remainingHeader = remainingHeader.substring(7 + buildNumber.length());
 196  0
                 }
 197  
                 else
 198  
                 {
 199  14
                     String version = state.getValue("Version");
 200  14
                     String buildNumber = nextElement(remainingHeader.substring(7));
 201  14
                     if (version != null)
 202  
                     {
 203  14
                         state.addDetail(new Safari(version,buildNumber));
 204  
                     }
 205  
                     else
 206  
                     {
 207  0
                         state.addDetail(new SafariBased(buildNumber));
 208  
                     }
 209  14
                     remainingHeader = remainingHeader.substring(7 + buildNumber.length());
 210  
                 }
 211  
             }
 212  
             // Clean up
 213  112
             if (oldHeader.equals(remainingHeader))
 214  
             {
 215  28
                 int nextElement = nextElementStart(remainingHeader);
 216  28
                 if (nextElement == 0)
 217  
                 {
 218  28
                     remainingHeader = remainingHeader.substring(1);
 219  
                 }
 220  0
                 else if (nextElement != -1)
 221  
                 {
 222  0
                     remainingHeader = remainingHeader.substring(nextElement);
 223  
                 }
 224  
                 else
 225  
                 {
 226  0
                     return;
 227  
                 }
 228  
             }
 229  112
             remainingHeader = remainingHeader.trim();
 230  112
         }
 231  14
         state.setRemaining(remainingHeader);
 232  14
         return;
 233  
     }
 234  
 }