ui-options.js 85 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541
  1. /*
  2. * Copyright 2010-2020 Gildas Lormeau
  3. * contact : gildas.lormeau <at> gmail.com
  4. *
  5. * This file is part of SingleFile.
  6. *
  7. * The code in this file is free software: you can redistribute it and/or
  8. * modify it under the terms of the GNU Affero General Public License
  9. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * The code in this file is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  15. * General Public License for more details.
  16. *
  17. * As additional permission under GNU AGPL version 3 section 7, you may
  18. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  19. * AGPL normally required by section 4, provided you include this license
  20. * notice and a URL through which recipients can access the Corresponding
  21. * Source.
  22. */
  23. /* global browser, window, document, localStorage, FileReader, location, fetch, TextDecoder, DOMParser, HTMLElement, MouseEvent */
  24. const HELP_ICON_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABIUlEQVQ4y+2TsarCMBSGvxTBRdqiUZAWOrhJB9EXcPKFfCvfQYfulUKHDqXg4CYUJSioYO4mSDX3ttzt3n87fMlHTpIjlsulxpDZbEYYhgghSNOUOI5Ny2mZYBAELBYLer0eAJ7ncTweKYri4x7LJJRS0u12n7XrukgpjSc0CpVSXK/XZ32/31FKNW85z3PW6zXT6RSAJEnIsqy5UGvNZrNhu90CcDqd+C6tT6J+v//2Th+PB2VZ1hN2Oh3G4zGTyQTbtl/YbrdjtVpxu91+Ljyfz0RRhG3bzOfzF+Y4TvNXvlwuaK2pE4tfzr/wzwsty0IIURlL0998KxRCMBqN8H2/wlzXJQxD2u12vVkeDoeUZUkURRU+GAw4HA7s9/sK+wK6CWHasQ/S/wAAAABJRU5ErkJggg==";
  25. const HELP_PAGE_PATH = "/src/ui/pages/help.html";
  26. let DEFAULT_PROFILE_NAME,
  27. DISABLED_PROFILE_NAME,
  28. CURRENT_PROFILE_NAME,
  29. BACKGROUND_SAVE_SUPPORTED,
  30. AUTO_SAVE_SUPPORTED,
  31. AUTO_OPEN_EDITOR_SUPPORTED,
  32. INFOBAR_SUPPORTED,
  33. BOOKMARKS_API_SUPPORTED,
  34. IDENTITY_API_SUPPORTED,
  35. CLIPBOARD_API_SUPPORTED,
  36. NATIVE_API_API_SUPPORTED,
  37. WEB_BLOCKING_API_SUPPORTED,
  38. SHARE_API_SUPPORTED;
  39. browser.runtime.sendMessage({ method: "config.getConstants" }).then(data => {
  40. ({
  41. DEFAULT_PROFILE_NAME,
  42. DISABLED_PROFILE_NAME,
  43. CURRENT_PROFILE_NAME,
  44. BACKGROUND_SAVE_SUPPORTED,
  45. AUTO_SAVE_SUPPORTED,
  46. AUTO_OPEN_EDITOR_SUPPORTED,
  47. INFOBAR_SUPPORTED,
  48. BOOKMARKS_API_SUPPORTED,
  49. IDENTITY_API_SUPPORTED,
  50. CLIPBOARD_API_SUPPORTED,
  51. NATIVE_API_API_SUPPORTED,
  52. WEB_BLOCKING_API_SUPPORTED,
  53. SHARE_API_SUPPORTED
  54. } = data);
  55. init();
  56. });
  57. const removeHiddenElementsLabel = document.getElementById("removeHiddenElementsLabel");
  58. const removeUnusedStylesLabel = document.getElementById("removeUnusedStylesLabel");
  59. const removeUnusedFontsLabel = document.getElementById("removeUnusedFontsLabel");
  60. const removeFramesLabel = document.getElementById("removeFramesLabel");
  61. const blockScriptsLabel = document.getElementById("blockScriptsLabel");
  62. const blockAudiosLabel = document.getElementById("blockAudiosLabel");
  63. const blockVideosLabel = document.getElementById("blockVideosLabel");
  64. const blockFontsLabel = document.getElementById("blockFontsLabel");
  65. const blockStylesheetsLabel = document.getElementById("blockStylesheetsLabel");
  66. const blockImagesLabel = document.getElementById("blockImagesLabel");
  67. const acceptHeaderDocumentLabel = document.getElementById("acceptHeaderDocumentLabel");
  68. const acceptHeaderScriptLabel = document.getElementById("acceptHeaderScriptLabel");
  69. const acceptHeaderAudioLabel = document.getElementById("acceptHeaderAudioLabel");
  70. const acceptHeaderVideoLabel = document.getElementById("acceptHeaderVideoLabel");
  71. const acceptHeaderFontLabel = document.getElementById("acceptHeaderFontLabel");
  72. const acceptHeaderStylesheetLabel = document.getElementById("acceptHeaderStylesheetLabel");
  73. const acceptHeaderImageLabel = document.getElementById("acceptHeaderImageLabel");
  74. const saveRawPageLabel = document.getElementById("saveRawPageLabel");
  75. const insertMetaCSPLabel = document.getElementById("insertMetaCSPLabel");
  76. const saveToClipboardLabel = document.getElementById("saveToClipboardLabel");
  77. const saveToFilesystemLabel = document.getElementById("saveToFilesystemLabel");
  78. const sharePageLabel = document.getElementById("sharePageLabel");
  79. const addProofLabel = document.getElementById("addProofLabel");
  80. const woleetKeyLabel = document.getElementById("woleetKeyLabel");
  81. const saveToGDriveLabel = document.getElementById("saveToGDriveLabel");
  82. const saveToDropboxLabel = document.getElementById("saveToDropboxLabel");
  83. const saveWithWebDAVLabel = document.getElementById("saveWithWebDAVLabel");
  84. const webDAVURLLabel = document.getElementById("webDAVURLLabel");
  85. const webDAVUserLabel = document.getElementById("webDAVUserLabel");
  86. const webDAVPasswordLabel = document.getElementById("webDAVPasswordLabel");
  87. const saveToGitHubLabel = document.getElementById("saveToGitHubLabel");
  88. const githubTokenLabel = document.getElementById("githubTokenLabel");
  89. const githubUserLabel = document.getElementById("githubUserLabel");
  90. const githubRepositoryLabel = document.getElementById("githubRepositoryLabel");
  91. const githubBranchLabel = document.getElementById("githubBranchLabel");
  92. const saveWithCompanionLabel = document.getElementById("saveWithCompanionLabel");
  93. const saveToS3Label = document.getElementById("saveToS3Label");
  94. const S3DomainLabel = document.getElementById("S3DomainLabel");
  95. const S3RegionLabel = document.getElementById("S3RegionLabel");
  96. const S3BucketLabel = document.getElementById("S3BucketLabel");
  97. const S3AccessKeyLabel = document.getElementById("S3AccessKeyLabel");
  98. const S3SecretKeyLabel = document.getElementById("S3SecretKeyLabel");
  99. const compressHTMLLabel = document.getElementById("compressHTMLLabel");
  100. const insertTextBodyLabel = document.getElementById("insertTextBodyLabel");
  101. const insertEmbeddedImageLabel = document.getElementById("insertEmbeddedImageLabel");
  102. const insertEmbeddedCustomImageLabel = document.getElementById("insertEmbeddedCustomImageLabel");
  103. const insertEmbeddedScreenshotImageLabel = document.getElementById("insertEmbeddedScreenshotImageLabel");
  104. const compressCSSLabel = document.getElementById("compressCSSLabel");
  105. const moveStylesInHeadLabel = document.getElementById("moveStylesInHeadLabel");
  106. const loadDeferredImagesLabel = document.getElementById("loadDeferredImagesLabel");
  107. const loadDeferredImagesMaxIdleTimeLabel = document.getElementById("loadDeferredImagesMaxIdleTimeLabel");
  108. const loadDeferredImagesKeepZoomLevelLabel = document.getElementById("loadDeferredImagesKeepZoomLevelLabel");
  109. const loadDeferredImagesDispatchScrollEventLabel = document.getElementById("loadDeferredImagesDispatchScrollEventLabel");
  110. const loadDeferredImagesBeforeFramesLabel = document.getElementById("loadDeferredImagesBeforeFramesLabel");
  111. const addMenuEntryLabel = document.getElementById("addMenuEntryLabel");
  112. const filenameTemplateLabel = document.getElementById("filenameTemplateLabel");
  113. const filenameMaxLengthLabel = document.getElementById("filenameMaxLengthLabel");
  114. const filenameMaxLengthBytesUnitLabel = document.getElementById("filenameMaxLengthBytesUnitLabel");
  115. const filenameMaxLengthCharsUnitLabel = document.getElementById("filenameMaxLengthCharsUnitLabel");
  116. const filenameReplacementCharacterLabel = document.getElementById("filenameReplacementCharacterLabel");
  117. const replaceEmojisInFilenameLabel = document.getElementById("replaceEmojisInFilenameLabel");
  118. const saveFilenameTemplateDataLabel = document.getElementById("saveFilenameTemplateDataLabel");
  119. const shadowEnabledLabel = document.getElementById("shadowEnabledLabel");
  120. const setMaxResourceSizeLabel = document.getElementById("setMaxResourceSizeLabel");
  121. const maxResourceSizeLabel = document.getElementById("maxResourceSizeLabel");
  122. const setMaxResourceDelayLabel = document.getElementById("setMaxResourceDelayLabel");
  123. const maxResourceDelayLabel = document.getElementById("maxResourceDelayLabel");
  124. const confirmFilenameLabel = document.getElementById("confirmFilenameLabel");
  125. const filenameConflictActionLabel = document.getElementById("filenameConflictActionLabel");
  126. const filenameConflictActionUniquifyLabel = document.getElementById("filenameConflictActionUniquifyLabel");
  127. const filenameConflictActionOverwriteLabel = document.getElementById("filenameConflictActionOverwriteLabel");
  128. const filenameConflictActionPromptLabel = document.getElementById("filenameConflictActionPromptLabel");
  129. const filenameConflictActionSkipLabel = document.getElementById("filenameConflictActionSkipLabel");
  130. const displayInfobarLabel = document.getElementById("displayInfobarLabel");
  131. const displayStatsLabel = document.getElementById("displayStatsLabel");
  132. const backgroundSaveLabel = document.getElementById("backgroundSaveLabel");
  133. const autoSaveDelayLabel = document.getElementById("autoSaveDelayLabel");
  134. const autoSaveLoadLabel = document.getElementById("autoSaveLoadLabel");
  135. const autoSaveUnloadLabel = document.getElementById("autoSaveUnloadLabel");
  136. const autoSaveLoadOrUnloadLabel = document.getElementById("autoSaveLoadOrUnloadLabel");
  137. const autoSaveDiscardLabel = document.getElementById("autoSaveDiscardLabel");
  138. const autoSaveRemoveLabel = document.getElementById("autoSaveRemoveLabel");
  139. const autoSaveRepeatLabel = document.getElementById("autoSaveRepeatLabel");
  140. const autoSaveRepeatDelayLabel = document.getElementById("autoSaveRepeatDelayLabel");
  141. const autoSaveExternalSaveLabel = document.getElementById("autoSaveExternalSaveLabel");
  142. const removeAlternativeFontsLabel = document.getElementById("removeAlternativeFontsLabel");
  143. const removeAlternativeImagesLabel = document.getElementById("removeAlternativeImagesLabel");
  144. const removeAlternativeMediasLabel = document.getElementById("removeAlternativeMediasLabel");
  145. const saveCreatedBookmarksLabel = document.getElementById("saveCreatedBookmarksLabel");
  146. const passReferrerOnErrorLabel = document.getElementById("passReferrerOnErrorLabel");
  147. const replaceBookmarkURLLabel = document.getElementById("replaceBookmarkURLLabel");
  148. const allowedBookmarkFoldersLabel = document.getElementById("allowedBookmarkFoldersLabel");
  149. const ignoredBookmarkFoldersLabel = document.getElementById("ignoredBookmarkFoldersLabel");
  150. const createRootDirectoryLabel = document.getElementById("createRootDirectoryLabel");
  151. const preventAppendedDataLabel = document.getElementById("preventAppendedDataLabel");
  152. const passwordLabel = document.getElementById("passwordLabel");
  153. const titleLabel = document.getElementById("titleLabel");
  154. const userInterfaceLabel = document.getElementById("userInterfaceLabel");
  155. const filenameLabel = document.getElementById("filenameLabel");
  156. const htmlContentLabel = document.getElementById("htmlContentLabel");
  157. const fileFormatLabel = document.getElementById("fileFormatLabel");
  158. const fileFormatSelectHTMLLabel = document.getElementById("fileFormatSelectHTMLLabel");
  159. const fileFormatSelectSelfExtractingUniversalLabel = document.getElementById("fileFormatSelectSelfExtractingUniversalLabel");
  160. const fileFormatSelectSelfExtractingLabel = document.getElementById("fileFormatSelectSelfExtractingLabel");
  161. const fileFormatSelectZIPLabel = document.getElementById("fileFormatSelectZIPLabel");
  162. const fileFormatSelectLabel = document.getElementById("fileFormatSelectLabel");
  163. const infobarLabel = document.getElementById("infobarLabel");
  164. const imagesLabel = document.getElementById("imagesLabel");
  165. const stylesheetsLabel = document.getElementById("stylesheetsLabel");
  166. const fontsLabel = document.getElementById("fontsLabel");
  167. const networkLabel = document.getElementById("networkLabel");
  168. const blockResourcesLabel = document.getElementById("blockResourcesLabel");
  169. const acceptHeadersLabel = document.getElementById("acceptHeadersLabel");
  170. const destinationLabel = document.getElementById("destinationLabel");
  171. const bookmarksLabel = document.getElementById("bookmarksLabel");
  172. const autoSaveLabel = document.getElementById("autoSaveLabel");
  173. const autoSettingsLabel = document.getElementById("autoSettingsLabel");
  174. const autoSettingsUrlLabel = document.getElementById("autoSettingsUrlLabel");
  175. const autoSettingsProfileLabel = document.getElementById("autoSettingsProfileLabel");
  176. const autoSettingsAutoSaveProfileLabel = document.getElementById("autoSettingsAutoSaveProfileLabel");
  177. const showAllProfilesLabel = document.getElementById("showAllProfilesLabel");
  178. const showAutoSaveProfileLabel = document.getElementById("showAutoSaveProfileLabel");
  179. const groupDuplicateImagesLabel = document.getElementById("groupDuplicateImagesLabel");
  180. const confirmInfobarLabel = document.getElementById("confirmInfobarLabel");
  181. const autoCloseLabel = document.getElementById("autoCloseLabel");
  182. const editorLabel = document.getElementById("editorLabel");
  183. const openEditorLabel = document.getElementById("openEditorLabel");
  184. const openSavedPageLabel = document.getElementById("openSavedPageLabel");
  185. const autoOpenEditorLabel = document.getElementById("autoOpenEditorLabel");
  186. const defaultEditorModeLabel = document.getElementById("defaultEditorModeLabel");
  187. const applySystemThemeLabel = document.getElementById("applySystemThemeLabel");
  188. const warnUnsavedPageLabel = document.getElementById("warnUnsavedPageLabel");
  189. const displayInfobarInEditorLabel = document.getElementById("displayInfobarInEditorLabel");
  190. const infobarTemplateLabel = document.getElementById("infobarTemplateLabel");
  191. const blockMixedContentLabel = document.getElementById("blockMixedContentLabel");
  192. const saveOriginalURLsLabel = document.getElementById("saveOriginalURLsLabel");
  193. const includeInfobarLabel = document.getElementById("includeInfobarLabel");
  194. const openInfobarLabel = document.getElementById("openInfobarLabel");
  195. const removeInfobarSavedDateLabel = document.getElementById("removeInfobarSavedDateLabel");
  196. const miscLabel = document.getElementById("miscLabel");
  197. const helpLabel = document.getElementById("helpLabel");
  198. const synchronizeLabel = document.getElementById("synchronizeLabel");
  199. const addProfileButton = document.getElementById("addProfileButton");
  200. const deleteProfileButton = document.getElementById("deleteProfileButton");
  201. const renameProfileButton = document.getElementById("renameProfileButton");
  202. const resetButton = document.getElementById("resetButton");
  203. const exportButton = document.getElementById("exportButton");
  204. const importButton = document.getElementById("importButton");
  205. const fileInput = document.getElementById("fileInput");
  206. const profileNamesInput = document.getElementById("profileNamesInput");
  207. const removeHiddenElementsInput = document.getElementById("removeHiddenElementsInput");
  208. const removeUnusedStylesInput = document.getElementById("removeUnusedStylesInput");
  209. const removeUnusedFontsInput = document.getElementById("removeUnusedFontsInput");
  210. const removeFramesInput = document.getElementById("removeFramesInput");
  211. const blockScriptsInput = document.getElementById("blockScriptsInput");
  212. const blockVideosInput = document.getElementById("blockVideosInput");
  213. const blockAudiosInput = document.getElementById("blockAudiosInput");
  214. const blockFontsInput = document.getElementById("blockFontsInput");
  215. const blockStylesheetsInput = document.getElementById("blockStylesheetsInput");
  216. const blockImagesInput = document.getElementById("blockImagesInput");
  217. const acceptHeaderDocumentInput = document.getElementById("acceptHeaderDocumentInput");
  218. const acceptHeaderScriptInput = document.getElementById("acceptHeaderScriptInput");
  219. const acceptHeaderAudioInput = document.getElementById("acceptHeaderAudioInput");
  220. const acceptHeaderVideoInput = document.getElementById("acceptHeaderVideoInput");
  221. const acceptHeaderFontInput = document.getElementById("acceptHeaderFontInput");
  222. const acceptHeaderStylesheetInput = document.getElementById("acceptHeaderStylesheetInput");
  223. const acceptHeaderImageInput = document.getElementById("acceptHeaderImageInput");
  224. const saveRawPageInput = document.getElementById("saveRawPageInput");
  225. const insertMetaCSPInput = document.getElementById("insertMetaCSPInput");
  226. const saveToClipboardInput = document.getElementById("saveToClipboardInput");
  227. const addProofInput = document.getElementById("addProofInput");
  228. const woleetKeyInput = document.getElementById("woleetKeyInput");
  229. const saveToGDriveInput = document.getElementById("saveToGDriveInput");
  230. const saveToDropboxInput = document.getElementById("saveToDropboxInput");
  231. const saveWithWebDAVInput = document.getElementById("saveWithWebDAVInput");
  232. const webDAVURLInput = document.getElementById("webDAVURLInput");
  233. const webDAVUserInput = document.getElementById("webDAVUserInput");
  234. const webDAVPasswordInput = document.getElementById("webDAVPasswordInput");
  235. const saveToGitHubInput = document.getElementById("saveToGitHubInput");
  236. const saveToS3Input = document.getElementById("saveToS3Input");
  237. const githubTokenInput = document.getElementById("githubTokenInput");
  238. const githubUserInput = document.getElementById("githubUserInput");
  239. const githubRepositoryInput = document.getElementById("githubRepositoryInput");
  240. const githubBranchInput = document.getElementById("githubBranchInput");
  241. const saveWithCompanionInput = document.getElementById("saveWithCompanionInput");
  242. const sharePageInput = document.getElementById("sharePageInput");
  243. const saveToFilesystemInput = document.getElementById("saveToFilesystemInput");
  244. const compressHTMLInput = document.getElementById("compressHTMLInput");
  245. const insertTextBodyInput = document.getElementById("insertTextBodyInput");
  246. const insertEmbeddedImageInput = document.getElementById("insertEmbeddedImageInput");
  247. const insertEmbeddedCustomImageInput = document.getElementById("insertEmbeddedCustomImageInput");
  248. const insertEmbeddedScreenshotImageInput = document.getElementById("insertEmbeddedScreenshotImageInput");
  249. const compressCSSInput = document.getElementById("compressCSSInput");
  250. const moveStylesInHeadInput = document.getElementById("moveStylesInHeadInput");
  251. const loadDeferredImagesInput = document.getElementById("loadDeferredImagesInput");
  252. const loadDeferredImagesMaxIdleTimeInput = document.getElementById("loadDeferredImagesMaxIdleTimeInput");
  253. const loadDeferredImagesKeepZoomLevelInput = document.getElementById("loadDeferredImagesKeepZoomLevelInput");
  254. const loadDeferredImagesDispatchScrollEventInput = document.getElementById("loadDeferredImagesDispatchScrollEventInput");
  255. const loadDeferredImagesBeforeFramesInput = document.getElementById("loadDeferredImagesBeforeFramesInput");
  256. const contextMenuEnabledInput = document.getElementById("contextMenuEnabledInput");
  257. const filenameTemplateInput = document.getElementById("filenameTemplateInput");
  258. const filenameMaxLengthInput = document.getElementById("filenameMaxLengthInput");
  259. const filenameMaxLengthUnitInput = document.getElementById("filenameMaxLengthUnitInput");
  260. const filenameReplacementCharacterInput = document.getElementById("filenameReplacementCharacterInput");
  261. const replaceEmojisInFilenameInput = document.getElementById("replaceEmojisInFilenameInput");
  262. const saveFilenameTemplateDataInput = document.getElementById("saveFilenameTemplateDataInput");
  263. const shadowEnabledInput = document.getElementById("shadowEnabledInput");
  264. const maxResourceSizeInput = document.getElementById("maxResourceSizeInput");
  265. const maxResourceSizeEnabledInput = document.getElementById("maxResourceSizeEnabledInput");
  266. const maxResourceDelayInput = document.getElementById("maxResourceDelayInput");
  267. const maxResourceDelayEnabledInput = document.getElementById("maxResourceDelayEnabledInput");
  268. const confirmFilenameInput = document.getElementById("confirmFilenameInput");
  269. const filenameConflictActionInput = document.getElementById("filenameConflictActionInput");
  270. const displayInfobarInput = document.getElementById("displayInfobarInput");
  271. const displayStatsInput = document.getElementById("displayStatsInput");
  272. const backgroundSaveInput = document.getElementById("backgroundSaveInput");
  273. const autoSaveDelayInput = document.getElementById("autoSaveDelayInput");
  274. const autoSaveLoadInput = document.getElementById("autoSaveLoadInput");
  275. const autoSaveUnloadInput = document.getElementById("autoSaveUnloadInput");
  276. const autoSaveDiscardInput = document.getElementById("autoSaveDiscardInput");
  277. const autoSaveRemoveInput = document.getElementById("autoSaveRemoveInput");
  278. const autoSaveLoadOrUnloadInput = document.getElementById("autoSaveLoadOrUnloadInput");
  279. const autoSaveRepeatInput = document.getElementById("autoSaveRepeatInput");
  280. const autoSaveRepeatDelayInput = document.getElementById("autoSaveRepeatDelayInput");
  281. const autoSaveExternalSaveInput = document.getElementById("autoSaveExternalSaveInput");
  282. const removeAlternativeFontsInput = document.getElementById("removeAlternativeFontsInput");
  283. const removeAlternativeImagesInput = document.getElementById("removeAlternativeImagesInput");
  284. const removeAlternativeMediasInput = document.getElementById("removeAlternativeMediasInput");
  285. const saveCreatedBookmarksInput = document.getElementById("saveCreatedBookmarksInput");
  286. const passReferrerOnErrorInput = document.getElementById("passReferrerOnErrorInput");
  287. const replaceBookmarkURLInput = document.getElementById("replaceBookmarkURLInput");
  288. const allowedBookmarkFoldersInput = document.getElementById("allowedBookmarkFoldersInput");
  289. const ignoredBookmarkFoldersInput = document.getElementById("ignoredBookmarkFoldersInput");
  290. const fileFormatSelectInput = document.getElementById("fileFormatSelectInput");
  291. const createRootDirectoryInput = document.getElementById("createRootDirectoryInput");
  292. const preventAppendedDataInput = document.getElementById("preventAppendedDataInput");
  293. const passwordInput = document.getElementById("passwordInput");
  294. const groupDuplicateImagesInput = document.getElementById("groupDuplicateImagesInput");
  295. const infobarTemplateInput = document.getElementById("infobarTemplateInput");
  296. const blockMixedContentInput = document.getElementById("blockMixedContentInput");
  297. const saveOriginalURLsInput = document.getElementById("saveOriginalURLsInput");
  298. const includeInfobarInput = document.getElementById("includeInfobarInput");
  299. const openInfobarInput = document.getElementById("openInfobarInput");
  300. const removeInfobarSavedDateInput = document.getElementById("removeInfobarSavedDateInput");
  301. const confirmInfobarInput = document.getElementById("confirmInfobarInput");
  302. const autoCloseInput = document.getElementById("autoCloseInput");
  303. const openEditorInput = document.getElementById("openEditorInput");
  304. const openSavedPageInput = document.getElementById("openSavedPageInput");
  305. const autoOpenEditorInput = document.getElementById("autoOpenEditorInput");
  306. const defaultEditorModeInput = document.getElementById("defaultEditorModeInput");
  307. const defaultEditorModeNormalLabel = document.getElementById("defaultEditorModeNormalLabel");
  308. const defaultEditorModeEditLabel = document.getElementById("defaultEditorModeEditLabel");
  309. const defaultEditorModeFormatLabel = document.getElementById("defaultEditorModeFormatLabel");
  310. const defaultEditorModeCutLabel = document.getElementById("defaultEditorModeCutLabel");
  311. const defaultEditorModeCutExternalLabel = document.getElementById("defaultEditorModeCutExternalLabel");
  312. const applySystemThemeInput = document.getElementById("applySystemThemeInput");
  313. const warnUnsavedPageInput = document.getElementById("warnUnsavedPageInput");
  314. const displayInfobarInEditorInput = document.getElementById("displayInfobarInEditorInput");
  315. const expandAllButton = document.getElementById("expandAllButton");
  316. const rulesDeleteAllButton = document.getElementById("rulesDeleteAllButton");
  317. const ruleUrlInput = document.getElementById("ruleUrlInput");
  318. const ruleProfileInput = document.getElementById("ruleProfileInput");
  319. const ruleAutoSaveProfileInput = document.getElementById("ruleAutoSaveProfileInput");
  320. const ruleEditProfileInput = document.getElementById("ruleEditProfileInput");
  321. const ruleEditAutoSaveProfileInput = document.getElementById("ruleEditAutoSaveProfileInput");
  322. const ruleAddButton = document.getElementById("ruleAddButton");
  323. const rulesElement = document.querySelector(".rules-table");
  324. const rulesContainerElement = document.querySelector(".rules-table-container");
  325. const ruleEditUrlInput = document.getElementById("ruleEditUrlInput");
  326. const ruleEditButton = document.getElementById("ruleEditButton");
  327. const createURLElement = rulesElement.querySelector(".rule-create");
  328. const showAllProfilesInput = document.getElementById("showAllProfilesInput");
  329. const showAutoSaveProfileInput = document.getElementById("showAutoSaveProfileInput");
  330. const synchronizeInput = document.getElementById("synchronizeInput");
  331. const resetAllButton = document.getElementById("resetAllButton");
  332. const resetCurrentButton = document.getElementById("resetCurrentButton");
  333. const resetCancelButton = document.getElementById("resetCancelButton");
  334. const confirmButton = document.getElementById("confirmButton");
  335. const cancelButton = document.getElementById("cancelButton");
  336. const promptInput = document.getElementById("promptInput");
  337. const promptCancelButton = document.getElementById("promptCancelButton");
  338. const promptConfirmButton = document.getElementById("promptConfirmButton");
  339. const manifest = browser.runtime.getManifest();
  340. const requestPermissionIdentity = manifest.optional_permissions && manifest.optional_permissions.includes("identity");
  341. const saveToRestFormApiLabel = document.getElementById("saveToRestFormApiLabel");
  342. const saveToRestFormApiUrlLabel = document.getElementById("saveToRestFormApiUrlLabel");
  343. const saveToRestFormApiFileFieldNameLabel = document.getElementById("saveToRestFormApiFileFieldNameLabel");
  344. const saveToRestFormApiUrlFieldNameLabel = document.getElementById("saveToRestFormApiUrlFieldNameLabel");
  345. const saveToRestFormApiTokenLabel = document.getElementById("saveToRestFormApiTokenLabel");
  346. const saveToRestFormApiInput = document.getElementById("saveToRestFormApiInput");
  347. const saveToRestFormApiUrlInput = document.getElementById("saveToRestFormApiUrlInput");
  348. const saveToRestFormApiFileFieldNameInput = document.getElementById("saveToRestFormApiFileFieldNameInput");
  349. const saveToRestFormApiUrlFieldNameInput = document.getElementById("saveToRestFormApiUrlFieldNameInput");
  350. const saveToRestFormApiTokenInput = document.getElementById("saveToRestFormApiTokenInput");
  351. const S3DomainInput = document.getElementById("S3DomainInput");
  352. const S3RegionInput = document.getElementById("S3RegionInput");
  353. const S3BucketInput = document.getElementById("S3BucketInput");
  354. const S3AccessKeyInput = document.getElementById("S3AccessKeyInput");
  355. const S3SecretKeyInput = document.getElementById("S3SecretKeyInput");
  356. let sidePanelDisplay;
  357. if (location.href.endsWith("#side-panel")) {
  358. sidePanelDisplay = true;
  359. document.querySelector(".options-title").remove();
  360. document.documentElement.classList.add("side-panel");
  361. }
  362. browser.runtime.onMessage.addListener(message => {
  363. if (message.method == "options.refresh" || (message.method == "options.refreshPanel" && sidePanelDisplay)) {
  364. refresh(message.profileName);
  365. }
  366. });
  367. let pendingSave = Promise.resolve();
  368. let autoSaveProfileChanged;
  369. ruleProfileInput.onchange = () => {
  370. if (!autoSaveProfileChanged && ruleProfileInput.value != CURRENT_PROFILE_NAME) {
  371. ruleAutoSaveProfileInput.value = ruleProfileInput.value;
  372. }
  373. };
  374. ruleAutoSaveProfileInput.onchange = () => {
  375. autoSaveProfileChanged = true;
  376. };
  377. rulesDeleteAllButton.addEventListener("click", async event => {
  378. if (await confirm(browser.i18n.getMessage("optionsDeleteDisplayedRulesConfirm"), event.clientY - 100)) {
  379. await browser.runtime.sendMessage({ method: "config.deleteRules", profileName: !showAllProfilesInput.checked && profileNamesInput.value });
  380. await refresh();
  381. await refreshExternalComponents();
  382. }
  383. }, false);
  384. createURLElement.onsubmit = async event => {
  385. event.preventDefault();
  386. try {
  387. await browser.runtime.sendMessage({ method: "config.addRule", url: ruleUrlInput.value, profileName: ruleProfileInput.value, autoSaveProfileName: ruleAutoSaveProfileInput.value });
  388. } catch (error) {
  389. // ignored
  390. }
  391. ruleUrlInput.value = "";
  392. ruleProfileInput.value = ruleAutoSaveProfileInput.value = DEFAULT_PROFILE_NAME;
  393. autoSaveProfileChanged = false;
  394. await refresh();
  395. await refreshExternalComponents();
  396. ruleUrlInput.focus();
  397. };
  398. ruleUrlInput.onclick = ruleUrlInput.onkeyup = ruleUrlInput.onchange = async () => {
  399. ruleAddButton.disabled = !ruleUrlInput.value;
  400. const rules = await browser.runtime.sendMessage({ method: "config.getRules" });
  401. if (rules.find(rule => rule.url == ruleUrlInput.value)) {
  402. ruleAddButton.disabled = true;
  403. }
  404. };
  405. ruleEditUrlInput.onclick = ruleEditUrlInput.onkeyup = ruleEditUrlInput.onchange = async () => {
  406. ruleEditButton.disabled = !ruleEditUrlInput.value;
  407. const rules = await browser.runtime.sendMessage({ method: "config.getRules" });
  408. if (rules.find(rule => rule.url == ruleEditUrlInput.value)) {
  409. ruleEditButton.disabled = true;
  410. }
  411. };
  412. if (getLocalStorageItem("optionShowAutoSaveProfile")) {
  413. showAutoSaveProfileInput.checked = true;
  414. rulesContainerElement.classList.remove("compact");
  415. }
  416. showAutoSaveProfileInput.addEventListener("click", () => {
  417. if (showAutoSaveProfileInput.checked) {
  418. setLocalStorageItem("optionShowAutoSaveProfile", 1);
  419. rulesContainerElement.classList.remove("compact");
  420. } else {
  421. removeLocalStorageItem("optionShowAutoSaveProfile");
  422. rulesContainerElement.classList.add("compact");
  423. }
  424. }, false);
  425. if (getLocalStorageItem("optionShowAllProfiles")) {
  426. showAllProfilesInput.checked = true;
  427. }
  428. showAllProfilesInput.addEventListener("click", () => {
  429. if (showAllProfilesInput.checked) {
  430. setLocalStorageItem("optionShowAllProfiles", 1);
  431. } else {
  432. removeLocalStorageItem("optionShowAllProfiles");
  433. }
  434. }, false);
  435. addProfileButton.addEventListener("click", async event => {
  436. const profileName = await prompt(browser.i18n.getMessage("profileAddPrompt"), event.clientY + 50);
  437. if (profileName) {
  438. try {
  439. await browser.runtime.sendMessage({ method: "config.createProfile", profileName, fromProfileName: profileNamesInput.value });
  440. } catch (error) {
  441. // ignored
  442. }
  443. if (sidePanelDisplay) {
  444. await refresh();
  445. } else {
  446. await refresh(profileName);
  447. }
  448. await refreshExternalComponents();
  449. }
  450. }, false);
  451. deleteProfileButton.addEventListener("click", async event => {
  452. if (await confirm(browser.i18n.getMessage("profileDeleteConfirm"), event.clientY + 50)) {
  453. try {
  454. await browser.runtime.sendMessage({ method: "config.deleteProfile", profileName: profileNamesInput.value });
  455. } catch (error) {
  456. // ignored
  457. }
  458. profileNamesInput.value = null;
  459. await refresh();
  460. await refreshExternalComponents();
  461. }
  462. }, false);
  463. renameProfileButton.addEventListener("click", async event => {
  464. const profileName = await prompt(browser.i18n.getMessage("profileRenamePrompt"), event.clientY + 50, profileNamesInput.value);
  465. if (profileName) {
  466. try {
  467. await browser.runtime.sendMessage({ method: "config.renameProfile", profileName: profileNamesInput.value, newProfileName: profileName });
  468. } catch (error) {
  469. // ignored
  470. }
  471. await refresh(profileName);
  472. await refreshExternalComponents();
  473. }
  474. }, false);
  475. resetButton.addEventListener("click", async event => {
  476. const choice = await reset(event.clientY - 250);
  477. if (choice) {
  478. if (choice == "all") {
  479. await browser.runtime.sendMessage({ method: "config.resetProfiles" });
  480. await refresh(DEFAULT_PROFILE_NAME);
  481. await refreshExternalComponents();
  482. }
  483. if (choice == "current") {
  484. await browser.runtime.sendMessage({ method: "config.resetProfile", profileName: profileNamesInput.value });
  485. await refresh();
  486. await refreshExternalComponents();
  487. }
  488. await update();
  489. }
  490. }, false);
  491. exportButton.addEventListener("click", async () => {
  492. const response = await browser.runtime.sendMessage({ method: "config.exportConfig" });
  493. if (response.filename && response.textContent) {
  494. const link = document.createElement("a");
  495. link.download = response.filename;
  496. link.href = "data:application/octet-stream," + response.textContent;
  497. link.target = "_blank";
  498. link.dispatchEvent(new MouseEvent("click"));
  499. }
  500. }, false);
  501. importButton.addEventListener("click", () => {
  502. fileInput.onchange = async () => {
  503. if (fileInput.files.length) {
  504. const reader = new FileReader();
  505. reader.readAsText(fileInput.files[0]);
  506. const serializedConfig = await new Promise((resolve, reject) => {
  507. reader.addEventListener("load", () => resolve(reader.result), false);
  508. reader.addEventListener("error", reject, false);
  509. });
  510. const config = JSON.parse(serializedConfig);
  511. Object.keys(config.profiles).forEach(profileName => {
  512. const profile = config.profiles[profileName];
  513. if (profile.saveToGDrive && !profile.forceWebAuthFlow) {
  514. profile.saveToGDrive = false;
  515. }
  516. profile.saveToClipboard = false;
  517. profile.saveWithCompanion = false;
  518. profile.saveCreatedBookmarks = false;
  519. profile.passReferrerOnError = false;
  520. });
  521. await browser.runtime.sendMessage({ method: "config.importConfig", config });
  522. await refresh(DEFAULT_PROFILE_NAME);
  523. await refreshExternalComponents();
  524. fileInput.value = "";
  525. }
  526. };
  527. fileInput.click();
  528. }, false);
  529. autoSaveUnloadInput.addEventListener("click", async () => {
  530. if (!autoSaveLoadInput.checked && !autoSaveUnloadInput.checked) {
  531. autoSaveLoadOrUnloadInput.checked = true;
  532. }
  533. }, false);
  534. autoSaveLoadInput.addEventListener("click", async () => {
  535. if (!autoSaveLoadInput.checked && !autoSaveUnloadInput.checked) {
  536. autoSaveLoadOrUnloadInput.checked = true;
  537. }
  538. }, false);
  539. autoSaveLoadOrUnloadInput.addEventListener("click", async () => {
  540. if (autoSaveLoadOrUnloadInput.checked) {
  541. autoSaveUnloadInput.checked = autoSaveLoadInput.checked = false;
  542. } else {
  543. autoSaveUnloadInput.checked = false;
  544. }
  545. }, false);
  546. expandAllButton.addEventListener("click", () => {
  547. if (expandAllButton.className) {
  548. expandAllButton.className = "";
  549. } else {
  550. expandAllButton.className = "opened";
  551. }
  552. document.querySelectorAll("details").forEach(detailElement => detailElement.open = Boolean(expandAllButton.className));
  553. }, false);
  554. saveToFilesystemInput.addEventListener("click", () => disableDestinationPermissions(["clipboardWrite", "nativeMessaging"]), false);
  555. saveToClipboardInput.addEventListener("click", () => disableDestinationPermissions(["nativeMessaging"]), false);
  556. saveWithCompanionInput.addEventListener("click", () => disableDestinationPermissions(["clipboardWrite"]), false);
  557. saveToGDriveInput.addEventListener("click", () => disableDestinationPermissions(["clipboardWrite", "nativeMessaging"], false), false);
  558. saveToDropboxInput.addEventListener("click", () => disableDestinationPermissions(["clipboardWrite", "nativeMessaging"], true, false), false);
  559. saveWithWebDAVInput.addEventListener("click", () => disableDestinationPermissions(["clipboardWrite", "nativeMessaging"]), false);
  560. saveToRestFormApiInput.addEventListener("click", () => disableDestinationPermissions(["clipboardWrite", "nativeMessaging"]), false);
  561. sharePageInput.addEventListener("click", () => disableDestinationPermissions(["clipboardWrite", "nativeMessaging"]), false);
  562. saveCreatedBookmarksInput.addEventListener("click", saveCreatedBookmarks, false);
  563. passReferrerOnErrorInput.addEventListener("click", passReferrerOnError, false);
  564. autoSaveExternalSaveInput.addEventListener("click", () => enableExternalSave(autoSaveExternalSaveInput), false);
  565. saveWithCompanionInput.addEventListener("click", () => enableExternalSave(saveWithCompanionInput), false);
  566. saveToClipboardInput.addEventListener("click", onClickSaveToClipboard, false);
  567. saveToGDriveInput.addEventListener("click", onClickSaveToGDrive, false);
  568. addProofInput.addEventListener("click", async event => {
  569. if (addProofInput.checked) {
  570. addProofInput.checked = false;
  571. if (await confirm(browser.i18n.getMessage("optionsAddProofConfirm"), event.clientY - 100)) {
  572. addProofInput.checked = true;
  573. woleetKeyInput.disabled = false;
  574. }
  575. await update();
  576. }
  577. });
  578. browser.runtime.sendMessage({ method: "config.isSync" }).then(data => synchronizeInput.checked = data.sync);
  579. synchronizeInput.addEventListener("click", async () => {
  580. if (synchronizeInput.checked) {
  581. await browser.runtime.sendMessage({ method: "config.enableSync" });
  582. await refresh(DEFAULT_PROFILE_NAME);
  583. } else {
  584. await browser.runtime.sendMessage({ method: "config.disableSync" });
  585. await refresh();
  586. }
  587. }, false);
  588. insertEmbeddedImageInput.addEventListener("click", () => {
  589. if (insertEmbeddedImageInput.checked) {
  590. insertEmbeddedScreenshotImageInput.checked = true;
  591. } else {
  592. insertEmbeddedScreenshotImageInput.checked = false;
  593. insertEmbeddedCustomImageInput.checked = false;
  594. }
  595. }, false);
  596. fileFormatSelectInput.addEventListener("change", () => {
  597. if (fileFormatSelectInput.value == "html") {
  598. insertEmbeddedScreenshotImageInput.checked = false;
  599. insertEmbeddedCustomImageInput.checked = false;
  600. }
  601. }, false);
  602. document.body.onchange = async event => {
  603. let target = event.target;
  604. if (target != ruleUrlInput &&
  605. target != ruleProfileInput &&
  606. target != ruleAutoSaveProfileInput &&
  607. target != ruleEditUrlInput &&
  608. target != ruleEditProfileInput &&
  609. target != ruleEditAutoSaveProfileInput &&
  610. target != showAutoSaveProfileInput &&
  611. target != saveCreatedBookmarksInput &&
  612. target != passReferrerOnErrorInput) {
  613. if (target != profileNamesInput && target != showAllProfilesInput) {
  614. await update();
  615. }
  616. if (target == profileNamesInput) {
  617. await refresh(profileNamesInput.value);
  618. if (sidePanelDisplay) {
  619. const tabsData = await browser.runtime.sendMessage({ method: "tabsData.get" });
  620. tabsData.profileName = profileNamesInput.value;
  621. await browser.runtime.sendMessage({ method: "tabsData.set", tabsData: tabsData });
  622. await browser.runtime.sendMessage({ method: "ui.refreshMenu" });
  623. }
  624. } else {
  625. if (target == contextMenuEnabledInput) {
  626. await browser.runtime.sendMessage({ method: "ui.refreshMenu" });
  627. }
  628. if (target == openEditorInput) {
  629. await browser.runtime.sendMessage({ method: "ui.refreshMenu" });
  630. }
  631. await refresh();
  632. }
  633. }
  634. };
  635. addProfileButton.title = browser.i18n.getMessage("profileAddButtonTooltip");
  636. deleteProfileButton.title = browser.i18n.getMessage("profileDeleteButtonTooltip");
  637. renameProfileButton.title = browser.i18n.getMessage("profileRenameButtonTooltip");
  638. removeHiddenElementsLabel.textContent = browser.i18n.getMessage("optionRemoveHiddenElements");
  639. removeUnusedStylesLabel.textContent = browser.i18n.getMessage("optionRemoveUnusedStyles");
  640. removeUnusedFontsLabel.textContent = browser.i18n.getMessage("optionRemoveUnusedFonts");
  641. removeFramesLabel.textContent = browser.i18n.getMessage("optionRemoveFrames");
  642. blockScriptsLabel.textContent = browser.i18n.getMessage("optionResourceScript");
  643. blockAudiosLabel.textContent = browser.i18n.getMessage("optionResourceAudio");
  644. blockVideosLabel.textContent = browser.i18n.getMessage("optionResourceVideo");
  645. blockFontsLabel.textContent = browser.i18n.getMessage("optionResourceFont");
  646. blockStylesheetsLabel.textContent = browser.i18n.getMessage("optionResourceStylesheet");
  647. blockImagesLabel.textContent = browser.i18n.getMessage("optionResourceImage");
  648. acceptHeaderDocumentLabel.textContent = browser.i18n.getMessage("optionResourceDocument");
  649. acceptHeaderScriptLabel.textContent = browser.i18n.getMessage("optionResourceScript");
  650. acceptHeaderAudioLabel.textContent = browser.i18n.getMessage("optionResourceAudio");
  651. acceptHeaderVideoLabel.textContent = browser.i18n.getMessage("optionResourceVideo");
  652. acceptHeaderFontLabel.textContent = browser.i18n.getMessage("optionResourceFont");
  653. acceptHeaderStylesheetLabel.textContent = browser.i18n.getMessage("optionResourceStylesheet");
  654. acceptHeaderImageLabel.textContent = browser.i18n.getMessage("optionResourceImage");
  655. saveRawPageLabel.textContent = browser.i18n.getMessage("optionSaveRawPage");
  656. insertMetaCSPLabel.textContent = browser.i18n.getMessage("optionInsertMetaCSP");
  657. saveToClipboardLabel.textContent = browser.i18n.getMessage("optionSaveToClipboard");
  658. saveToFilesystemLabel.textContent = browser.i18n.getMessage("optionSaveToFilesystem");
  659. sharePageLabel.textContent = browser.i18n.getMessage("optionSharePage");
  660. addProofLabel.textContent = browser.i18n.getMessage("optionAddProof");
  661. woleetKeyLabel.textContent = browser.i18n.getMessage("optionWoleetKey");
  662. saveToGDriveLabel.textContent = browser.i18n.getMessage("optionSaveToGDrive");
  663. saveToDropboxLabel.textContent = browser.i18n.getMessage("optionSaveToDropbox");
  664. saveWithWebDAVLabel.textContent = browser.i18n.getMessage("optionSaveWithWebDAV");
  665. webDAVURLLabel.textContent = browser.i18n.getMessage("optionWebDAVURL");
  666. webDAVUserLabel.textContent = browser.i18n.getMessage("optionWebDAVUser");
  667. webDAVPasswordLabel.textContent = browser.i18n.getMessage("optionWebDAVPassword");
  668. saveToGitHubLabel.textContent = browser.i18n.getMessage("optionSaveToGitHub");
  669. githubTokenLabel.textContent = browser.i18n.getMessage("optionGitHubToken");
  670. githubUserLabel.textContent = browser.i18n.getMessage("optionGitHubUser");
  671. githubRepositoryLabel.textContent = browser.i18n.getMessage("optionGitHubRepository");
  672. githubBranchLabel.textContent = browser.i18n.getMessage("optionGitHubBranch");
  673. saveToS3Label.textContent = browser.i18n.getMessage("optionSaveToS3");
  674. S3DomainLabel.textContent = browser.i18n.getMessage("optionS3Domain");
  675. S3RegionLabel.textContent = browser.i18n.getMessage("optionS3Region");
  676. S3BucketLabel.textContent = browser.i18n.getMessage("optionS3Bucket");
  677. S3AccessKeyLabel.textContent = browser.i18n.getMessage("optionS3AccessKey");
  678. S3SecretKeyLabel.textContent = browser.i18n.getMessage("optionS3SecretKey");
  679. saveWithCompanionLabel.textContent = browser.i18n.getMessage("optionSaveWithCompanion");
  680. compressHTMLLabel.textContent = browser.i18n.getMessage("optionCompressHTML");
  681. insertTextBodyLabel.textContent = browser.i18n.getMessage("optionInsertTextBody");
  682. insertEmbeddedImageLabel.textContent = browser.i18n.getMessage("optionInsertEmbeddedImage");
  683. insertEmbeddedCustomImageLabel.textContent = browser.i18n.getMessage("optionInsertEmbeddedCustomImage");
  684. insertEmbeddedScreenshotImageLabel.textContent = browser.i18n.getMessage("optionInsertEmbeddedScreenshotImage");
  685. compressCSSLabel.textContent = browser.i18n.getMessage("optionCompressCSS");
  686. moveStylesInHeadLabel.textContent = browser.i18n.getMessage("optionMoveStylesInHead");
  687. loadDeferredImagesLabel.textContent = browser.i18n.getMessage("optionLoadDeferredImages");
  688. loadDeferredImagesMaxIdleTimeLabel.textContent = browser.i18n.getMessage("optionLoadDeferredImagesMaxIdleTime");
  689. loadDeferredImagesKeepZoomLevelLabel.textContent = browser.i18n.getMessage("optionLoadDeferredImagesKeepZoomLevel");
  690. loadDeferredImagesDispatchScrollEventLabel.textContent = browser.i18n.getMessage("optionLoadDeferredImagesDispatchScrollEvent");
  691. loadDeferredImagesBeforeFramesLabel.textContent = browser.i18n.getMessage("optionLoadDeferredImagesBeforeFrames");
  692. addMenuEntryLabel.textContent = browser.i18n.getMessage("optionAddMenuEntry");
  693. filenameTemplateLabel.textContent = browser.i18n.getMessage("optionFilenameTemplate");
  694. filenameMaxLengthLabel.textContent = browser.i18n.getMessage("optionFilenameMaxLength");
  695. filenameMaxLengthBytesUnitLabel.textContent = browser.i18n.getMessage("optionFilenameMaxLengthBytesUnit");
  696. filenameMaxLengthCharsUnitLabel.textContent = browser.i18n.getMessage("optionFilenameMaxLengthCharsUnit");
  697. filenameReplacementCharacterLabel.textContent = browser.i18n.getMessage("optionFilenameReplacementCharacter");
  698. replaceEmojisInFilenameLabel.textContent = browser.i18n.getMessage("optionReplaceEmojisInFilename");
  699. saveFilenameTemplateDataLabel.textContent = browser.i18n.getMessage("optionSaveFilenameTemplateData");
  700. shadowEnabledLabel.textContent = browser.i18n.getMessage("optionDisplayShadow");
  701. setMaxResourceSizeLabel.textContent = browser.i18n.getMessage("optionSetMaxResourceSize");
  702. maxResourceSizeLabel.textContent = browser.i18n.getMessage("optionMaxResourceSize");
  703. setMaxResourceDelayLabel.textContent = browser.i18n.getMessage("optionSetMaxResourceDelay");
  704. maxResourceDelayLabel.textContent = browser.i18n.getMessage("optionMaxResourceDelay");
  705. confirmFilenameLabel.textContent = browser.i18n.getMessage("optionConfirmFilename");
  706. filenameConflictActionLabel.textContent = browser.i18n.getMessage("optionFilenameConflictAction");
  707. filenameConflictActionUniquifyLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionUniquify");
  708. filenameConflictActionOverwriteLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionOverwrite");
  709. filenameConflictActionPromptLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionPrompt");
  710. filenameConflictActionSkipLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionSkip");
  711. displayInfobarLabel.textContent = browser.i18n.getMessage("optionDisplayInfobar");
  712. displayStatsLabel.textContent = browser.i18n.getMessage("optionDisplayStats");
  713. backgroundSaveLabel.textContent = browser.i18n.getMessage("optionBackgroundSave");
  714. autoSaveDelayLabel.textContent = browser.i18n.getMessage("optionAutoSaveDelay");
  715. autoSaveLoadLabel.textContent = browser.i18n.getMessage("optionAutoSaveLoad");
  716. autoSaveUnloadLabel.textContent = browser.i18n.getMessage("optionAutoSaveUnload");
  717. autoSaveLoadOrUnloadLabel.textContent = browser.i18n.getMessage("optionAutoSaveLoadOrUnload");
  718. autoSaveDiscardLabel.textContent = browser.i18n.getMessage("optionAutoSaveDiscard");
  719. autoSaveRemoveLabel.textContent = browser.i18n.getMessage("optionAutoSaveRemove");
  720. autoSaveRepeatLabel.textContent = browser.i18n.getMessage("optionAutoSaveRepeat");
  721. autoSaveRepeatDelayLabel.textContent = browser.i18n.getMessage("optionAutoSaveRepeatDelay");
  722. autoSaveExternalSaveLabel.textContent = browser.i18n.getMessage("optionAutoSaveExternalSave");
  723. removeAlternativeFontsLabel.textContent = browser.i18n.getMessage("optionRemoveAlternativeFonts");
  724. removeAlternativeImagesLabel.textContent = browser.i18n.getMessage("optionRemoveAlternativeImages");
  725. removeAlternativeMediasLabel.textContent = browser.i18n.getMessage("optionRemoveAlternativeMedias");
  726. saveCreatedBookmarksLabel.textContent = browser.i18n.getMessage("optionSaveCreatedBookmarks");
  727. passReferrerOnErrorLabel.textContent = browser.i18n.getMessage("optionPassReferrerOnError");
  728. replaceBookmarkURLLabel.textContent = browser.i18n.getMessage("optionReplaceBookmarkURL");
  729. allowedBookmarkFoldersLabel.textContent = browser.i18n.getMessage("optionAllowedBookmarkFolders");
  730. ignoredBookmarkFoldersLabel.textContent = browser.i18n.getMessage("optionIgnoredBookmarkFolders");
  731. createRootDirectoryLabel.textContent = browser.i18n.getMessage("optionCreateRootDirectory");
  732. preventAppendedDataLabel.textContent = browser.i18n.getMessage("optionPreventAppendedData");
  733. passwordLabel.textContent = browser.i18n.getMessage("optionPassword");
  734. groupDuplicateImagesLabel.textContent = browser.i18n.getMessage("optionGroupDuplicateImages");
  735. titleLabel.textContent = browser.i18n.getMessage("optionsTitle");
  736. userInterfaceLabel.textContent = browser.i18n.getMessage("optionsUserInterfaceSubTitle");
  737. filenameLabel.textContent = browser.i18n.getMessage("optionsFileNameSubTitle");
  738. htmlContentLabel.textContent = browser.i18n.getMessage("optionsHTMLContentSubTitle");
  739. fileFormatLabel.textContent = browser.i18n.getMessage("optionsFileFormatSubTitle");
  740. fileFormatSelectHTMLLabel.textContent = browser.i18n.getMessage("optionFileFormatSelectHTML");
  741. fileFormatSelectSelfExtractingUniversalLabel.textContent = browser.i18n.getMessage("optionFileFormatSelectSelfExtractingUniversal");
  742. fileFormatSelectSelfExtractingLabel.textContent = browser.i18n.getMessage("optionFileFormatSelectSelfExtracting");
  743. fileFormatSelectZIPLabel.textContent = browser.i18n.getMessage("optionFileFormatSelectZIP");
  744. fileFormatSelectLabel.textContent = browser.i18n.getMessage("optionFileFormat");
  745. infobarLabel.textContent = browser.i18n.getMessage("optionsInfobarSubTitle");
  746. imagesLabel.textContent = browser.i18n.getMessage("optionsImagesSubTitle");
  747. stylesheetsLabel.textContent = browser.i18n.getMessage("optionsStylesheetsSubTitle");
  748. fontsLabel.textContent = browser.i18n.getMessage("optionsFontsSubTitle");
  749. networkLabel.textContent = browser.i18n.getMessage("optionsNetworkSubTitle");
  750. blockResourcesLabel.textContent = browser.i18n.getMessage("optionsBlockedResources");
  751. acceptHeadersLabel.textContent = browser.i18n.getMessage("optionsAcceptHeaders");
  752. destinationLabel.textContent = browser.i18n.getMessage("optionsDestinationSubTitle");
  753. bookmarksLabel.textContent = browser.i18n.getMessage("optionsBookmarkSubTitle");
  754. autoSaveLabel.textContent = browser.i18n.getMessage("optionsAutoSaveSubTitle");
  755. miscLabel.textContent = browser.i18n.getMessage("optionsMiscSubTitle");
  756. helpLabel.textContent = browser.i18n.getMessage("optionsHelpLink");
  757. infobarTemplateLabel.textContent = browser.i18n.getMessage("optionInfobarTemplate");
  758. blockMixedContentLabel.textContent = browser.i18n.getMessage("optionBlockMixedContent");
  759. saveOriginalURLsLabel.textContent = browser.i18n.getMessage("optionSaveOriginalURLs");
  760. includeInfobarLabel.textContent = browser.i18n.getMessage("optionIncludeInfobar");
  761. openInfobarLabel.textContent = browser.i18n.getMessage("optionOpenInfobar");
  762. removeInfobarSavedDateLabel.textContent = browser.i18n.getMessage("optionRemoveInfobarSavedDate");
  763. confirmInfobarLabel.textContent = browser.i18n.getMessage("optionConfirmInfobar");
  764. autoCloseLabel.textContent = browser.i18n.getMessage("optionAutoClose");
  765. editorLabel.textContent = browser.i18n.getMessage("optionsEditorSubTitle");
  766. openEditorLabel.textContent = browser.i18n.getMessage("optionOpenEditor");
  767. openSavedPageLabel.textContent = browser.i18n.getMessage("optionOpenSavedPage");
  768. autoOpenEditorLabel.textContent = browser.i18n.getMessage("optionAutoOpenEditor");
  769. defaultEditorModeLabel.textContent = browser.i18n.getMessage("optionDefaultEditorMode");
  770. defaultEditorModeNormalLabel.textContent = browser.i18n.getMessage("optionDefaultEditorModeNormal");
  771. defaultEditorModeEditLabel.textContent = browser.i18n.getMessage("optionDefaultEditorModeEdit");
  772. defaultEditorModeFormatLabel.textContent = browser.i18n.getMessage("optionDefaultEditorModeFormat");
  773. defaultEditorModeCutLabel.textContent = browser.i18n.getMessage("optionDefaultEditorModeCut");
  774. defaultEditorModeCutExternalLabel.textContent = browser.i18n.getMessage("optionDefaultEditorModeCutExternal");
  775. applySystemThemeLabel.textContent = browser.i18n.getMessage("optionApplySystemTheme");
  776. warnUnsavedPageLabel.textContent = browser.i18n.getMessage("optionWarnUnsavedPage");
  777. displayInfobarInEditorLabel.textContent = browser.i18n.getMessage("optiondisplayInfobarInEditor");
  778. resetButton.textContent = browser.i18n.getMessage("optionsResetButton");
  779. exportButton.textContent = browser.i18n.getMessage("optionsExportButton");
  780. importButton.textContent = browser.i18n.getMessage("optionsImportButton");
  781. resetButton.title = browser.i18n.getMessage("optionsResetTooltip");
  782. autoSettingsLabel.textContent = browser.i18n.getMessage("optionsAutoSettingsSubTitle");
  783. autoSettingsUrlLabel.textContent = browser.i18n.getMessage("optionsAutoSettingsUrl");
  784. autoSettingsProfileLabel.textContent = browser.i18n.getMessage("optionsAutoSettingsProfile");
  785. autoSettingsAutoSaveProfileLabel.textContent = browser.i18n.getMessage("optionsAutoSettingsAutoSaveProfile");
  786. ruleAddButton.title = browser.i18n.getMessage("optionsAddRuleTooltip");
  787. ruleEditButton.title = browser.i18n.getMessage("optionsValidateChangesTooltip");
  788. rulesDeleteAllButton.title = browser.i18n.getMessage("optionsDeleteRulesTooltip");
  789. showAllProfilesLabel.textContent = browser.i18n.getMessage("optionsAutoSettingsShowAllProfiles");
  790. showAutoSaveProfileLabel.textContent = browser.i18n.getMessage("optionsAutoSettingsShowAutoSaveProfile");
  791. ruleUrlInput.placeholder = ruleEditUrlInput.placeholder = browser.i18n.getMessage("optionsAutoSettingsUrlPlaceholder");
  792. synchronizeLabel.textContent = browser.i18n.getMessage("optionSynchronize");
  793. resetAllButton.textContent = browser.i18n.getMessage("optionsResetAllButton");
  794. resetCurrentButton.textContent = browser.i18n.getMessage("optionsResetCurrentButton");
  795. resetCancelButton.textContent = promptCancelButton.textContent = cancelButton.textContent = browser.i18n.getMessage("optionsCancelButton");
  796. confirmButton.textContent = promptConfirmButton.textContent = browser.i18n.getMessage("optionsOKButton");
  797. document.getElementById("resetConfirmLabel").textContent = browser.i18n.getMessage("optionsResetConfirm");
  798. saveToRestFormApiLabel.textContent = browser.i18n.getMessage("optionSaveToRestFormApi");
  799. saveToRestFormApiUrlLabel.textContent = browser.i18n.getMessage("optionRestFormApiUrl");
  800. saveToRestFormApiFileFieldNameLabel.textContent = browser.i18n.getMessage("optionRestFormApiFileFieldName");
  801. saveToRestFormApiUrlFieldNameLabel.textContent = browser.i18n.getMessage("optionRestFormApiUrlFieldName");
  802. saveToRestFormApiTokenLabel.textContent = browser.i18n.getMessage("optionRestFormApiToken");
  803. if (location.href.endsWith("#")) {
  804. document.querySelector(".new-window-link").remove();
  805. document.documentElement.classList.add("maximized");
  806. }
  807. let tabsData;
  808. browser.runtime.sendMessage({ method: "tabsData.get" }).then(allTabsData => {
  809. tabsData = allTabsData;
  810. return refresh(tabsData.profileName);
  811. });
  812. getHelpContents();
  813. function init() {
  814. if (!AUTO_SAVE_SUPPORTED) {
  815. document.getElementById("autoSaveSection").hidden = true;
  816. document.getElementById("showAutoSaveProfileOption").hidden = true;
  817. rulesContainerElement.classList.add("compact");
  818. }
  819. if (!BACKGROUND_SAVE_SUPPORTED) {
  820. document.getElementById("backgroundSaveOptions").hidden = true;
  821. document.getElementById("confirmFilenameOption").hidden = true;
  822. document.getElementById("filenameConflictAction").hidden = true;
  823. }
  824. if (!BOOKMARKS_API_SUPPORTED) {
  825. document.getElementById("bookmarksOptions").hidden = true;
  826. }
  827. if (!AUTO_OPEN_EDITOR_SUPPORTED) {
  828. document.getElementById("autoOpenEditorOption").hidden = true;
  829. }
  830. if (!INFOBAR_SUPPORTED) {
  831. document.getElementById("displayInfobarOption").hidden = true;
  832. }
  833. if (!IDENTITY_API_SUPPORTED) {
  834. document.getElementById("saveToGDriveOption").hidden = true;
  835. document.getElementById("saveToDropboxOption").hidden = true;
  836. }
  837. if (!CLIPBOARD_API_SUPPORTED) {
  838. document.getElementById("saveToClipboardOption").hidden = true;
  839. }
  840. if (!NATIVE_API_API_SUPPORTED) {
  841. document.getElementById("saveWithCompanionOption").hidden = true;
  842. }
  843. if (!WEB_BLOCKING_API_SUPPORTED) {
  844. document.getElementById("passReferrerOnErrorOption").hidden = true;
  845. }
  846. if (!SHARE_API_SUPPORTED) {
  847. document.getElementById("sharePageOption").hidden = true;
  848. }
  849. }
  850. async function refresh(profileName) {
  851. const [profiles, rules, companionState] = await Promise.all([
  852. browser.runtime.sendMessage({ method: "config.getProfiles" }),
  853. browser.runtime.sendMessage({ method: "config.getRules" }),
  854. browser.runtime.sendMessage({ method: "companion.state" })]);
  855. const selectedProfileName = profileName || profileNamesInput.value || DEFAULT_PROFILE_NAME;
  856. Array.from(profileNamesInput.childNodes).forEach(node => node.remove());
  857. profileNamesInput.options.length = 0;
  858. ruleProfileInput.options.length = 0;
  859. ruleAutoSaveProfileInput.options.length = 0;
  860. ruleEditProfileInput.options.length = 0;
  861. ruleEditAutoSaveProfileInput.options.length = 0;
  862. let optionElement = document.createElement("option");
  863. optionElement.value = DEFAULT_PROFILE_NAME;
  864. optionElement.textContent = browser.i18n.getMessage("profileDefaultSettings");
  865. [CURRENT_PROFILE_NAME].concat(...Object.keys(profiles)).forEach(profileName => {
  866. const optionElement = document.createElement("option");
  867. optionElement.value = optionElement.textContent = profileName;
  868. if (profileName == DEFAULT_PROFILE_NAME) {
  869. optionElement.textContent = browser.i18n.getMessage("profileDefaultSettings");
  870. }
  871. if (profileName != CURRENT_PROFILE_NAME) {
  872. profileNamesInput.appendChild(optionElement);
  873. }
  874. ruleProfileInput.appendChild(optionElement.cloneNode(true));
  875. ruleAutoSaveProfileInput.appendChild(optionElement.cloneNode(true));
  876. ruleEditProfileInput.appendChild(optionElement.cloneNode(true));
  877. ruleEditAutoSaveProfileInput.appendChild(optionElement.cloneNode(true));
  878. });
  879. profileNamesInput.disabled = profileNamesInput.options.length == 1;
  880. optionElement = document.createElement("option");
  881. optionElement.value = DISABLED_PROFILE_NAME;
  882. optionElement.textContent = browser.i18n.getMessage("profileDisabled");
  883. ruleAutoSaveProfileInput.appendChild(optionElement);
  884. ruleEditAutoSaveProfileInput.appendChild(optionElement.cloneNode(true));
  885. const rulesDataElement = rulesElement.querySelector(".rules-data");
  886. Array.from(rulesDataElement.childNodes).forEach(node => (!node.className || !node.className.includes("rule-edit")) && node.remove());
  887. const editURLElement = rulesElement.querySelector(".rule-edit");
  888. createURLElement.hidden = false;
  889. editURLElement.hidden = true;
  890. ruleProfileInput.value = ruleAutoSaveProfileInput.value = selectedProfileName;
  891. let rulesDisplayed;
  892. rules.forEach(rule => {
  893. if (showAllProfilesInput.checked || selectedProfileName == rule.profile || selectedProfileName == rule.autoSaveProfile) {
  894. rulesDisplayed = true;
  895. const ruleElement = rulesElement.querySelector(".rule-view").cloneNode(true);
  896. const ruleUrlElement = ruleElement.querySelector(".rule-url");
  897. const ruleProfileElement = ruleElement.querySelector(".rule-profile");
  898. const ruleAutoSaveProfileElement = ruleElement.querySelector(".rule-autosave-profile");
  899. ruleUrlElement.textContent = ruleUrlElement.title = rule.url;
  900. ruleProfileElement.textContent = ruleProfileElement.title = getProfileText(rule.profile);
  901. ruleAutoSaveProfileElement.textContent = ruleAutoSaveProfileElement.title = getProfileText(rule.autoSaveProfile);
  902. ruleElement.hidden = false;
  903. ruleElement.className = "tr data";
  904. rulesDataElement.appendChild(ruleElement);
  905. const ruleDeleteButton = ruleElement.querySelector(".rule-delete-button");
  906. const ruleUpdateButton = ruleElement.querySelector(".rule-update-button");
  907. ruleDeleteButton.title = browser.i18n.getMessage("optionsDeleteRuleTooltip");
  908. ruleDeleteButton.addEventListener("click", async event => {
  909. if (await confirm(browser.i18n.getMessage("optionsDeleteRuleConfirm"), event.clientY - 100)) {
  910. await browser.runtime.sendMessage({ method: "config.deleteRule", url: rule.url });
  911. await refresh();
  912. await refreshExternalComponents();
  913. }
  914. }, false);
  915. ruleUpdateButton.title = browser.i18n.getMessage("optionsUpdateRuleTooltip");
  916. ruleUpdateButton.addEventListener("click", async () => {
  917. if (editURLElement.hidden) {
  918. createURLElement.hidden = true;
  919. editURLElement.hidden = false;
  920. rulesDataElement.replaceChild(editURLElement, ruleElement);
  921. ruleEditUrlInput.value = rule.url;
  922. ruleEditProfileInput.value = rule.profile;
  923. ruleEditAutoSaveProfileInput.value = rule.autoSaveProfile;
  924. ruleEditUrlInput.focus();
  925. editURLElement.onsubmit = async event => {
  926. event.preventDefault();
  927. rulesElement.appendChild(editURLElement);
  928. await browser.runtime.sendMessage({ method: "config.updateRule", url: rule.url, newUrl: ruleEditUrlInput.value, profileName: ruleEditProfileInput.value, autoSaveProfileName: ruleEditAutoSaveProfileInput.value });
  929. await refresh();
  930. await refreshExternalComponents();
  931. ruleUrlInput.focus();
  932. };
  933. }
  934. }, false);
  935. }
  936. });
  937. rulesDeleteAllButton.disabled = !rulesDisplayed;
  938. rulesElement.appendChild(createURLElement);
  939. profileNamesInput.value = selectedProfileName;
  940. renameProfileButton.disabled = deleteProfileButton.disabled = profileNamesInput.value == DEFAULT_PROFILE_NAME;
  941. const profileOptions = profiles[selectedProfileName];
  942. removeHiddenElementsInput.checked = profileOptions.removeHiddenElements;
  943. removeUnusedStylesInput.checked = profileOptions.removeUnusedStyles;
  944. removeUnusedFontsInput.checked = profileOptions.removeUnusedFonts;
  945. removeFramesInput.checked = profileOptions.removeFrames;
  946. blockScriptsInput.checked = profileOptions.blockScripts;
  947. blockVideosInput.checked = profileOptions.blockVideos;
  948. blockAudiosInput.checked = profileOptions.blockAudios;
  949. blockFontsInput.checked = profileOptions.blockFonts;
  950. blockStylesheetsInput.checked = profileOptions.blockStylesheets;
  951. blockImagesInput.checked = profileOptions.blockImages;
  952. acceptHeaderDocumentInput.value = profileOptions.acceptHeaders.document;
  953. acceptHeaderScriptInput.value = profileOptions.acceptHeaders.script;
  954. acceptHeaderAudioInput.value = profileOptions.acceptHeaders.audio;
  955. acceptHeaderVideoInput.value = profileOptions.acceptHeaders.video;
  956. acceptHeaderFontInput.value = profileOptions.acceptHeaders.font;
  957. acceptHeaderStylesheetInput.value = profileOptions.acceptHeaders.stylesheet;
  958. acceptHeaderImageInput.value = profileOptions.acceptHeaders.image;
  959. saveRawPageInput.checked = profileOptions.saveRawPage;
  960. insertMetaCSPInput.checked = profileOptions.insertMetaCSP;
  961. saveToClipboardInput.checked = profileOptions.saveToClipboard;
  962. addProofInput.checked = profileOptions.addProof;
  963. woleetKeyInput.value = profileOptions.woleetKey;
  964. woleetKeyInput.disabled = !profileOptions.addProof;
  965. saveToGDriveInput.checked = profileOptions.saveToGDrive;
  966. saveToDropboxInput.checked = profileOptions.saveToDropbox;
  967. saveWithWebDAVInput.checked = profileOptions.saveWithWebDAV;
  968. webDAVURLInput.value = profileOptions.webDAVURL;
  969. webDAVURLInput.disabled = !profileOptions.saveWithWebDAV;
  970. webDAVUserInput.value = profileOptions.webDAVUser;
  971. webDAVUserInput.disabled = !profileOptions.saveWithWebDAV;
  972. webDAVPasswordInput.value = profileOptions.webDAVPassword;
  973. webDAVPasswordInput.disabled = !profileOptions.saveWithWebDAV;
  974. saveToGitHubInput.checked = profileOptions.saveToGitHub;
  975. githubTokenInput.value = profileOptions.githubToken;
  976. githubTokenInput.disabled = !profileOptions.saveToGitHub;
  977. githubUserInput.value = profileOptions.githubUser;
  978. githubUserInput.disabled = !profileOptions.saveToGitHub;
  979. githubRepositoryInput.value = profileOptions.githubRepository;
  980. githubRepositoryInput.disabled = !profileOptions.saveToGitHub;
  981. githubBranchInput.value = profileOptions.githubBranch;
  982. githubBranchInput.disabled = !profileOptions.saveToGitHub;
  983. saveWithCompanionInput.checked = profileOptions.saveWithCompanion;
  984. saveToRestFormApiInput.checked = profileOptions.saveToRestFormApi;
  985. saveToRestFormApiUrlInput.value = profileOptions.saveToRestFormApiUrl;
  986. saveToRestFormApiUrlInput.disabled = !profileOptions.saveToRestFormApi;
  987. saveToRestFormApiTokenInput.value = profileOptions.saveToRestFormApiToken;
  988. saveToRestFormApiTokenInput.disabled = !profileOptions.saveToRestFormApi;
  989. saveToRestFormApiFileFieldNameInput.value = profileOptions.saveToRestFormApiFileFieldName;
  990. saveToRestFormApiFileFieldNameInput.disabled = !profileOptions.saveToRestFormApi;
  991. saveToRestFormApiUrlFieldNameInput.value = profileOptions.saveToRestFormApiUrlFieldName;
  992. saveToRestFormApiUrlFieldNameInput.disabled = !profileOptions.saveToRestFormApi;
  993. saveToS3Input.checked = profileOptions.saveToS3;
  994. S3DomainInput.value = profileOptions.S3Domain;
  995. S3DomainInput.disabled = !profileOptions.saveToS3;
  996. S3RegionInput.value = profileOptions.S3Region;
  997. S3RegionInput.disabled = !profileOptions.saveToS3;
  998. S3BucketInput.value = profileOptions.S3Bucket;
  999. S3BucketInput.disabled = !profileOptions.saveToS3;
  1000. S3AccessKeyInput.value = profileOptions.S3AccessKey;
  1001. S3AccessKeyInput.disabled = !profileOptions.saveToS3;
  1002. S3SecretKeyInput.value = profileOptions.S3SecretKey;
  1003. S3SecretKeyInput.disabled = !profileOptions.saveToS3;
  1004. sharePageInput.checked = profileOptions.sharePage;
  1005. saveToFilesystemInput.checked = !profileOptions.saveToGDrive && !profileOptions.saveToGitHub && !profileOptions.saveToS3 && !profileOptions.saveWithCompanion && !profileOptions.saveToClipboard && !profileOptions.saveWithWebDAV && !profileOptions.saveToDropbox && !profileOptions.saveToRestFormApi && !profileOptions.sharePage;
  1006. compressHTMLInput.checked = profileOptions.compressHTML;
  1007. compressCSSInput.checked = profileOptions.compressCSS;
  1008. moveStylesInHeadInput.checked = profileOptions.moveStylesInHead;
  1009. loadDeferredImagesInput.checked = profileOptions.loadDeferredImages;
  1010. loadDeferredImagesMaxIdleTimeInput.value = profileOptions.loadDeferredImagesMaxIdleTime;
  1011. loadDeferredImagesKeepZoomLevelInput.checked = profileOptions.loadDeferredImagesKeepZoomLevel;
  1012. loadDeferredImagesKeepZoomLevelInput.disabled = !profileOptions.loadDeferredImages;
  1013. loadDeferredImagesMaxIdleTimeInput.disabled = !profileOptions.loadDeferredImages;
  1014. loadDeferredImagesDispatchScrollEventInput.checked = profileOptions.loadDeferredImagesDispatchScrollEvent;
  1015. loadDeferredImagesDispatchScrollEventInput.disabled = !profileOptions.loadDeferredImages;
  1016. loadDeferredImagesBeforeFramesInput.checked = profileOptions.loadDeferredImagesBeforeFrames;
  1017. loadDeferredImagesBeforeFramesInput.disabled = !profileOptions.loadDeferredImages;
  1018. contextMenuEnabledInput.checked = profileOptions.contextMenuEnabled;
  1019. filenameTemplateInput.value = profileOptions.filenameTemplate;
  1020. filenameMaxLengthInput.value = profileOptions.filenameMaxLength;
  1021. filenameMaxLengthUnitInput.value = profileOptions.filenameMaxLengthUnit;
  1022. filenameReplacementCharacterInput.value = profileOptions.filenameReplacementCharacter;
  1023. replaceEmojisInFilenameInput.checked = profileOptions.replaceEmojisInFilename;
  1024. saveFilenameTemplateDataInput.checked = profileOptions.saveFilenameTemplateData;
  1025. shadowEnabledInput.checked = profileOptions.shadowEnabled;
  1026. maxResourceSizeEnabledInput.checked = profileOptions.maxResourceSizeEnabled;
  1027. maxResourceSizeInput.value = profileOptions.maxResourceSizeEnabled ? profileOptions.maxResourceSize : 10;
  1028. maxResourceSizeInput.disabled = !profileOptions.maxResourceSizeEnabled;
  1029. maxResourceDelayEnabledInput.checked = Boolean(profileOptions.networkTimeout);
  1030. maxResourceDelayInput.value = profileOptions.networkTimeout ? profileOptions.networkTimeout / 1000 : 60;
  1031. maxResourceDelayInput.disabled = !profileOptions.networkTimeout;
  1032. confirmFilenameInput.checked = profileOptions.confirmFilename;
  1033. filenameConflictActionInput.value = profileOptions.filenameConflictAction;
  1034. displayInfobarInput.checked = profileOptions.displayInfobar;
  1035. displayStatsInput.checked = profileOptions.displayStats;
  1036. backgroundSaveInput.checked = profileOptions.backgroundSave;
  1037. autoSaveDelayInput.value = profileOptions.autoSaveDelay;
  1038. autoSaveLoadInput.checked = !profileOptions.autoSaveLoadOrUnload && profileOptions.autoSaveLoad;
  1039. autoSaveLoadOrUnloadInput.checked = profileOptions.autoSaveLoadOrUnload;
  1040. autoSaveUnloadInput.checked = !profileOptions.autoSaveLoadOrUnload && profileOptions.autoSaveUnload;
  1041. autoSaveLoadInput.disabled = profileOptions.autoSaveLoadOrUnload;
  1042. autoSaveUnloadInput.disabled = profileOptions.autoSaveLoadOrUnload;
  1043. autoSaveDiscardInput.checked = profileOptions.autoSaveDiscard;
  1044. autoSaveRemoveInput.checked = profileOptions.autoSaveRemove;
  1045. autoSaveRepeatInput.checked = profileOptions.autoSaveRepeat;
  1046. autoSaveRepeatDelayInput.value = profileOptions.autoSaveRepeatDelay;
  1047. autoSaveRepeatDelayInput.disabled = !profileOptions.autoSaveRepeat;
  1048. autoSaveExternalSaveInput.checked = profileOptions.autoSaveExternalSave;
  1049. autoSaveExternalSaveInput.parentElement.hidden = !companionState.enabled;
  1050. removeAlternativeFontsInput.checked = profileOptions.removeAlternativeFonts;
  1051. removeAlternativeImagesInput.checked = profileOptions.removeAlternativeImages;
  1052. groupDuplicateImagesInput.checked = profileOptions.groupDuplicateImages;
  1053. removeAlternativeMediasInput.checked = profileOptions.removeAlternativeMedias;
  1054. saveCreatedBookmarksInput.checked = profileOptions.saveCreatedBookmarks;
  1055. passReferrerOnErrorInput.checked = profileOptions.passReferrerOnError;
  1056. replaceBookmarkURLInput.checked = profileOptions.replaceBookmarkURL;
  1057. replaceBookmarkURLInput.disabled = !profileOptions.saveCreatedBookmarks;
  1058. allowedBookmarkFoldersInput.value = profileOptions.allowedBookmarkFolders.map(folder => folder.replace(/,/g, "\\,")).join(",");
  1059. allowedBookmarkFoldersInput.disabled = !profileOptions.saveCreatedBookmarks;
  1060. ignoredBookmarkFoldersInput.value = profileOptions.ignoredBookmarkFolders.map(folder => folder.replace(/,/g, "\\,")).join(",");
  1061. ignoredBookmarkFoldersInput.disabled = !profileOptions.saveCreatedBookmarks;
  1062. fileFormatSelectInput.value = profileOptions.compressContent ? profileOptions.selfExtractingArchive ? profileOptions.extractDataFromPage ?
  1063. "self-extracting-zip-universal" : "self-extracting-zip" : "zip" : "html";
  1064. createRootDirectoryInput.checked = profileOptions.createRootDirectory;
  1065. createRootDirectoryInput.disabled = !profileOptions.compressContent;
  1066. preventAppendedDataInput.checked = profileOptions.preventAppendedData;
  1067. preventAppendedDataInput.disabled = !profileOptions.compressContent && !profileOptions.selfExtractingArchive;
  1068. passwordInput.value = profileOptions.password;
  1069. passwordInput.disabled = !profileOptions.compressContent;
  1070. insertTextBodyInput.checked = profileOptions.insertTextBody;
  1071. insertTextBodyInput.disabled = !profileOptions.compressContent || (!profileOptions.selfExtractingArchive && !profileOptions.extractDataFromPage);
  1072. insertEmbeddedCustomImageInput.checked = profileOptions.insertEmbeddedImage;
  1073. insertEmbeddedCustomImageInput.disabled = !profileOptions.compressContent || (!profileOptions.insertEmbeddedImage && !profileOptions.insertEmbeddedScreenshotImage);
  1074. insertEmbeddedScreenshotImageInput.checked = profileOptions.insertEmbeddedScreenshotImage;
  1075. insertEmbeddedScreenshotImageInput.disabled = !profileOptions.compressContent || (!profileOptions.insertEmbeddedImage && !profileOptions.insertEmbeddedScreenshotImage);
  1076. insertEmbeddedImageInput.checked = profileOptions.compressContent && (profileOptions.insertEmbeddedImage || profileOptions.insertEmbeddedScreenshotImage);
  1077. insertEmbeddedImageInput.disabled = !profileOptions.compressContent;
  1078. infobarTemplateInput.value = profileOptions.infobarTemplate;
  1079. blockMixedContentInput.checked = profileOptions.blockMixedContent;
  1080. saveOriginalURLsInput.checked = profileOptions.saveOriginalURLs;
  1081. includeInfobarInput.checked = profileOptions.includeInfobar;
  1082. openInfobarInput.checked = profileOptions.openInfobar;
  1083. removeInfobarSavedDateInput.checked = profileOptions.removeSavedDate;
  1084. confirmInfobarInput.checked = profileOptions.confirmInfobarContent;
  1085. autoCloseInput.checked = profileOptions.autoClose;
  1086. openEditorInput.checked = profileOptions.openEditor;
  1087. openSavedPageInput.checked = profileOptions.openSavedPage;
  1088. autoOpenEditorInput.checked = profileOptions.autoOpenEditor;
  1089. defaultEditorModeInput.value = profileOptions.defaultEditorMode;
  1090. applySystemThemeInput.checked = profileOptions.applySystemTheme;
  1091. warnUnsavedPageInput.checked = profileOptions.warnUnsavedPage;
  1092. displayInfobarInEditorInput.checked = profileOptions.displayInfobarInEditor;
  1093. }
  1094. function getProfileText(profileName) {
  1095. return profileName == DEFAULT_PROFILE_NAME ? browser.i18n.getMessage("profileDefaultSettings") : profileName == DISABLED_PROFILE_NAME ? browser.i18n.getMessage("profileDisabled") : profileName;
  1096. }
  1097. async function update() {
  1098. try {
  1099. await pendingSave;
  1100. } catch (error) {
  1101. // ignored
  1102. }
  1103. pendingSave = browser.runtime.sendMessage({
  1104. method: "config.updateProfile",
  1105. profileName: profileNamesInput.value,
  1106. profile: {
  1107. removeHiddenElements: removeHiddenElementsInput.checked,
  1108. removeUnusedStyles: removeUnusedStylesInput.checked,
  1109. removeUnusedFonts: removeUnusedFontsInput.checked,
  1110. removeFrames: removeFramesInput.checked,
  1111. blockScripts: blockScriptsInput.checked,
  1112. blockVideos: blockVideosInput.checked,
  1113. blockAudios: blockAudiosInput.checked,
  1114. blockFonts: blockFontsInput.checked,
  1115. blockStylesheets: blockStylesheetsInput.checked,
  1116. blockImages: blockImagesInput.checked,
  1117. acceptHeaders: {
  1118. document: acceptHeaderDocumentInput.value,
  1119. script: acceptHeaderScriptInput.value,
  1120. audio: acceptHeaderAudioInput.value,
  1121. video: acceptHeaderVideoInput.value,
  1122. font: acceptHeaderFontInput.value,
  1123. stylesheet: acceptHeaderStylesheetInput.value,
  1124. image: acceptHeaderImageInput.value
  1125. },
  1126. saveRawPage: saveRawPageInput.checked,
  1127. insertMetaCSP: insertMetaCSPInput.checked,
  1128. saveToClipboard: saveToClipboardInput.checked,
  1129. addProof: addProofInput.checked,
  1130. woleetKey: woleetKeyInput.value,
  1131. saveToGDrive: saveToGDriveInput.checked,
  1132. saveToDropbox: saveToDropboxInput.checked,
  1133. saveWithWebDAV: saveWithWebDAVInput.checked,
  1134. webDAVURL: webDAVURLInput.value,
  1135. webDAVUser: webDAVUserInput.value,
  1136. webDAVPassword: webDAVPasswordInput.value,
  1137. saveToGitHub: saveToGitHubInput.checked,
  1138. githubToken: githubTokenInput.value,
  1139. githubUser: githubUserInput.value,
  1140. githubRepository: githubRepositoryInput.value,
  1141. githubBranch: githubBranchInput.value,
  1142. saveWithCompanion: saveWithCompanionInput.checked,
  1143. sharePage: sharePageInput.checked,
  1144. compressHTML: compressHTMLInput.checked,
  1145. insertTextBody: insertTextBodyInput.checked,
  1146. insertEmbeddedImage: insertEmbeddedCustomImageInput.checked,
  1147. insertEmbeddedScreenshotImage: insertEmbeddedScreenshotImageInput.checked,
  1148. compressCSS: compressCSSInput.checked,
  1149. moveStylesInHead: moveStylesInHeadInput.checked,
  1150. loadDeferredImages: loadDeferredImagesInput.checked,
  1151. loadDeferredImagesMaxIdleTime: Math.max(loadDeferredImagesMaxIdleTimeInput.value, 0),
  1152. loadDeferredImagesKeepZoomLevel: loadDeferredImagesKeepZoomLevelInput.checked,
  1153. loadDeferredImagesDispatchScrollEvent: loadDeferredImagesDispatchScrollEventInput.checked,
  1154. loadDeferredImagesBeforeFrames: loadDeferredImagesBeforeFramesInput.checked,
  1155. contextMenuEnabled: contextMenuEnabledInput.checked,
  1156. filenameTemplate: filenameTemplateInput.value,
  1157. filenameMaxLength: filenameMaxLengthInput.value,
  1158. filenameMaxLengthUnit: filenameMaxLengthUnitInput.value,
  1159. filenameReplacementCharacter: filenameReplacementCharacterInput.value,
  1160. replaceEmojisInFilename: replaceEmojisInFilenameInput.checked,
  1161. saveFilenameTemplateData: saveFilenameTemplateDataInput.checked,
  1162. shadowEnabled: shadowEnabledInput.checked,
  1163. maxResourceSizeEnabled: maxResourceSizeEnabledInput.checked,
  1164. maxResourceSize: maxResourceSizeEnabledInput.checked ? Math.max(maxResourceSizeInput.value, 0) : 10,
  1165. networkTimeout: maxResourceDelayEnabledInput.checked ? Math.max(maxResourceDelayInput.value * 1000, 60) : 0,
  1166. confirmFilename: confirmFilenameInput.checked,
  1167. filenameConflictAction: filenameConflictActionInput.value,
  1168. displayInfobar: displayInfobarInput.checked,
  1169. displayStats: displayStatsInput.checked,
  1170. backgroundSave: backgroundSaveInput.checked,
  1171. autoSaveDelay: Math.max(autoSaveDelayInput.value, 0),
  1172. autoSaveLoad: autoSaveLoadInput.checked,
  1173. autoSaveUnload: autoSaveUnloadInput.checked,
  1174. autoSaveDiscard: autoSaveDiscardInput.checked,
  1175. autoSaveRemove: autoSaveRemoveInput.checked,
  1176. autoSaveLoadOrUnload: autoSaveLoadOrUnloadInput.checked,
  1177. autoSaveRepeat: autoSaveRepeatInput.checked,
  1178. autoSaveRepeatDelay: Math.max(autoSaveRepeatDelayInput.value, 1),
  1179. autoSaveExternalSave: autoSaveExternalSaveInput.checked,
  1180. removeAlternativeFonts: removeAlternativeFontsInput.checked,
  1181. removeAlternativeImages: removeAlternativeImagesInput.checked,
  1182. removeAlternativeMedias: removeAlternativeMediasInput.checked,
  1183. saveCreatedBookmarks: saveCreatedBookmarksInput.checked,
  1184. passReferrerOnError: passReferrerOnErrorInput.checked,
  1185. replaceBookmarkURL: replaceBookmarkURLInput.checked,
  1186. allowedBookmarkFolders: allowedBookmarkFoldersInput.value.replace(/([^\\]),/g, "$1 ,").split(/[^\\],/).map(folder => folder.replace(/\\,/g, ",")),
  1187. ignoredBookmarkFolders: ignoredBookmarkFoldersInput.value.replace(/([^\\]),/g, "$1 ,").split(/[^\\],/).map(folder => folder.replace(/\\,/g, ",")),
  1188. compressContent: fileFormatSelectInput.value.includes("zip"),
  1189. createRootDirectory: createRootDirectoryInput.checked,
  1190. preventAppendedData: preventAppendedDataInput.checked,
  1191. selfExtractingArchive: fileFormatSelectInput.value.includes("self-extracting"),
  1192. extractDataFromPage: fileFormatSelectInput.value == "self-extracting-zip-universal",
  1193. password: passwordInput.value,
  1194. groupDuplicateImages: groupDuplicateImagesInput.checked,
  1195. infobarTemplate: infobarTemplateInput.value,
  1196. blockMixedContent: blockMixedContentInput.checked,
  1197. saveOriginalURLs: saveOriginalURLsInput.checked,
  1198. includeInfobar: includeInfobarInput.checked,
  1199. openInfobar: openInfobarInput.checked,
  1200. removeSavedDate: removeInfobarSavedDateInput.checked,
  1201. confirmInfobarContent: confirmInfobarInput.checked,
  1202. autoClose: autoCloseInput.checked,
  1203. openEditor: openEditorInput.checked,
  1204. openSavedPage: openSavedPageInput.checked,
  1205. autoOpenEditor: autoOpenEditorInput.checked,
  1206. defaultEditorMode: defaultEditorModeInput.value,
  1207. applySystemTheme: applySystemThemeInput.checked,
  1208. warnUnsavedPage: warnUnsavedPageInput.checked,
  1209. displayInfobarInEditor: displayInfobarInEditorInput.checked,
  1210. saveToRestFormApi: saveToRestFormApiInput.checked,
  1211. saveToRestFormApiUrl: saveToRestFormApiUrlInput.value,
  1212. saveToRestFormApiToken: saveToRestFormApiTokenInput.value,
  1213. saveToRestFormApiFileFieldName: saveToRestFormApiFileFieldNameInput.value,
  1214. saveToRestFormApiUrlFieldName: saveToRestFormApiUrlFieldNameInput.value,
  1215. saveToS3: saveToS3Input.checked,
  1216. S3Domain: S3DomainInput.value,
  1217. S3Region: S3RegionInput.value,
  1218. S3Bucket: S3BucketInput.value,
  1219. S3AccessKey: S3AccessKeyInput.value,
  1220. S3SecretKey: S3SecretKeyInput.value
  1221. }
  1222. });
  1223. try {
  1224. await pendingSave;
  1225. } catch (error) {
  1226. // ignored
  1227. }
  1228. }
  1229. async function refreshExternalComponents() {
  1230. try {
  1231. await browser.runtime.sendMessage({ method: "ui.refreshMenu" });
  1232. if (sidePanelDisplay) {
  1233. await browser.runtime.sendMessage({ method: "options.refresh", profileName: profileNamesInput.value });
  1234. } else {
  1235. await browser.runtime.sendMessage({ method: "options.refreshPanel", profileName: profileNamesInput.value });
  1236. }
  1237. } catch (error) {
  1238. // ignored
  1239. }
  1240. }
  1241. async function saveCreatedBookmarks() {
  1242. if (saveCreatedBookmarksInput.checked) {
  1243. saveCreatedBookmarksInput.checked = false;
  1244. try {
  1245. const permissionGranted = await browser.permissions.request({ permissions: ["bookmarks"] });
  1246. if (permissionGranted) {
  1247. saveCreatedBookmarksInput.checked = true;
  1248. await update();
  1249. await refresh();
  1250. await browser.runtime.sendMessage({ method: "bookmarks.saveCreatedBookmarks" });
  1251. } else {
  1252. await disableOption();
  1253. }
  1254. } catch (error) {
  1255. saveCreatedBookmarksInput.checked = false;
  1256. await disableOption();
  1257. }
  1258. } else {
  1259. try {
  1260. await browser.permissions.remove({ permissions: ["bookmarks"] });
  1261. } catch (error) {
  1262. // ignored
  1263. }
  1264. await disableOption();
  1265. }
  1266. async function disableOption() {
  1267. await update();
  1268. await refresh();
  1269. await browser.runtime.sendMessage({ method: "bookmarks.disable" });
  1270. }
  1271. }
  1272. async function onClickSaveToClipboard() {
  1273. if (saveToClipboardInput.checked) {
  1274. saveToClipboardInput.checked = false;
  1275. try {
  1276. const permissionGranted = await browser.permissions.request({ permissions: ["clipboardWrite"] });
  1277. if (permissionGranted) {
  1278. saveToClipboardInput.checked = true;
  1279. await browser.runtime.sendMessage({ method: "downloads.disableGDrive" });
  1280. }
  1281. } catch (error) {
  1282. saveToClipboardInput.checked = false;
  1283. }
  1284. }
  1285. await update();
  1286. await refresh();
  1287. }
  1288. async function onClickSaveToGDrive() {
  1289. if (saveToGDriveInput.checked) {
  1290. saveToGDriveInput.checked = false;
  1291. try {
  1292. if (requestPermissionIdentity) {
  1293. const permissionGranted = await browser.permissions.request({ permissions: ["identity"] });
  1294. if (permissionGranted) {
  1295. saveToGDriveInput.checked = true;
  1296. }
  1297. } else {
  1298. saveToGDriveInput.checked = true;
  1299. }
  1300. } catch (error) {
  1301. saveToGDriveInput.checked = false;
  1302. await browser.runtime.sendMessage({ method: "downloads.disableGDrive" });
  1303. }
  1304. }
  1305. await update();
  1306. await refresh();
  1307. }
  1308. async function disableDestinationPermissions(permissions, disableGDrive = true, disableDropbox = true) {
  1309. if (disableGDrive) {
  1310. await browser.runtime.sendMessage({ method: "downloads.disableGDrive" });
  1311. }
  1312. if (disableDropbox) {
  1313. await browser.runtime.sendMessage({ method: "downloads.disableDropbox" });
  1314. }
  1315. try {
  1316. await browser.permissions.remove({ permissions });
  1317. } catch (error) {
  1318. //ignored
  1319. }
  1320. }
  1321. async function passReferrerOnError() {
  1322. if (passReferrerOnErrorInput.checked) {
  1323. passReferrerOnErrorInput.checked = false;
  1324. try {
  1325. const permissionGranted = await browser.permissions.request({ permissions: ["webRequest", "webRequestBlocking"] });
  1326. if (permissionGranted) {
  1327. passReferrerOnErrorInput.checked = true;
  1328. await update();
  1329. await refresh();
  1330. await browser.runtime.sendMessage({ method: "requests.enableReferrerOnError" });
  1331. } else {
  1332. await disableOption();
  1333. }
  1334. } catch (error) {
  1335. await disableOption();
  1336. }
  1337. } else {
  1338. await disableOption();
  1339. }
  1340. async function disableOption() {
  1341. await update();
  1342. await refresh();
  1343. await browser.runtime.sendMessage({ method: "requests.disableReferrerOnError" });
  1344. await browser.permissions.remove({ permissions: ["webRequest", "webRequestBlocking"] });
  1345. }
  1346. }
  1347. async function enableExternalSave(input) {
  1348. if (input.checked) {
  1349. input.checked = false;
  1350. try {
  1351. const permissionGranted = await browser.permissions.request({ permissions: ["nativeMessaging"] });
  1352. if (permissionGranted) {
  1353. input.checked = true;
  1354. await refreshOption();
  1355. if (window.chrome) {
  1356. window.chrome.runtime.reload();
  1357. }
  1358. } else {
  1359. await refreshOption();
  1360. }
  1361. } catch (error) {
  1362. input.checked = true;
  1363. await refreshOption();
  1364. }
  1365. } else {
  1366. await refreshOption();
  1367. }
  1368. async function refreshOption() {
  1369. await update();
  1370. await refresh();
  1371. }
  1372. }
  1373. async function confirm(message, positionY) {
  1374. document.getElementById("confirmLabel").textContent = message;
  1375. document.getElementById("formConfirmContainer").style.setProperty("display", "flex");
  1376. document.querySelector("#formConfirmContainer .popup-content").style.setProperty("margin-top", positionY + "px");
  1377. confirmButton.focus();
  1378. document.body.style.setProperty("overflow-y", "hidden");
  1379. return new Promise(resolve => {
  1380. confirmButton.onclick = event => hideAndResolve(event, true);
  1381. cancelButton.onclick = event => hideAndResolve(event);
  1382. window.onkeyup = event => {
  1383. if (event.key == "Escape") {
  1384. hideAndResolve(event);
  1385. }
  1386. };
  1387. function hideAndResolve(event, value) {
  1388. event.preventDefault();
  1389. document.getElementById("formConfirmContainer").style.setProperty("display", "none");
  1390. document.body.style.setProperty("overflow-y", "");
  1391. resolve(value);
  1392. }
  1393. });
  1394. }
  1395. async function reset(positionY) {
  1396. document.getElementById("formResetContainer").style.setProperty("display", "flex");
  1397. document.querySelector("#formResetContainer .popup-content").style.setProperty("margin-top", positionY + "px");
  1398. resetCancelButton.focus();
  1399. document.body.style.setProperty("overflow-y", "hidden");
  1400. return new Promise(resolve => {
  1401. resetAllButton.onclick = event => hideAndResolve(event, "all");
  1402. resetCurrentButton.onclick = event => hideAndResolve(event, "current");
  1403. resetCancelButton.onclick = event => hideAndResolve(event);
  1404. window.onkeyup = event => {
  1405. if (event.key == "Escape") {
  1406. hideAndResolve(event);
  1407. }
  1408. };
  1409. function hideAndResolve(event, value) {
  1410. event.preventDefault();
  1411. document.getElementById("formResetContainer").style.setProperty("display", "none");
  1412. document.body.style.setProperty("overflow-y", "");
  1413. resolve(value);
  1414. }
  1415. });
  1416. }
  1417. async function prompt(message, positionY, defaultValue = "") {
  1418. document.getElementById("promptLabel").textContent = message;
  1419. document.getElementById("formPromptContainer").style.setProperty("display", "flex");
  1420. document.querySelector("#formPromptContainer .popup-content").style.setProperty("margin-top", positionY + "px");
  1421. promptInput.value = defaultValue;
  1422. promptInput.focus();
  1423. document.body.style.setProperty("overflow-y", "hidden");
  1424. return new Promise(resolve => {
  1425. promptConfirmButton.onclick = event => hideAndResolve(event, promptInput.value);
  1426. promptCancelButton.onclick = event => hideAndResolve(event);
  1427. window.onkeyup = event => {
  1428. if (event.key == "Escape") {
  1429. hideAndResolve(event);
  1430. }
  1431. };
  1432. function hideAndResolve(event, value) {
  1433. event.preventDefault();
  1434. document.getElementById("formPromptContainer").style.setProperty("display", "none");
  1435. document.body.style.setProperty("overflow-y", "");
  1436. resolve(value);
  1437. }
  1438. });
  1439. }
  1440. async function getHelpContents() {
  1441. const helpPage = await fetch(browser.runtime.getURL(HELP_PAGE_PATH));
  1442. const content = new TextDecoder().decode(await helpPage.arrayBuffer());
  1443. const doc = (new DOMParser()).parseFromString(content, "text/html");
  1444. const items = doc.querySelectorAll("[data-options-label]");
  1445. items.forEach(itemElement => {
  1446. const optionLabel = document.getElementById(itemElement.dataset.optionsLabel);
  1447. if (optionLabel) {
  1448. const helpIconWrapper = document.createElement("span");
  1449. const helpIconContainer = document.createElement("span");
  1450. const helpIcon = document.createElement("img");
  1451. helpIcon.src = HELP_ICON_URL;
  1452. helpIconWrapper.className = "help-icon-wrapper";
  1453. const labelWords = optionLabel.textContent.split(/\s+/);
  1454. if (labelWords.length > 1) {
  1455. helpIconWrapper.textContent = labelWords.pop();
  1456. optionLabel.textContent = labelWords.join(" ") + " ";
  1457. }
  1458. helpIconContainer.className = "help-icon";
  1459. helpIconContainer.onclick = () => {
  1460. helpContent.hidden = !helpContent.hidden;
  1461. return false;
  1462. };
  1463. helpIcon.tabIndex = 0;
  1464. helpIconContainer.onkeyup = event => {
  1465. if (event.code == "Enter") {
  1466. helpContent.hidden = !helpContent.hidden;
  1467. return false;
  1468. }
  1469. };
  1470. helpIconContainer.appendChild(helpIcon);
  1471. helpIconWrapper.appendChild(helpIconContainer);
  1472. optionLabel.appendChild(helpIconWrapper);
  1473. const helpContent = document.createElement("div");
  1474. helpContent.hidden = true;
  1475. helpContent.className = "help-content";
  1476. itemElement.childNodes.forEach(node => {
  1477. if (node instanceof HTMLElement && node.className != "option") {
  1478. helpContent.appendChild(document.importNode(node, true));
  1479. }
  1480. });
  1481. helpContent.querySelectorAll("a[href]").forEach(linkElement => {
  1482. const hrefValue = linkElement.getAttribute("href");
  1483. if (hrefValue.startsWith("#")) {
  1484. linkElement.href = browser.runtime.getURL(HELP_PAGE_PATH + linkElement.getAttribute("href"));
  1485. linkElement.target = "_blank";
  1486. }
  1487. });
  1488. optionLabel.parentElement.insertAdjacentElement("afterEnd", helpContent);
  1489. }
  1490. });
  1491. }
  1492. function getLocalStorageItem(key) {
  1493. try {
  1494. return localStorage.getItem(key);
  1495. } catch (error) {
  1496. // ignored
  1497. }
  1498. }
  1499. function setLocalStorageItem(key, value) {
  1500. try {
  1501. return localStorage.setItem(key, value);
  1502. } catch (error) {
  1503. // ignored
  1504. }
  1505. }
  1506. function removeLocalStorageItem(key) {
  1507. try {
  1508. return localStorage.removeItem(key);
  1509. } catch (error) {
  1510. // ignored
  1511. }
  1512. }