I had more than 200 tabs open on opera and they would normally reopen again, even after reboots.  

My phone broke, but I have a backup of the external SD Card, internal SD Card, and a backup from TWRP which is of a size of 23.7 GB but does not have an obviously accessible structure.  

Following the advice from [another QA](https://android.stackexchange.com/a/184831/96334), it is possible to concatenate the `data.ext4.win000` to `data.ext4.win009` files and access them as a tar archive (It's a good idea to cd to where you want the backup to be extracted to first):

> ```bash cat data.ext4.win??? | tar xvfi - ```
> 
> What this does is concatenate each file matching the pattern
> data.ext4.win??? and then pipe the concatenated files to tar for
> extraction. the - as the filename tells tar to extract from stdin. The
> i option ignores zero blocks which will be in between each archive
> file concatenated.
> 
> In this example I used the ext4 formatted data partition. Change
> data.ext4 to match the partition you are extracting.

Although the tar command exits with
> ```
/data/magisk_backup_bd5d0aa87b96353c78a3bf3a455121d0c767089c/boot.img.gz
tar: Exiting with failure status due to previous errors
> ```

it extracts quite a few files before this hapens.

Now that I have my `/data` directory again, I have access to `/data/data/com.opera.browser` and `/data/app/com.opera.browser-2`. What do I do with them to extract a list of urls that were open?

### Directory Structures
data/data/com.opera.browser
```
├───app_opera
│   ├───Application Cache
│   │   └───Cache
│   │       └───index-dir
│   ├───blob_storage
│   │   └───9b46839e-470e-4a3a-aa32-e9bc919a25f0
│   ├───databases
│   ├───databases-incognito
│   ├───File System
│   │   ├───026
│   │   │   └───t
│   │   │       └───Paths
│   │   └───Origins
│   ├───GCM Store
│   │   └───Encryption
│   ├───GPUCache
│   │   └───index-dir
│   ├───IndexedDB
│   │   ├───https_hackernoon.com_0.indexeddb.leveldb
│   │   ├───https_mobile.twitter.com_0.indexeddb.leveldb
│   │   ├───https_www.epicgames.com_0.indexeddb.leveldb
│   │   └───https_www.independent.co.uk_0.indexeddb.leveldb
│   ├───Local Storage
│   │   └───leveldb
│   ├───paks
│   ├───Platform Notifications
│   ├───saved_pages
│   ├───Service Worker
│   │   ├───CacheStorage
│   │   │   ├───5a6f7e336992bc24678958dc2f1f9b9eec83593b
│   │   │   │   ├───281ffb34-a074-4397-a60c-e3dc55aee5e5
│   │   │   │   │   └───index-dir
│   │   │   │   └───8d34090e-e00a-4f69-9450-bbe1b4b0dc9d
│   │   │   │       └───index-dir
│   │   │   ├───96f3041722d8f6857b95786ee88fa6a107a86943
│   │   │   │   └───11ccf6ea-9e2a-4648-8c61-a635e1cca5c5
│   │   │   │       └───index-dir
│   │   │   └───e60030e2e5440743857a39cacd108634434c91f1
│   │   │       ├───0045349f-4331-4037-bf9d-e9711e515a08
│   │   │       │   └───index-dir
│   │   │       ├───4a447cca-f7ca-41f1-9464-e40337cd7ed1
│   │   │       │   └───index-dir
│   │   │       └───907b2396-da18-4880-a0df-e3608abac640
│   │   │           └───index-dir
│   │   ├───Database
│   │   └───ScriptCache
│   │       └───index-dir
│   ├───Session Storage
│   ├───shared_proto_db
│   │   └───metadata
│   ├───Sync Data
│   │   └───LevelDB
│   └───VideoDecodeStats
├───app_optimized
├───app_textures
├───app_webview
│   ├───blob_storage
│   │   └───3f7cc261-4c0e-41cc-947b-2dc712733f49
│   ├───GPUCache
│   │   └───index-dir
│   └───Local Storage
│       └───leveldb
├───cache
│   ├───cache
│   │   └───index-dir
│   ├───Crashpad
│   │   ├───attachments
│   │   ├───completed
│   │   ├───new
│   │   └───pending
│   ├───crash_dumps
│   ├───distiller
│   │   └───index-dir
│   └───okhttp
├───code_cache
├───databases
├───files
│   ├───AFRequestCache
│   ├───ds
│   │   ├───10
│   │   └───E
│   ├───images
│   │   └───share
│   ├───keychain
│   │   └───0
│   ├───reading
│   └───recently_closed_tabs
├───no_backup
└───shared_prefs
```

data/app/com.opera.browser-2
```
├───lib
│   ├───arm
│   └───arm64
└───oat
    ├───arm
    └───arm64
```

data/data/com.opera.browser/files/
```
# 332 files of the nameformat "thumbnail_-214748????"
# 3   files of the nameformat "searchengine_j_<UUID>"
AFRequestCache             
appstate.bin                    
audience_network.dex     
cards_settings.dat           
ds                                  
favorite_25                     
favorite_29                     
favorite_31                     
favorites.json                  
images                           
keychain                        
newsfeedback                 
permissions.bin               
reading                          
recently_closed_tabs       
reksio.ini   
```

### System Info
I think I was on Android 7.1.1  
Rooted with Magisk, but stock ROM

### Recently Closed Tabs
Not what I am looking for right now, but I stumbled upon the location of those, in case a future viewer is looking for them:  
```
data/data/com.opera.browser/files/recently_closed_tabs/state-2147481796
```

### Related Links
* [How can I export all my open Firefox Tabs to a text file?](https://android.stackexchange.com/a/205587/96334) is posed about doing so on a living phone, but also points out where the file is located. The relevant file is called `sessionstore.js`.  
That does not seem useful for opera. grepping `find` for "session" only finds `shared_prefs/sessionrestore.xml` which contains nothing useful for my purposes.

* [How can I export the list of open Chrome tabs?](https://android.stackexchange.com/questions/56635/how-can-i-export-the-list-of-open-chrome-tabs)

### Promising Files `appstate.bin`
`data/data/com.opera.browser/files/appstate.bin` contains at least some urls and their titles, separated by a null-byte. `strings appstate.bin` outputs more than just the urls that were open though. And some of those doubly or not completely.
I shall document my journy with this file below.

Looking at `data/data/com.opera.browser/files/appstate.bin` shows that it's a binary data file, but it contains readable strings. Open it with `vim appstate.bin` or look at `hexdump -C appstate.bin`.

```bash
strings appstate.bin | grep -A3 reader_mode_state
```
already spits out quite a few urls. But it's not yet obvious to me how the structure of that file actually works.

Some entries prefix the url with `l` or `O` or `K` or `]` or not at all.  
In some entries the first line after "reader_mode_state" is the url, in others it is "operaui://startpage" and the url follows further below.

But what stands out is that the urls all seem to start with `http` or `https` - unless you had some ftp or such open, which I'm pretty confident I did not.

```bash
strings appstate.bin | grep http
```

outputs 1506 lines though. some links are duplicates, others are links I do not care about. e.g. like so:
```
Qhttps://www.linuxuprising.com/2018/06/fix-no-sound-dummy-output-issue-in.html?m=1
Qhttps://www.linuxuprising.com/2018/06/fix-no-sound-dummy-output-issue-in.html?m=1
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
https://www.linuxuprising.com
```

Since I don't care about duplicates, we can apply `uniq` to reduce that number down to 967 urls. With `sort -u` we would get down to 833 instead. But both are still too many. It seems to me like opera also stores the tab's history in there.

Removing some obviously unwanted lines gives 523 lines, so ~260 urls:
```bash
 strings appstate.bin | grep -v -e 'operaui://startpage' -e 'Speed Dial' | grep -A2 reader_mode_state | uniq | grep -v 'reader_mode_state'
```

As a target number to consider:
```bash
strings appstate.bin | grep reader_mode_state | wc -l
231
```

That means - assuming this target number is a good estimate of how many tabs were open - that I have about thirty urls too many. I think I can live with that.