有时候你会遇到一种很奇怪的软件。
它表面上是个浏览器,或者至少长得像浏览器;它有地址栏,有标签页,有窗口恢复,有 pinned tab,有自己的 new tab page。但在设置里翻来覆去看,就是找不到所谓“启动后默认打开哪一页”的选项。
很多人到这里就停了。
但实际上,这类软件往往并不是“不能改”,而是没有把这个行为暴露给你改。它们通常还是要把窗口、标签页、会话恢复信息落到本地。只要本地有状态,就有被理解和被重写的可能。
本文只提供方法论,不点名具体产品,不写真实路径,只写一种通用的探索方式。懂的人看完就知道该怎么试,不懂的人至少知道这条路存在。
一、先判断:它到底有没有“恢复状态”
第一步不是乱改文件,而是先判断这个应用是不是依赖“会话恢复”。
通常可以从两个地方看:
- 偏好文件里是否出现类似下面的键:
NSWindowRestoresWorkspaceAtLaunch
NSQuitAlwaysKeepsWindows
has_submitted_on_ntp
has_submitted_url_on_ntp
selectedTabId
default_tabs_layout
- 用户目录下是否存在类似下面这些结构:
~/Library/Application Support/<browser-id>/
tabs/
tabgroups/
archived-tabs/
archived-tabgroups/
browser-data/
workspace-data/
如果有,那么基本可以确定:这个程序不是“没有启动页逻辑”,而是把启动行为折叠进了窗口恢复或新标签页状态里。
二、不要一开始就找 homepage,要找 current tab
很多人会下意识搜:
homepage
home_url
startup_url
newtab_url
但很多现代桌面应用压根不这么命名。
它们真正的做法往往是:
- 启动时恢复上次窗口
- 窗口里恢复上次 tab 列表
- 然后把
selectedTabId指到某一个 tab
也就是说,所谓“启动页”,在这类软件里可能根本不是一个独立设置,而只是:
“上次退出时,哪个 tab 是当前选中的。”
这就是思路上的关键转折。
三、优先读三类文件
我一般会按这个顺序查:
1. 偏好文件
例如:
~/Library/Preferences/<bundle-id>.plist
这里面通常能看到:
- 窗口是否恢复
- 默认标签插入方式
- 默认搜索偏好
- 是否保留窗口
- 一些 NTP 相关的布尔值
它不一定给你答案,但能帮你确认这条链是否存在。
2. 单个标签状态文件
例如:
~/Library/Application Support/<browser-id>/<profile>/tabs/<tab-id>.data
这里最重要的字段不是文件名,而是里面的内容。通常你会看到:
title
url
faviconSource
selectionDate
presentationDate
partition
permissions
只要你能在这里读到你目标网页的 URL,那就说明这个 tab 本身是可识别、可恢复、可替换的。
3. 窗口组 / tabgroup 文件
例如:
~/Library/Application Support/<browser-id>/<profile>/tabgroups/window:<window-id>.data
这里往往会有最重要的几个字段:
selectedTabId
sections.normal.tabIDs
sections.pinned.tabIDs
你真正想改的,经常就在这里。
四、先备份,再动手
这种事情一定不要直接裸改。
因为你改的不是普通配置,而是会话恢复数据。写坏了最轻是恢复失败,重一点可能导致窗口结构异常,最坏就是应用重置会话。
所以最小流程一定是:
mkdir -p <backup-dir>
cp <window-state-file> <backup-dir>/
cp <target-tab-file> <backup-dir>/
如果你想更谨慎,整个 profile 目录都可以打包一份。
五、修改顺序比修改内容更重要
这一步很多人会失败,不是因为字段没找对,而是因为软件还活着。
如果应用、helper、renderer、background process 还在运行,它很可能会在你改完后立刻把文件写回去,把你的修改覆盖掉。
所以顺序应该是:
- 备份
- 退出应用
- 确认相关进程不再存活
- 改恢复文件
- 重启应用验证
伪代码是这样:
quit "<app-name>"
ensure_processes_are_gone "<app-name>"
edit <window-state-file>
edit <target-tab-file>
open "<app-name>"
六、真正有用的改法,不是“造一个首页”,而是“篡改恢复目标”
如果你已经找到了目标 tab 文件,也知道窗口状态文件里有 selectedTabId,那么最稳的思路通常不是添加某个神秘的 homepage 键,而是做下面这几件事:
1. 把 selectedTabId 指向你想要的那个 tab
selectedTabId = <target-tab-id>
2. 必要时把窗口里的 tab 列表压缩
例如让当前窗口只剩目标页:
sections.normal.tabIDs = [<target-tab-id>]
sections.pinned.tabIDs = []
或者反过来,让目标页成为 pinned tab,而它仍然是选中的那个。
核心不是形式,而是要避免应用在恢复时先跳去别的 tab。
3. 清理 tab 文件里的异常状态
有时候某个标签虽然 URL 对,但它带着奇怪的展示属性,例如:
popupWindowFlavor
stale faviconSource
temporary interactionState
如果看起来像一个“临时弹出页”而不是正常页,应用恢复时可能会特别对待它。
这类字段不是必须改,但如果你发现它长得跟普通标签不一样,值得清掉。
七、为什么这招有效
因为不少现代桌面应用的真实启动逻辑其实很朴素:
读 profile
读最近窗口
读窗口里的 tab 列表
恢复 selected tab
渲染
它并不真的在乎“这是不是你心目中的首页”,它只在乎“恢复状态是否自洽”。
所以你只要构造一个自洽的恢复状态,它就会顺着这个状态启动。
八、什么情况下会失效
这招不是标准接口,而是利用应用内部的恢复机制,所以它天然有脆弱性。
最常见的失效原因有三个:
1. 应用更新后会话文件结构变了
字段名变了、容器结构变了、二进制格式变了,都可能导致之前的方法失效。
2. 启动时程序会主动重建窗口
有些应用不会直接使用旧窗口,而是“读取后再生成新窗口”。如果它在更高层逻辑里硬编码了新标签页,那你改底层恢复文件就只能部分生效。
3. 后台进程覆盖你的修改
你以为应用退出了,但 helper 还在。结果你一改文件,它下一秒又写回去。
所以确认进程完全结束非常重要。
九、如果你只想稳定,不想优雅
有时候不要追求“最正统的首页设置”,追求“每次打开都直接落到我的页”就够了。
那么最现实的原则是:
- 不找 homepage
- 不找 UI 开关
- 直接把恢复窗口改成目标页面
- 让目标 tab 成为唯一或第一优先级 tab
这其实比找一个根本不存在的官方选项要现实得多。
十、一个抽象化的排查模板
最后给一个伪代码版模板。
1. locate app bundle id
2. inspect:
~/Library/Preferences/<bundle-id>.plist
~/Library/Application Support/<browser-id>/<profile>/tabs/
~/Library/Application Support/<browser-id>/<profile>/tabgroups/
3. identify:
target tab file
active window file
selectedTabId
4. backup:
cp <window-file> <backup-dir>/
cp <tab-file> <backup-dir>/
5. terminate app fully
6. edit:
selectedTabId -> <target-tab-id>
sections.normal.tabIDs -> [<target-tab-id>]
sections.pinned.tabIDs -> []
tab.url -> <your-url>
remove suspicious popup-only fields if needed
7. relaunch app
8. validate:
whether app rewrites session file
whether selectedTabId persists
whether startup now lands on target page
结语
很多软件不是不能改,而是它们只暴露“安全的改法”。
当你开始去看会话恢复文件、窗口状态和标签状态时,你会发现大量所谓“不可定制”的行为,其实都只是没有放进设置面板而已。
当然,这不意味着应该随便乱改。
真正稳妥的态度仍然是:
- 先读
- 再备份
- 后修改
- 留回滚
剩下的,无非就是一点耐心,和一点对状态机的敏感。