Ian Whiffin
Posted: 2nd July 2024
Revised: 2024-09-09 Tweet #share
In the last few weeks, there’s been a few more examiners reach out about this. There's clearly still some confusion so I thought I should do a brief update to clarify.
As I previously stated, the BrowserState last_viewed_time is the time the tab took focus. The URL and Title shown in the database are related to the most recent page visited in that tab.
There are differences between iOS versions that determine when the record is written but the meaning of the timestamp appears consistent.
Testing iOS14 & Below
iOS 12, 13, 14 all create the BrowserState record immediately when a tab is created continuously update the URL and Title fields as navigation occurs. The timestamp is updated when the tab is given or loses focus.
To test this:
I opened a tab at 9:21 and searched for “9:21“. The BrowserState record was immediately created. The timestamp and URL/Title both showed 9:21:
At 9:22, I searched for “922” and checked the database again.
You can see that the title is updated but the last_viewed_time remains 9:21.
I then completely closed Safari, reopening it at 9:23 and searched for “923”. Checking the database showed the updated timestamp and title:
Closing the tab and checking the database again showed no change to the data at all.
Testing iOS15 & Above
In iOS 15, 16, 17 and the 18 Beta, the record is not made in the BrowserState database immediately, and therefore never has to be updated. It appears everything is stored in RAM and only written to database when the tab is closed. Again though, the last_viewed_time is the time the tab took focus.
I created a tab at 10:23 and searched for “1023”. Checking the database, there was no record.
At 10:24, I closed the tab and rechecked the database.
At 1025 I created a new tab and searched for “1025”.
At 1026, I used the same tab to search for “1026”.
I then closed the tab and checked the database.
As you can see, the last_viewed_time still reflects the time the tab was focused and the URL and Title are the related to the most recent page visited.
Tab Focus?
Tab Focus can occur for a few different reasons;
The tab is created and therefore takes focus.
Safari is closed (not backgrounded) and reopened. The reopening causes the tab to take focus.
Switching between tabs. The tab being brought INTO view takes focus. The tab being moved OUT of view is updated (but this will only be reflected if the tab is closed without ever receiving focus again)
Closing a tab - Big BUT here. The tab being closed is NOT updated. But, the process of closing one tab causes another tab to take focus and therefore the tab receiving focus is updated.
Scenarios
This can cause some interesting scenarios that it’s worth looking at individually.
Scenario 1
Imagine I open a tab at 10am and search for “1000”. The last_viewed_time inherits the time the tabs took focus (in this case, when the tab was created), so, 10am.
I then minimize safari for 1 hour, reopening it at 11am. Minimize/Maximize doesn’t affect the focus, so no timestamps are updated.
I can close the tab, and the record will show a last_viewed_time of 10am and a search of “1000”, making it appear accurate.
Scenario 2
Similar setup to before. Open a tab at 10am and search for “1000”. I then CLOSE safari, and OPEN it an hour later.
Opening Safari from a closed state DOES update the timestamp. So the timestamp now reads 11am. I close the tab and the record is written with a timestamp of 11am and a search term of “1000”. This is clearly not accurate and makes it appear the search for “1000” was conducted at 11am.
Scenario 3
Keeping the same setup still, tab opened at 10am and searched for “1000”.
This time, I keep safari open for the next hour and run a new search every minute. So I have a search at 10:01 for “1001”, a search at 10:02 for “1002” and so on.
At 11:00 I do my final search for “1100” and close the tab.
Throughout the hour, the same tab has been in focus and so the timestamp was never updated.
The record in the database will show a last_viewed_time of 10am and the most recent URL visited of “1100”. This is also not accurate and makes it appear that I searched for “1100” at 10am.
Scenario 4
Finally, sticking with the same premise, I open a tab at 10am and search for “1000”. I MINIMIZE Safari for the hour. At 11am I MAXIMIZE Safari and search for “1100”. Again, since minimize/maximize doesn’t cause a refocus to occur, the last_viewed_time remains 10am but the URL shows the most recent value of “1100”. This has the same result as Scenario 3 and makes it appear I searched for “1100” at 10am.
Timeline
I'll also present the data in a timeline which I hope will add further clarity.
This table attempts to show the state of the last_viewed_time, URL and Title as they exist in memory and/or database (depending on iOS version).
Time
Action
Tab Focus Event
Navigation Event
Result
10:00
Open a tab.
Search for "1000".
Yes
Yes
last_viewed_time: 10:00 URL : Relates to "1000" search Title : "1000"
This can easily be mistaken as a correlation between the last_viewed_time and the URL. But it is just a coincidence.
10:05
Search "1005" in same tab.
No
Yes
last_viewed_time: 10:00 URL : Relates to "1005" search Title : "1005"
This could be mistaken as the "1005" search occured at 10:00.
10:10
Minimize Safari
No
No
last_viewed_time: 10:00 URL : Relates to "1005" search Title : "1005"
No change.
10:15
Maximize Safari
No
No
last_viewed_time: 10:00 URL : Relates to "1005" search Title : "1005"
No change.
10:20
Search for "1020"
No
Yes
last_viewed_time: 10:00 URL : Relates to "1020" search Title : "1020"
This could be mistaken as the "1020" search occuring at 10:00.
10:25
Close Safari
No
No
last_viewed_time: 10:00 URL : Relates to "1020" search Title : "1020"
No change.
10:30
Open Safari
Yes
No
last_viewed_time: 10:30 URL : Relates to "1020" search Title : "1020"
This could be mistaken as the "1020" search occuring at 10:30.
10:35
Open new tab (Tab 2)
Search for "1035"
Yes
Yes
last_viewed_time: 10:30 URL : Relates to "1020" search Title : "1020"
last_viewed_time: 10:35 URL : Relates to "1035" search Title : "1035"
A new Tab is created but the original tab is unaffected.
10:40
Close Tab 2
This causes
Tab 1 comes back into focus.
Yes
No
last_viewed_time: 10:40 URL : Relates to "1020" search Title : "1020"
The original tab's last_viewed_time is updated which could be mistaken for the "1020" search occuring at 10:40.
10:45
Search for "1045"
No
Yes
last_viewed_time: 10:40 URL : Relates to "1045" search Title : "1045"
This could be mistaken as the "1045" search occuring at 10:40.
Hopefully, the above scenarios and table demonstrates that there are occasions where;
The last_viewed_time is NEWER than the contents of the URL and Title field (as is the case at 10:30 and 10:40).
The last_viewed_time is OLDER than the contents of the URL and Title field (as is the case at 10:05, 10:20 and 10:45).
Essentially, the last_viewed_time value could be before or after the actual time of the URL visit. Making this timestamp utterly unreliable.
Wrapping Up
The nice thing about this artifact is that it’s super easy to test for yourself. BrowserState.db is included within an Encrypted iTunes Backup so you don’t even need an advanced extraction tool.