diff --git a/BUILD.gn b/BUILD.gn index dea9cd3c79b..75eff7fb313 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -91,6 +91,15 @@ if (is_win || is_mac || is_linux) { brave_all_unit_tests_deps += [ "//brave/updater:brave_updater_unittests" ] } +if (is_win) { + # These tests are especially important while we are maintaining the delta + # update logic ourselves. See github.com/brave/brave-core/pull/31937. + brave_all_unit_tests_deps += [ + "//chrome/installer/setup:setup_unittests", + "//chrome/installer/util:installer_util_unittests", + ] +} + # This group is for unit tests that run as part of brave_all_unit_tests. Other # tests that you only want to build should be added directly to `all` group group("brave_all_unit_tests") { diff --git a/app/brave_strings.grd b/app/brave_strings.grd index a9a370ad4b6..574cf7aad03 100644 --- a/app/brave_strings.grd +++ b/app/brave_strings.grd @@ -2814,6 +2814,8 @@ Brave is unable to recover your settings. Google Chrome Beta Google Chrome Dev - + + Installation failed due to unspecified error. Please download Brave again. + diff --git a/app/resources/brave_strings_af.xtb b/app/resources/brave_strings_af.xtb index fac6fb6a8c2..f11ea9fb657 100644 --- a/app/resources/brave_strings_af.xtb +++ b/app/resources/brave_strings_af.xtb @@ -698,4 +698,5 @@ Brave kan nie jou instellings herwin nie. Wanneer jy iets in die adresbalk of soekkassie tik, stuur Brave wat jy tik na jou versteksoekenjin toe om beter voorstelle te kry. Dit is af in Incognito. Brave Incognito Brave sal jou waarsku voordat ’n werf met ’n onveilige verbinding gelaai word wanneer jy in Incognitomodus blaai +Kon weens 'n ongespesifiseerde fout nie installeer nie. Laai Brave asseblief weer af. \ No newline at end of file diff --git a/app/resources/brave_strings_am.xtb b/app/resources/brave_strings_am.xtb index 8f9b20c61fb..29c86297112 100644 --- a/app/resources/brave_strings_am.xtb +++ b/app/resources/brave_strings_am.xtb @@ -700,4 +700,5 @@ Brave ቅንብሮችዎን ማስመለስ አልቻለም። በአድራሻ አሞሌው ወይም የፍለጋ ሳጥን ላይ ሲተይቡ፣ Brave የተሻሉ ጥቆማዎችን ለማግኘት በእርስዎ ነባሪ የፍለጋ ሞተር የተየቡትን ይልካል። ይህ በግላዊነት ውስጥ ይጠፋል። Brave Private በግል ሁነታ ውስጥ ሲያስሱ Brave ደህንነቱ ያልተጠበቀ ግንኙነት በመጠቀም ጣቢያ ከመጫንዎ በፊት ያስጠነቅቀዎታል +ተለይቶ ባልታወቀ ስህተት ምክንያት ጭነት ከሽፏል። እባክዎ Braveን እንደገና ያውርዱ። \ No newline at end of file diff --git a/app/resources/brave_strings_ar.xtb b/app/resources/brave_strings_ar.xtb index e870f79a6d8..a86670b4a99 100644 --- a/app/resources/brave_strings_ar.xtb +++ b/app/resources/brave_strings_ar.xtb @@ -699,4 +699,5 @@ عندما تكتب في شريط العناوين أو مربع البحث، فإن Brave يرسل ما تكتبه إلى محرك البحث الافتراضي للحصول على اقتراحات أفضل. هذا متوقف في الوضع الخاص. Brave Private عند التصفح في وضع خاص، سيحذرك متصفح Brave قبل تحميل موقع باستخدام اتصال غير آمن +‏تعذّر التثبيت نظرًا لحدوث خطأ غير محدد. يُرجى إعادة تنزيل Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_as.xtb b/app/resources/brave_strings_as.xtb index 0cf98769c4e..4fb7b020eb7 100644 --- a/app/resources/brave_strings_as.xtb +++ b/app/resources/brave_strings_as.xtb @@ -698,4 +698,5 @@ Braveএ আপোনাৰ ছেটিংসমূহ পুনৰুদ্ধ আপোনাৰ অৱস্থান ব্যৱহাৰ কৰিবলৈ, ছিষ্টেমৰ ছেটিঙত Braveক এক্সেছ দিয়ক Google Chrome বিটা Google Chrome Dev +অনির্দিষ্ট আসোঁৱাহৰ বাবে ইনষ্টলেশ্বন কৰিব পৰা নগ’ল। অনুগ্ৰহ কৰি পুনৰ Brave ডাউনল’ড কৰক। \ No newline at end of file diff --git a/app/resources/brave_strings_az.xtb b/app/resources/brave_strings_az.xtb index bd5011508ac..796138ef6ba 100644 --- a/app/resources/brave_strings_az.xtb +++ b/app/resources/brave_strings_az.xtb @@ -706,4 +706,5 @@ Bəzi funksiyalar əlçatmaz ola bilər. Xüsusi profil direktoriyası göstəri Ünvan panelinə və ya axtarış qutusuna yazdıqda, Brave daha yaxşı tövsiyələr vermək üçün yazdıqlarınızı standart axtarış mühərrikinizə göndərir. Bu xüsusiyyət Gizli rejimdə bağlıdır. Brave Gizli rejimi İnternetə Gizli rejimdə baxarkən Brave təhlükəli bağlantıya malik bir saytdan istifadə etməzdən əvvəl sizə xəbərdarlıq göndərir +Naməlum xəta üzündən quraşdırmaq alınmadı. Brave'u yenidən endirin. \ No newline at end of file diff --git a/app/resources/brave_strings_be.xtb b/app/resources/brave_strings_be.xtb index 32cc4bbba37..2c59e1fe41b 100644 --- a/app/resources/brave_strings_be.xtb +++ b/app/resources/brave_strings_be.xtb @@ -697,4 +697,5 @@ Каб выкарыстоўваць месцазнаходжанне, дайце Brave адпаведны доступ у сістэмных наладах Google Chrome (бэта-версія) Google Chrome для распрацоўшчыкаў +Збой усталявання з-за нявызначанай памылкі. Спампуйце Brave зноў. \ No newline at end of file diff --git a/app/resources/brave_strings_bg.xtb b/app/resources/brave_strings_bg.xtb index adc9f7cd32f..a9689a29c90 100644 --- a/app/resources/brave_strings_bg.xtb +++ b/app/resources/brave_strings_bg.xtb @@ -693,4 +693,5 @@ Когато пишете в адресната лента или полето за търсене, Brave автоматично изпраща написаното към Вашата търсачка по подразбиране, за да получите по-добри предложения. Тази функция е изключена в режим Личен. Поверителен режим на Brave Когато сърфирате в частен режим, Brave ще ви предупреждава, преди да заредите сайт, който използва незащитена връзка. +Инсталирането не бе успешно поради неизвестна грешка. Моля, изтеглете отново Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_bn.xtb b/app/resources/brave_strings_bn.xtb index 4ed6b1c91f7..8b1e023a9e2 100644 --- a/app/resources/brave_strings_bn.xtb +++ b/app/resources/brave_strings_bn.xtb @@ -694,4 +694,5 @@ Brave আপনার সেটিংস পুনরুদ্ধার কর আপনি যখন অ্যাড্রেস বারে বা সন্ধানের বক্সে টাইপ করেন তখন আরো ভালো পরামর্শ পেতে Brave, আপনি যা টাইপ করেন সেটিকে আপনার ডিফল্ট সন্ধানের ইঞ্জিনে পাঠায়। ব্যক্তিগত-তে এটি বন্ধ। Brave ব্যক্তিগত ব্যক্তিগত মোডে ব্রাউজ করার সময়, একটি অনিরাপদ সংযোগ ব্যবহার করে একটি সাইট লোড করার আগে Brave আপনাকে সতর্ক করবে +অনির্দিষ্ট ত্রুটির কারণে ইনস্টল করা যায়নি৷ অনুগ্রহ করে Brave আবার ডাউনলোড করুন৷ \ No newline at end of file diff --git a/app/resources/brave_strings_bs.xtb b/app/resources/brave_strings_bs.xtb index 36c32145130..07f4bbab10d 100644 --- a/app/resources/brave_strings_bs.xtb +++ b/app/resources/brave_strings_bs.xtb @@ -698,4 +698,5 @@ Brave ne može vratiti vaše postavke. Da koristite lokaciju, odobrite Braveu pristup u postavkama sistema Google Chrome Beta Google Chrome Dev +Instalacija nije uspjela zbog neodređene greške. Ponovo preuzmite Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_ca.xtb b/app/resources/brave_strings_ca.xtb index 868aadb0bc3..b0f1c1edd97 100644 --- a/app/resources/brave_strings_ca.xtb +++ b/app/resources/brave_strings_ca.xtb @@ -699,4 +699,5 @@ Brave no pot recuperar la configuració. Quan escrius a la barra d'adreces o al quadre de cerca, Brave envia el que escrius al motor de cerca predeterminat per obtenir millors suggeriments. Aquesta opció està desactivada en el mode d'incògnit. Brave Incògnit Quan navegues en mode d'incògnit, Brave t'avisarà abans de carregar un lloc web que utilitzi una connexió no segura +La instal·lació ha fallat a causa d'un error no especificat. Torneu a baixar Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_cs.xtb b/app/resources/brave_strings_cs.xtb index 539cbb0693d..0c247439aad 100644 --- a/app/resources/brave_strings_cs.xtb +++ b/app/resources/brave_strings_cs.xtb @@ -700,4 +700,5 @@ Brave nemůže vaše nastavení obnovit. Když zadáváte text do adresního řádku nebo vyhledávacího pole, Brave zasílá vámi psaný text do vašeho výchozího vyhledávače, aby byla zobrazena lepší doporučení. To je v soukromém režimu vypnuto. Soukromé Brave Při procházení v soukromém režimu vás Brave před načtením webu prostřednictvím nezabezpečeného připojení upozorní +Instalace se z neznámého důvodu nezdařila. Stáhněte prosím Brave znovu. \ No newline at end of file diff --git a/app/resources/brave_strings_cy.xtb b/app/resources/brave_strings_cy.xtb index 3620ef513cc..67184752c97 100644 --- a/app/resources/brave_strings_cy.xtb +++ b/app/resources/brave_strings_cy.xtb @@ -698,4 +698,5 @@ Ni all Brave adfer eich gosodiadau. I ddefnyddio'ch lleoliad, rhowch fynediad i Brave yn y gosodiadau system Beta Google Chrome Google Chrome Dev +Methwyd y gosodiad oherwydd gwall amhenodol. Lawrlwythwch Brave eto. \ No newline at end of file diff --git a/app/resources/brave_strings_da.xtb b/app/resources/brave_strings_da.xtb index 835b6e5bd5b..1b16865341c 100644 --- a/app/resources/brave_strings_da.xtb +++ b/app/resources/brave_strings_da.xtb @@ -696,4 +696,5 @@ Brave kan ikke gendanne dine præferencer. Når du skriver noget i adresselinjen eller søgefeltet, sender Brave de indtastede værdier til din primære søgemaskine for at få bedre forslag. Dette er slået fra i Privat-tilstand. Brave Private Når du browser i Privat tilstand, vil Brave advare dig, før du indlæser et websted ved hjælp af en usikker forbindelse +Installationen mislykkedes på grund af en uspecificeret fejl. Download Brave igen. \ No newline at end of file diff --git a/app/resources/brave_strings_de.xtb b/app/resources/brave_strings_de.xtb index cc5876bfab1..ede648bc092 100644 --- a/app/resources/brave_strings_de.xtb +++ b/app/resources/brave_strings_de.xtb @@ -695,4 +695,5 @@ Brave kann deine Einstellungen nicht wiederherstellen. Wenn Sie etwas in die Adressleiste oder das Suchfeld eingeben, sendet Brave Ihre Eingabe an Ihre Standardsuchmaschine, um bessere Vorschläge zu erhalten. Dies ist im Privatmodus deaktiviert. Brave-Privatmodus Wenn Sie im privaten Modus surfen, warnt Brave Sie, bevor Sie eine Website über eine unsichere Verbindung laden. +Die Installation konnte aufgrund eines undefinierten Fehlers nicht abgeschlossen werden. Bitte lade Brave erneut herunter. \ No newline at end of file diff --git a/app/resources/brave_strings_el.xtb b/app/resources/brave_strings_el.xtb index f66992bde59..d75e35e271a 100644 --- a/app/resources/brave_strings_el.xtb +++ b/app/resources/brave_strings_el.xtb @@ -708,4 +708,5 @@ Όταν πληκτρολογείτε κάτι στη γραμμή διευθύνσεων ή στο πλαίσιο αναζήτησης, το Brave στέλνει το περιεχόμενο που πληκτρολογείτε στην προεπιλεγμένη μηχανή αναζήτησής σας για να λαμβάνετε καλύτερες προτάσεις. Αυτή η επιλογή είναι απενεργοποιημένη στην Ιδιωτική λειτουργία. Ιδιωτική λειτουργία Brave Κατά την Ανώνυμη Περιήγηση, ο Brave θα σας προειδοποιεί πριν φορτώσετε κάποια ιστοσελίδα με μη ασφαλή σύνδεση +Η εγκατάσταση απέτυχε λόγω μη καθορισμένου σφάλματος. Κατεβάστε το Brave ξανά. \ No newline at end of file diff --git a/app/resources/brave_strings_en-GB.xtb b/app/resources/brave_strings_en-GB.xtb index 3a5bd159c1f..2afc3043421 100644 --- a/app/resources/brave_strings_en-GB.xtb +++ b/app/resources/brave_strings_en-GB.xtb @@ -701,4 +701,5 @@ Brave is unable to recover your settings. When you type in the address bar or search box, Brave sends what you type to your default search engine to get better suggestions. This is off in Private. Brave Private When browsing in Private mode, Brave will warn you before loading a site using an insecure connection +Installation failed due to unspecified error. Please download Brave again. \ No newline at end of file diff --git a/app/resources/brave_strings_es-419.xtb b/app/resources/brave_strings_es-419.xtb index ebc7b26b697..056344705f9 100644 --- a/app/resources/brave_strings_es-419.xtb +++ b/app/resources/brave_strings_es-419.xtb @@ -693,4 +693,5 @@ Cuando escribes en la barra de direcciones o en el cuadro de búsqueda, Brave envía lo que escribes a tu motor de búsqueda predeterminado para obtener mejores sugerencias. Esto está desactivado en el modo de incógnito. Modo privado de Brave Cuando navegues en modo de incógnito, Brave te avisará antes de cargar un sitio que utilice una conexión no segura +La instalación falló debido a un error no especificado. Descarga Brave otra vez. \ No newline at end of file diff --git a/app/resources/brave_strings_es.xtb b/app/resources/brave_strings_es.xtb index 7598ff0d8dc..0c9bbfed9ba 100644 --- a/app/resources/brave_strings_es.xtb +++ b/app/resources/brave_strings_es.xtb @@ -710,4 +710,5 @@ Brave no puede recuperar tu configuración. Cuando escribes en la barra de direcciones o en el cuadro de búsqueda, Brave envía lo que escribes a tu motor de búsqueda predeterminado para obtener mejores sugerencias. Esta función está desactivada en el modo de incógnito. Modo privado de Brave Al navegar en el modo privado, Brave te advertirá cada vez que trates de cargar un sitio web con una conexión no segura +La instalación ha fallado debido a un error no especificado. Vuelve a descargar Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_et.xtb b/app/resources/brave_strings_et.xtb index 1e10bdc0697..56561d8aa28 100644 --- a/app/resources/brave_strings_et.xtb +++ b/app/resources/brave_strings_et.xtb @@ -699,4 +699,5 @@ Brave ei saa teie seadeid taastada. Kui sisestate midagi aadressiribale või otsingukasti, saadab Brave sisestatava teie vaikeotsingumootorile, et saada paremaid soovitusi. Privaatses režiimis on see välja lülitatud. Brave’i privaatrežiim Privaatrežiimis sirvimisel hoiatab Brave teid enne ebaturvalise ühenduse kaudu veebisaidi laadimist +Installimine ebaõnnestus tundmatu vea tõttu. Laadige Brave uuesti alla. \ No newline at end of file diff --git a/app/resources/brave_strings_eu.xtb b/app/resources/brave_strings_eu.xtb index 2d0d7d110fd..e23ab973bb5 100644 --- a/app/resources/brave_strings_eu.xtb +++ b/app/resources/brave_strings_eu.xtb @@ -700,4 +700,5 @@ Brave-ek ezin ditu ezarpenak berreskuratu. Helbide-barran edo bilaketa-koadroan idazten duzunean, Bravek zuk idatzitakoa zure lehenetsitako bilatzaileari bidaltzen dio iradokizun hoberenak lortzeko. Hau Pribatuan itzalita dago. Brave Pribatua Modu Pribatuan nabigatzean, Bravek webgune bat konexio ez-seguru bat erabiltzen ari dela kargatu aurretik ohartaraziko zaitu. +Instalazioak huts egin du zehaztu gabeko errore batengatik. Deskargatu Brave berriro. \ No newline at end of file diff --git a/app/resources/brave_strings_fa.xtb b/app/resources/brave_strings_fa.xtb index fb80dadba3d..eb2b4435eb8 100644 --- a/app/resources/brave_strings_fa.xtb +++ b/app/resources/brave_strings_fa.xtb @@ -697,4 +697,5 @@ Brave قادر به بازیابی تنظیمات شما نیست. وقتی در نوار آدرس یا کادر جستجو تایپ می‌کنید، Brave آنچه را که تایپ می‌کنید به موتور جستجوی پیش‌فرض شما ارسال می‌کند تا پیشنهادات بهتری دریافت کند. این قابلیت در حالت «خصوصی» خاموش است. Brave خصوصی هنگام مرور صفحات در حالت خصوصی، Brave قبل از بارگیری سایت با استفاده از اتصال ناامن به شما هشدار می‌دهد. +‏به دلیل خطای نامشخص، نصب ناموفق بود. لطفاً دوباره Brave را بارگیری کنید. \ No newline at end of file diff --git a/app/resources/brave_strings_fi.xtb b/app/resources/brave_strings_fi.xtb index 826e59ad889..97b40944a92 100644 --- a/app/resources/brave_strings_fi.xtb +++ b/app/resources/brave_strings_fi.xtb @@ -699,4 +699,5 @@ Brave ei voi palauttaa asetuksiasi. Kun kirjoitat tekstiä osoitepalkkiin tai hakukenttään, Brave lähettää kirjoittamasi tekstin oletushakukoneeseesi, jotta saat parempia ehdotuksia. Tämä on pois päältä yksityisessä tilassa. Braven yksityinen tila Silloin kun selailet yksityisessä tilassa, Brave varoittaa ennen kuin lataat epävarmaa yhteyttä käyttävän sivuston. +Asennus epäonnistui määrittelemättömän virheen vuoksi. Lataa Brave uudelleen. \ No newline at end of file diff --git a/app/resources/brave_strings_fil.xtb b/app/resources/brave_strings_fil.xtb index ac37eb9daa8..36213eb2ef9 100644 --- a/app/resources/brave_strings_fil.xtb +++ b/app/resources/brave_strings_fil.xtb @@ -701,4 +701,5 @@ Hindi mabawi ng Brave ang iyong mga setting. Kapag nag-type ka sa address bar o box para sa paghahanap, ipinapadala ng Brave ang tina-type mo sa iyong default na search engine para makakuha ng mas mahuhusay na suhestyon. Naka-off ito sa Pribado. Brave Private Kapag nagba-browse sa Private mode, babalaan ka ng Brave bago mag-load ng site gamit ang isang hindi secure na koneksyon +Nabigo ang pag-install dahil sa hindi natukoy na error. Mangyaring i-download muli ang Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_fr-CA.xtb b/app/resources/brave_strings_fr-CA.xtb index 4873849014e..eeba6c396cd 100644 --- a/app/resources/brave_strings_fr-CA.xtb +++ b/app/resources/brave_strings_fr-CA.xtb @@ -700,4 +700,5 @@ Brave est incapable de récupérer vos paramètres. Lorsque vous tapez dans la barre d'adresse ou la zone de recherche, Brave envoie ce que vous saisissez à votre moteur de recherche par défaut pour obtenir de meilleures suggestions. Cette fonctionnalité est désactivée en mode de navigation privée. Navigation privée Brave Lorsque vous naviguerez en mode privé, Brave vous avertira avant de charger un site via une connexion non sécurisée +Échec de l'installation en raison d'une erreur non spécifiée. Veuillez télécharger Brave à nouveau. \ No newline at end of file diff --git a/app/resources/brave_strings_fr.xtb b/app/resources/brave_strings_fr.xtb index a447387cfae..73c90093b68 100644 --- a/app/resources/brave_strings_fr.xtb +++ b/app/resources/brave_strings_fr.xtb @@ -699,4 +699,5 @@ Brave ne peut pas récupérer vos paramètres. Lorsque vous tapez dans la barre d'adresse ou la zone de recherche, Brave envoie ce que vous saisissez à votre moteur de recherche par défaut pour obtenir de meilleures suggestions. Cette fonctionnalité est désactivée en mode de navigation privée. Navigation privée Brave Lorsque vous naviguerez en mode privé, Brave vous avertira avant de charger un site via une connexion non sécurisée +Échec de l'installation en raison d'une erreur non spécifiée. Veuillez télécharger Brave à nouveau. \ No newline at end of file diff --git a/app/resources/brave_strings_gl.xtb b/app/resources/brave_strings_gl.xtb index 733c0c7d415..dd90dfd40b5 100644 --- a/app/resources/brave_strings_gl.xtb +++ b/app/resources/brave_strings_gl.xtb @@ -698,4 +698,5 @@ Brave non pode recuperar a túa configuración. Cando escribas na barra de enderezos ou na caixa de busca, Brave enviará o que escribas ao teu motor de busca predeterminado para obter mellores suxestións. Esta opción está desactivada na opción Privado. Modo de incógnito de Brave Cando navegues no modo privado, Brave avisarate antes de cargar un sitio cunha conexión insegura +Non se puido efectuar a instalación debido a un erro. Volve descargar Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_gu.xtb b/app/resources/brave_strings_gu.xtb index 47b28a7dca4..52833cacd5b 100644 --- a/app/resources/brave_strings_gu.xtb +++ b/app/resources/brave_strings_gu.xtb @@ -698,4 +698,5 @@ Brave તમારા સેટિંગને રિકવર શકતું જ્યારે તમે ઍડ્રેસ બાર અથવા શોધ બૉક્સમાં ટાઇપ કરો છો, ત્યારે બહેતર સૂચનો મેળવવા માટે Brave તમે જે ટાઇપ કરો છો તેને તમારા ડિફૉલ્ટ શોધ એન્જિનને મોકલે છે. આ સુવિધા છૂપા મોડમાં કામ કરતી નથી. Brave છૂપો મોડ છૂપા મોડમાં બ્રાઉઝ કરતી વખતે, અસુરક્ષિત કનેક્શનનો ઉપયોગ કરીને સાઇટ લોડ કરતા પહેલાં Brave તમને ચેતવણી આપશે +અનુલ્લેખિત ભૂલને કારણે ઇન્સ્ટોલેશન નિષ્ફળ રહ્યું. કૃપા કરીને Brave ફરીથી ડાઉનલોડ કરો. \ No newline at end of file diff --git a/app/resources/brave_strings_hi.xtb b/app/resources/brave_strings_hi.xtb index ee4aa0ae362..8d2e849553e 100644 --- a/app/resources/brave_strings_hi.xtb +++ b/app/resources/brave_strings_hi.xtb @@ -695,4 +695,5 @@ Brave आपकी सेटिंग बहाल नहीं कर सकत जब आप पता बार या खोज बॉक्स में टाइप करते हैं, तो बेहतर सुझाव पाने के लिए, आप जो कुछ टाइप करते हैं Brave उसे आपके डिफ़ॉल्ट खोज इंजन पर भेजता है। यह 'निजी' में बंद रहता है। Brave प्राइवेट निजी मोड में ब्राउज़ करते समय, असुरक्षित कनेक्शन का उपयोग करके साइट लोड करने से पहले Brave आपको चेतावनी देगा +अनिर्दिष्ट कारणों से इंस्‍टॉलेशन विफल हुआ. कृपया Brave फिर से डाउनलोड करें. \ No newline at end of file diff --git a/app/resources/brave_strings_hr.xtb b/app/resources/brave_strings_hr.xtb index 3049074cc98..f85226e3582 100644 --- a/app/resources/brave_strings_hr.xtb +++ b/app/resources/brave_strings_hr.xtb @@ -700,4 +700,5 @@ Brave ne može oporaviti vaše postavke. Kada upisujete u adresnu traku ili okvir za pretraživanje, Brave šalje što upisujete zadanoj tražilici za dobivanje boljih prijedloga. To je isključeno u privatnom načinu rada. Privatni način rada preglednika Brave Kada pregledavate u privatnom načinu rada, Brave će vas upozoriti prije učitavanja stranice uporabom nesigurne veze +Instalacija nije uspjela zbog nepoznate pogreške. Ponovo preuzmite Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_hu.xtb b/app/resources/brave_strings_hu.xtb index 449fc7accc9..dc6c71d913c 100644 --- a/app/resources/brave_strings_hu.xtb +++ b/app/resources/brave_strings_hu.xtb @@ -697,4 +697,5 @@ A Brave nem tudja visszaállítani a beállításait. Amikor szöveget ír a címsávba vagy keresőmezőbe, a Brave elküldi a beírt szöveget az alapértelmezett keresőmotornak a javaslatok fejlesztése érdekében. Ez Privát módban ki van kapcsolva. Brave privát mód Amikor Privát módban böngészik, a Brave figyelmeztetni fogja Önt, mielőtt betöltene egy nem biztonságos kapcsolatot használó oldalt +A telepítés egy meg nem határozott hiba miatt nem sikerült. Kérjük, töltse le újra a Braveot. \ No newline at end of file diff --git a/app/resources/brave_strings_hy.xtb b/app/resources/brave_strings_hy.xtb index c5e694a87a5..bb08fa93ad5 100644 --- a/app/resources/brave_strings_hy.xtb +++ b/app/resources/brave_strings_hy.xtb @@ -698,4 +698,5 @@ Brave-ին չհաջողվեց վերականգնել ձեր կարգավորու Ձեր տեղադրության տվյալներն օգտագործելու համար Brave-ին թույլտվություն տրամադրեք համակարգի կարգավորումներում Google Chrome Բետա Google Chrome Dev +Անհայտ սխալի պատճառով տեղադրումը չհաջողվեց: Նորից ներբեռնեք Brave-ը: \ No newline at end of file diff --git a/app/resources/brave_strings_id.xtb b/app/resources/brave_strings_id.xtb index ab9df5289db..524cb9dffef 100644 --- a/app/resources/brave_strings_id.xtb +++ b/app/resources/brave_strings_id.xtb @@ -699,4 +699,5 @@ Brave tidak dapat memulihkan setelan Anda. Ketika Anda mengetik di bilah alamat atau kotak pencarian, Brave mengirim hal yang Anda ketik ke mesin pencarian bawaan Anda untuk mendapatkan usulan yang lebih baik. Ini dinonaktifkan di mode Privat. Privat Brave Saat meramban dalam mode Privat, Brave akan memperingatkan Anda sebelum memuat situs dengan menggunakan koneksi yang tidak aman +Pemasangan gagal karena kesalahan yang tidak ditentukan. Download Brave lagi. \ No newline at end of file diff --git a/app/resources/brave_strings_is.xtb b/app/resources/brave_strings_is.xtb index a19a67be3ca..c51ac023a73 100644 --- a/app/resources/brave_strings_is.xtb +++ b/app/resources/brave_strings_is.xtb @@ -698,4 +698,5 @@ Brave getur ekki endurheimt stillingarnar þínar. Veittu Brave aðgang að staðsetningunni þinni í kerfisstillingum til að geta notað hana Google Chrome Beta Google Chrome Dev +Uppsetning mistókst vegna ótilgreindrar villu. Sæktu Brave aftur. \ No newline at end of file diff --git a/app/resources/brave_strings_it.xtb b/app/resources/brave_strings_it.xtb index 0baa9e93c56..39734e54a64 100644 --- a/app/resources/brave_strings_it.xtb +++ b/app/resources/brave_strings_it.xtb @@ -698,4 +698,5 @@ Brave non è in grado di recuperare le impostazioni. Quando digiti qualcosa nella barra degli indirizzi o nella casella di ricerca, Brave invia il testo digitato al tuo motore di ricerca predefinito per ottenere suggerimenti migliori. Questa opzione è disattivata nella modalità privata. Modalità privata Brave Navigando in modalità privata, riceverai un avviso da Brave prima di caricare un sito tramite una connessione non sicura +Installazione non riuscita a causa di un errore imprecisato. Scarica di nuovo Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_iw.xtb b/app/resources/brave_strings_iw.xtb index 1ca4c3df876..f04a9756b2a 100644 --- a/app/resources/brave_strings_iw.xtb +++ b/app/resources/brave_strings_iw.xtb @@ -697,4 +697,5 @@ Brave לא יכול לשחזר את ההגדרות שלך. כשאתה מקליד בשורת הכתובת או בתיבת החיפוש, Brave שולח את מה שאתה מקליד למנוע החיפוש המוגדר כברירת מחדל כדי לקבל הצעות טובות יותר. זה לא פעיל בפרטי. פרטי אמיץ בעת גלישה במצב פרטי, Brave תזהיר אותך לפני טעינת אתר המשתמש בחיבור לא מאובטח +‏ההתקנה נכשלה בשל שגיאה לא מזוהה. יש להוריד שוב את Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_ja.xtb b/app/resources/brave_strings_ja.xtb index 90325fef368..4d75afc4f26 100644 --- a/app/resources/brave_strings_ja.xtb +++ b/app/resources/brave_strings_ja.xtb @@ -689,4 +689,5 @@ アドレスバーや検索ボックスに文字を入力すると、Braveは入力した文字をデフォルトの検索エンジンに送信し、より良い候補を取得します。これはプライベートではオフになっています。 Braveプライベートモード プライベートモードでブラウザを利用している場合、安全でない接続を使用してサイトを読み込む前にBraveが警告を表示します +原因不明のエラーによりインストールに失敗しました。Brave をもう一度ダウンロードしてください。 \ No newline at end of file diff --git a/app/resources/brave_strings_ka.xtb b/app/resources/brave_strings_ka.xtb index c1d6bc22feb..15cfafd15e2 100644 --- a/app/resources/brave_strings_ka.xtb +++ b/app/resources/brave_strings_ka.xtb @@ -710,4 +710,5 @@ other {Brave-ის განახლებული ვერსია უკ მისამართის ან საძიებო ველში აკრეფილ ტექსტს Brave თქვენს ნაგულისხმევ საძიებო სისტემაში აგზავნის, რათა უკეთესი შეთავაზებები მიიღოთ. პირად რეჟიმში ეს ფუნქცია ავტომატურად გათიშულია. Brave Private როდესაც ბრაუზინგს კონფიდენციალურ რეჟიმში ახორციელებთ, Brave წინასწარ შეგატყობინებთ, თუკი საიტი საეჭვო კავშირზე ცდილობს ჩატვირთვას +ინსტალაცია ვერ განხორციელდა გაურკვეველი შეცდომის გამო. ხელახლა ჩამოტვირთეთ Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_kk.xtb b/app/resources/brave_strings_kk.xtb index 92bc2d43fee..da7d45d63ec 100644 --- a/app/resources/brave_strings_kk.xtb +++ b/app/resources/brave_strings_kk.xtb @@ -706,4 +706,5 @@ Brave параметрлеріңізді қалпына келтіре алма Мекенжай жолағына немесе іздеу жолағына тергенде, Brave сіздің әдепкі іздеу жүйеңізге жақсы ұсыныстар алу үшін мәтінді жібереді. Бұл Жеке режимде өшірулі. Brave Private Жеке режимде шолу жасағанда, Brave жүйесі қауіпсіз емес қосылымды пайдаланып сайтты жүктеуден бұрын ескертеді. +Орнату анықталмаған қате себебінен сәтсіз аяқталды. Brave браузерін қайта жүктеңіз. \ No newline at end of file diff --git a/app/resources/brave_strings_km.xtb b/app/resources/brave_strings_km.xtb index f8650778856..c922d594191 100644 --- a/app/resources/brave_strings_km.xtb +++ b/app/resources/brave_strings_km.xtb @@ -698,4 +698,5 @@ Brave មិនអាចសង្គ្រោះការកំណត់រប នៅពេលអ្នកវាយក្នុងបារទីតាំងឬប្រអប់ស្វែងរក Brave នឹងផ្ញើអ្វីដែលអ្នកវាយទៅម៉ាស៊ីនស្វែងរកលំនាំដើមរបស់អ្នកដើម្បីទទួលបានការណែនាំល្អប្រសើរជាងមុន។ នេះត្រូវបានបិទក្នុងផ្នែកឯកជន។ Brave Private នៅពេលរុករកក្នុងរបៀបឯកជន Brave នឹងព្រមានអ្នកមុនពេលផ្ទុកវេបសាយដែលប្រើការតភ្ជាប់មិនមានសុវត្ថិភាព +ការតំឡើងបានបរាជ័យដោយសារកំហុសឆ្គងដែលមិនជាក់លាក់។ សូមទាញយក Brave ម្តងទៀត។ \ No newline at end of file diff --git a/app/resources/brave_strings_kn.xtb b/app/resources/brave_strings_kn.xtb index 75d98ece03c..8b6d1226eb2 100644 --- a/app/resources/brave_strings_kn.xtb +++ b/app/resources/brave_strings_kn.xtb @@ -690,4 +690,5 @@ ನೀವು ವಿಳಾಸ ಬಾರ್ ಅಥವಾ ಹುಡುಕಾಟ ಬಾಕ್ಸ್‌ನಲ್ಲಿ ಟೈಪ್ ಮಾಡಿದಾಗ, ಉತ್ತಮ ಸಲಹೆಗಳನ್ನು ಪಡೆಯುವುದಕ್ಕಾಗಿ ನೀವು ಟೈಪ್ ಮಾಡುವುದನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಹುಡುಕಾಟ ಇಂಜಿನ್‌ಗೆ Brave ಕಳುಹಿಸುತ್ತದೆ. ಇದು ಖಾಸಗಿ ಎಂಬಲ್ಲಿ ಆಫ್ ಆಗಿದೆ. Brave ಖಾಸಗಿ ಖಾಸಗಿ ಮೋಡ್‌ನಲ್ಲಿ ಬ್ರೌಸಿಂಗ್ ಮಾಡುವಾಗ, ಅಸುರಕ್ಷಿತ ಸಂಪರ್ಕವನ್ನು ಬಳಸಿಕೊಂಡು ಸೈಟ್ ಅನ್ನು ಲೋಡ್ ಮಾಡುವುದಕ್ಕೂ ಮೊದಲು Brave ನಿಮ್ಮನ್ನು ಎಚ್ಚರಿಸುತ್ತದೆ +ಅನಿರ್ದಿಷ್ಟ ದೋಷದಿಂದಾಗಿ ಸ್ಥಾಪನೆ ವಿಫಲವಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೊಮ್ಮೆ Brave ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ. \ No newline at end of file diff --git a/app/resources/brave_strings_ko.xtb b/app/resources/brave_strings_ko.xtb index c9057e76959..fe12af96589 100644 --- a/app/resources/brave_strings_ko.xtb +++ b/app/resources/brave_strings_ko.xtb @@ -700,4 +700,5 @@ Brave에서 설정을 복구할 수 없습니다. 주소창이나 검색창에 입력하면 입력하신 내용을 Brave가 기본 검색 엔진으로 보내 추천 결과를 개선합니다. 비공개 모드에서는 꺼집니다. Brave Private 비공개 모드로 탐색 중에 비보안 연결을 사용하는 사이트에 진입하면 로드 전에 Brave가 경고합니다. +알 수 없는 오류로 인해 설치에 실패했습니다. Brave을 다시 다운로드하세요. \ No newline at end of file diff --git a/app/resources/brave_strings_ky.xtb b/app/resources/brave_strings_ky.xtb index eaa02eea6b2..f30676a53ad 100644 --- a/app/resources/brave_strings_ky.xtb +++ b/app/resources/brave_strings_ky.xtb @@ -698,4 +698,5 @@ Brave параметрлериңизди калыбына келтире алб Жүргөн жерди колдонуу үчүн Brave'га системанын параметрлеринен кирүүгө уруксат бериңиз Google Chrome Бета Google Chrome Dev +Белгиси катадан улам, орнотулбай калды. Brave'ду кайра жүктөп алыңыз. \ No newline at end of file diff --git a/app/resources/brave_strings_lo.xtb b/app/resources/brave_strings_lo.xtb index 28edf0f01b1..e7f8fd575f3 100644 --- a/app/resources/brave_strings_lo.xtb +++ b/app/resources/brave_strings_lo.xtb @@ -698,4 +698,5 @@ Brave ບໍ່ສາມາດກູ້ການຕັ້ງຄ່າຂອງ ເມື່ອທ່ານພິມຢູ່ໃນບີນທີ່ທິດສຳລະທີ່ຢູ່ຕ່ຳຂອງທ່ານ, Brave ຈະສົ່ງມູນທີ່ທ່ານພີລາຍນັ້ປານທເຮັບໃຫ້ທິດສຳລະທີ່ຕັ້ງໂຂມາດເພື້ອໃຫ້ລາຍໄດ້ດີ. ໃຊ້ງານໄດ້. ແທການ Brave Private ເມື່ອເຊີມມູນໃນເ້ບສ່ວນຕົວ, Brave ຈະກາຍຫຼືວາເຕືອນກ່ຽວກັນໃກ້ເປັນໃນພຽງໃກ້ +ການ​ຕິດ​ຕັ້ງ​ບໍ່​ສໍາ​ເລັດ ​ເນື່ອງ​ຈາກ​ຄວາມຜິດພາດທີ່ບໍ່ໄດ້ລະບຸ​. ກະ​ລຸ​ນາ​ດາວ​ໂຫລດ Brave ອີກ​. \ No newline at end of file diff --git a/app/resources/brave_strings_lt.xtb b/app/resources/brave_strings_lt.xtb index 0b4779b8dad..001ef7c989e 100644 --- a/app/resources/brave_strings_lt.xtb +++ b/app/resources/brave_strings_lt.xtb @@ -701,4 +701,5 @@ Kai kurios funkcijos gali būti nepasiekiamos. Nurodykite kitą profilio katalog Siekiant užtikrinti, kad gausite tinkamiausius pasiūlymus, užklausa, kurią įvedate adreso juostoje arba paieškos lauke, perduodama numatytajai paieškos sistemai. Ši funkcija išjungta naršant privačiuoju režimu. „Brave“ inkognito Naršant inkognito režimu, prieš įkeliant svetainę, kurioje naudojamas nesaugus ryšys, „Brave“ jus įspės +Nepavyko įdiegti dėl nenurodytos klaidos. Atsisiųskite „Brave“ dar kartą. \ No newline at end of file diff --git a/app/resources/brave_strings_lv.xtb b/app/resources/brave_strings_lv.xtb index 6e3381666d3..a7a66b18b6c 100644 --- a/app/resources/brave_strings_lv.xtb +++ b/app/resources/brave_strings_lv.xtb @@ -705,4 +705,5 @@ other {Lai lietotu atjauninājumu, administrators pieprasa restartēt pārlūku Kad rakstāt adreses joslā vai meklēšanas lodziņā, to, ko rakstāt, Brave nosūta uz jūsu noklusējuma meklētājprogrammu, lai iegūtu labākus ieteikumus. Inkognito režīmā šī opcija ir izslēgta. Brave inkognito Pārlūkojot privātajā režīmā, Brave brīdinās jūs pirms vietnes ielādes, izmantojot nedrošu savienojumu +Instalēšana neizdevās nenoteiktas kļūdas dēļ. Lejupielādējiet pārlūku Brave vēlreiz. \ No newline at end of file diff --git a/app/resources/brave_strings_mk.xtb b/app/resources/brave_strings_mk.xtb index a0a64c3d514..f0281956299 100644 --- a/app/resources/brave_strings_mk.xtb +++ b/app/resources/brave_strings_mk.xtb @@ -698,4 +698,5 @@ Brave не може да ги обнови вашите поставки.Кога пишувате во адресната лента или полето за пребарување, Brave го испраќа напишаното до вашиот стандардно пребарувач за да добиете подобри предлози. Ова е оневозможено во Приватниот режим. Brave Приватен Кога пребарувате во Приватниот режим, Brave ќе ве предупредува пред да вчита сајт со несигурна врска +Инсталирањето не успеа поради неназначена грешка. Преземете го Brave повторно. \ No newline at end of file diff --git a/app/resources/brave_strings_ml.xtb b/app/resources/brave_strings_ml.xtb index d6f5a471abb..29f8d8cf3a8 100644 --- a/app/resources/brave_strings_ml.xtb +++ b/app/resources/brave_strings_ml.xtb @@ -698,4 +698,5 @@ നിങ്ങൾ വിലാസ ബാറിലോ സെർച്ച് ബോക്‌സിലോ ടൈപ്പ് ചെയ്യുമ്പോൾ, മികച്ച നിർദ്ദേശങ്ങൾ ലഭിക്കുന്നതിന് ടൈപ്പ് ചെയ്യുന്നതെന്തോ അത് Brave നിങ്ങളുടെ ഡിഫോൾട്ട് തിരയൽ യന്ത്രത്തിലേക്ക് അയയ്ക്കുന്നു. ഇത് അദൃശ്യ മോഡിൽ ഓഫാണ്. Brave അദൃശ്യ മോഡ് അദൃശ്യ മോഡിൽ ബ്രൗസ് ചെയ്യുമ്പോൾ, സുരക്ഷിതമല്ലാത്ത കണക്ഷൻ ഉപയോഗിച്ച് ഒരു സൈറ്റ് ലോഡ് ചെയ്യുന്നതിന് മുമ്പ് Brave നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകും +അവ്യക്തമായ പിശകിനാൽ ഇൻസ്റ്റാൾ ചെയ്യൽ പരാജയപ്പെട്ടു. Brave വീണ്ടും ഡൗൺലോഡ് ചെയ്യുക. \ No newline at end of file diff --git a/app/resources/brave_strings_mn.xtb b/app/resources/brave_strings_mn.xtb index b639a79273c..73b044dd422 100644 --- a/app/resources/brave_strings_mn.xtb +++ b/app/resources/brave_strings_mn.xtb @@ -694,4 +694,5 @@ Та хаягийн баар эсвэл хайлтын хайрцагт бичих үед Brave таны хайлтны илүү сайн санал авахын тулд таны бичсэн зүйлээ үндсэн хайлтын системд явуулдаг. Энэ нь Нууцлалтай горимд идэвхгүй. Brave Нууцлалтай Нууцлалтай горимоор интернет үзэх үед Brave аюулгүй бус холболттой сайтыг ачаалахаас өмнө танд анхааруулга өгнө. +Гэнэтийн алдаанаас болж суулгах ажиллагаа амжилтгүй боллоо. Brave-ыг дахин татаж авна уу. \ No newline at end of file diff --git a/app/resources/brave_strings_mr.xtb b/app/resources/brave_strings_mr.xtb index ec2523d7128..aa043e65472 100644 --- a/app/resources/brave_strings_mr.xtb +++ b/app/resources/brave_strings_mr.xtb @@ -697,4 +697,5 @@ Brave तुमची सेटिंग्ज रिकव्हर करू तुम्ही अ‍ॅड्रेस बार किंवा सर्च बॉक्समध्ये टाइप करता, तेव्हा अधिक चांगल्या सूचना मिळवण्यासाठी तुम्ही जे टाइप करता ते Brave तुमच्या डीफॉल्ट शोध इंजीनला पाठवते. हे गुप्त मोड मध्ये बंद आहे. Brave चा गुप्त मोड गुप्त मोडमध्ये ब्राउझ करताना, असुरक्षित कनेक्शन वापरून साइट लोड करण्यापूर्वी Brave तुम्हाला चेतावणी देईल +नमूद न केलेल्या एररमुळे स्थापना अयशस्वी झाली. कृपया Brave पुन्‍हा डाउनलोड करा. \ No newline at end of file diff --git a/app/resources/brave_strings_ms.xtb b/app/resources/brave_strings_ms.xtb index 5d6372ace16..e5c0041334d 100644 --- a/app/resources/brave_strings_ms.xtb +++ b/app/resources/brave_strings_ms.xtb @@ -696,4 +696,5 @@ Brave tidak dapat mengembalikan tetapan anda. Apabila anda menaipkan maklumat ke dalam bar alamat atau kotak carian, Brave menghantar maklumat yang anda taipkan kepada enjin carian lalai anda untuk mendapatkan cadangan lebih baik. Ciri ini dimatikan dalam penyemak imbas Peribadi. Brave Private Apabila menyemak imbas dalam mod Peribadi, Brave akan memberikan amaran kepada anda sebelum memuatkan sesuatu laman menggunakan sambungan yang tidak selamat +Pemasangan gagal disebabkan ralat yang tidak dinyatakan. Sila muat turun semula Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_my.xtb b/app/resources/brave_strings_my.xtb index dbc4b5d1fd9..f4e5a76de1e 100644 --- a/app/resources/brave_strings_my.xtb +++ b/app/resources/brave_strings_my.xtb @@ -706,4 +706,5 @@ Brave သည်သင့်ကြိုတင်ချိန်ညှိချ သင့်လိပ်စာသို့ရှာဖွေပါမည်- Brave Private Private mode မွ browsing ဆောင်ရွက်နေစဉ် Brave သည် ဖွေလုံးများမတင်မသင့်ဖြစ်သည့် site အသားစများကို မရှိမဖြစ်ပေးပြီးမတင်မနိူင်သော +မသိရသည့် အမှားတစ်ခုကြောင့် တပ်ဆင်မှု မအေင်မြင်ခဲ့ပါ။ ကျေးဇူးပြုပြီး Brave ကို ထပ်ပြီး ဒေါင်းလုဒ် လုပ်ယူပါ။ \ No newline at end of file diff --git a/app/resources/brave_strings_ne.xtb b/app/resources/brave_strings_ne.xtb index cc1dbc1da77..c179c0ad0b6 100644 --- a/app/resources/brave_strings_ne.xtb +++ b/app/resources/brave_strings_ne.xtb @@ -696,4 +696,5 @@ Brave ले तपाइँका सेटिङहरू पुनर्प जब तपाई‍ले ठेगाना बार वा खोजी बक्समा टाइप गर्नुहुन्छ, Brave थप सुझावहरू प्राप्त गर्न तपाईंले टाइप गर्नु भएको कुरा तपाईँको डिफल्ट खोज इन्जिनमा पठाउँछ। यो निजि मोडमा बन्द हुन्छ। Brave निजि निजि मोडमा ब्राउजिङ गर्दा, Brave ले असुरक्षित जडान प्रयोग गर्ने साइट लोड गर्नु अघि तपाईंलाई चेतावनी दिनेछ। +अनिश् \ No newline at end of file diff --git a/app/resources/brave_strings_nl.xtb b/app/resources/brave_strings_nl.xtb index d11228cce1f..491b1356cf3 100644 --- a/app/resources/brave_strings_nl.xtb +++ b/app/resources/brave_strings_nl.xtb @@ -700,4 +700,5 @@ Brave kan je instellingen niet herstellen. Wanneer u iets in de adresbalk of het zoekveld typt, stuurt Brave dat naar uw standaard zoekmachine voor betere suggesties. Dit is uitgeschakeld in Privé. Brave Privé Wanneer u in privémodus surft, zal Brave u waarschuwen voordat u een site laadt met een onveilige verbinding +De installatie is mislukt wegens een onbekende fout. Download Brave opnieuw. \ No newline at end of file diff --git a/app/resources/brave_strings_no.xtb b/app/resources/brave_strings_no.xtb index a4efadfee0c..bf7ed4628f9 100644 --- a/app/resources/brave_strings_no.xtb +++ b/app/resources/brave_strings_no.xtb @@ -696,4 +696,5 @@ Brave kan ikke gjenopprette innstillingen dine. Når du skriver i adressefeltet eller søkefeltet, sender Brave det du skriver inn, til søkemotoren du har som standard, for å få opp bedre forslag. Dette er deaktivert i Privat modus. Brave Privat Når du surfer i Privat modus, advarer Brave deg før det lastes opp sider via usikre tilkoblinger +Installeringen mislyktes på grunn av en uspesifisert feil. Last ned Brave på nytt. \ No newline at end of file diff --git a/app/resources/brave_strings_or.xtb b/app/resources/brave_strings_or.xtb index dff78ffd302..88977cdee20 100644 --- a/app/resources/brave_strings_or.xtb +++ b/app/resources/brave_strings_or.xtb @@ -697,4 +697,5 @@ Brave ଆପଣଙ୍କ ସେଟିଂସ୍‌କୁ ପୁନରୁଦ୍ଧ ଆପଣଙ୍କ ଲୋକେସନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ସିଷ୍ଟମ ସେଟିଂସରେ Braveକୁ ଆକ୍ସେସ ଦିଅନ୍ତୁ Google Chrome ବିଟା Google Chrome ଡେଭ୍‍ +ଅନିର୍ଦ୍ଦିଷ୍ଟ ତ୍ରୁଟି ଯୋଗୁଁ ଇନ୍‌ଷ୍ଟଲେସନ୍ ବିଫଳ ହୋଇଛି। ଦୟାକରି Brave ପୁଣି ଡାଉନ୍‌ଲୋଡ୍ କରନ୍ତୁ। \ No newline at end of file diff --git a/app/resources/brave_strings_pa.xtb b/app/resources/brave_strings_pa.xtb index 3275db3b5e2..b0516db1c1e 100644 --- a/app/resources/brave_strings_pa.xtb +++ b/app/resources/brave_strings_pa.xtb @@ -698,4 +698,5 @@ Brave ਤੁਹਾਡੀਆਂ ਸੈਟਿੰਗਾਂ ਮੁੜ-ਹਾਸਲ ਜਦੋਂ ਤੁਸੀਂ ਪਤੇ ਦੀ ਪੱਟੀ ਜਾਂ ਖੋਜ ਬਾਕਸ ਵਿੱਚ ਟਾਈਪ ਕਰਦੇ ਹੋ, Brave ਤੁਹਾਡੇ ਜੋ ਕੁਝ ਤੁਸੀਂ ਟਾਈਪ ਕਰਦੇ ਹੋ ਉਸ ਨੂੰ ਚੰਗੇ ਸੁਝਾਅ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਡਿਫਾਲਟ ਖੋਜ ਇੰਜਣ ਨੂੰ ਭੇਜਦਾ ਹੈ। ਇਹ ਨਿੱਜੀ ਵਿੱਚ ਬੰਦ ਹੈ। Brave Private ਨਿੱਜੀ ਮੋਡ ਵਿੱਚ ਬਰਾਊਜ਼ਿੰਗ ਕਰਦੇ ਸਮੇਂ, Brave ਅਸੁਰੱਖਿਅਤ ਕਨੈਕਸ਼ਨ ਦੀ ਵਰਤੋਂ ਰਲਾਉਣ ਤੋਂ ਪਹਿਲਾਂ ਤੁਹਾਨੂੰ ਚੇਤਾਵਨੀ ਦੇਵੇਗਾ। +ਅਨਿਸ਼ਚਿਤ ਗੜਬੜ ਕਾਰਨ ਸਥਾਪਨਾ ਅਸਫਲ ਹੋ ਗਈ। ਕਿਰਪਾ ਕਰਕੇ Brave ਨੂੰ ਦੁਬਾਰਾ ਡਾਊਨਲੋਡ ਕਰੋ। \ No newline at end of file diff --git a/app/resources/brave_strings_pl.xtb b/app/resources/brave_strings_pl.xtb index 146dd6d0c87..d850401f9ca 100644 --- a/app/resources/brave_strings_pl.xtb +++ b/app/resources/brave_strings_pl.xtb @@ -696,4 +696,5 @@ Brave nie może odzyskać ustawień. Kiedy wpisujesz tekst w pasku adresu lub polu wyszukiwania, Brave wysyła wpisywany tekst do domyślnej wyszukiwarki w celu uzyskania lepszych wyników. Ta funkcja jest wyłączona w przeglądaniu prywatnym. Tryb prywatny Brave Przeglądając strony w trybie prywatnym, otrzymasz ostrzeżenie od Brave, kiedy ładowana strona korzysta z niezabezpieczonego połączenia +Instalacja nie powiodła się z powodu nieokreślonego błędu. Pobierz Brave ponownie. \ No newline at end of file diff --git a/app/resources/brave_strings_pt-BR.xtb b/app/resources/brave_strings_pt-BR.xtb index f7e141e1582..5c8ca922e49 100644 --- a/app/resources/brave_strings_pt-BR.xtb +++ b/app/resources/brave_strings_pt-BR.xtb @@ -696,4 +696,5 @@ Quando você digita na barra de endereços ou na caixa de pesquisa, o Brave envia o que você digita para o mecanismo de pesquisa padrão para obter melhores sugestões. Isso está desativado em Privado. Modo privado do Brave Ao navegar no modo Privado, o Brave avisa você antes de carregar um site utilizando uma conexão não segura +Falha na instalação devido a um erro não especificado. Baixe o Brave novamente. \ No newline at end of file diff --git a/app/resources/brave_strings_pt-PT.xtb b/app/resources/brave_strings_pt-PT.xtb index aba3cc8e16c..5a3ce9e3313 100644 --- a/app/resources/brave_strings_pt-PT.xtb +++ b/app/resources/brave_strings_pt-PT.xtb @@ -699,4 +699,5 @@ O Brave não consegue recuperar as suas definições. Quando introduz alguma coisa na barra de endereços ou na caixa de pesquisa, o Brave envia o que introduziu para o seu motor de busca padrão para ter sugestões melhores. Esta configuração está desativada no modo privado. Modo privado do Brave Ao navegar no modo Privado, o Brave avisa-o antes de carregar um site utilizando uma ligação não segura +A instalação falhou devido a um erro não especificado. Descarregue novamente o Brave . \ No newline at end of file diff --git a/app/resources/brave_strings_ro.xtb b/app/resources/brave_strings_ro.xtb index 9021128e4a1..f5929314906 100644 --- a/app/resources/brave_strings_ro.xtb +++ b/app/resources/brave_strings_ro.xtb @@ -699,4 +699,5 @@ Brave nu poate recupera setările. Când tastați în bara de adrese sau în caseta de căutare, Brave trimite ceea ce tastați către motorul de căutare implicit pentru a obține sugestii mai bune. Acest lucru este dezactivat în privat. Brave Private Când răsfoiți în modul Privat, Brave vă va avertiza înainte de a încărca un site care folosește o conexiune nesecurizată. +Instalarea nu a reușit din cauza unei erori neprecizate. Descărcați Brave din nou. \ No newline at end of file diff --git a/app/resources/brave_strings_ru.xtb b/app/resources/brave_strings_ru.xtb index 93e32a53c19..8145c395987 100644 --- a/app/resources/brave_strings_ru.xtb +++ b/app/resources/brave_strings_ru.xtb @@ -694,4 +694,5 @@ Когда вы набираете текст в адресной строке или в поле поиска, Brave отправляет его в поисковую систему по умолчанию, чтобы получить лучшие предложения. В режиме «‎Приватный» эта функция отключена. Приватный режим Brave Когда вы находитесь в браузере в приватном режиме, Brave предупредит вас перед загрузкой сайта с небезопасным соединением +В процессе установки произошла неизвестная ошибка. Скачайте Brave ещё раз. \ No newline at end of file diff --git a/app/resources/brave_strings_si.xtb b/app/resources/brave_strings_si.xtb index 0214758b4ca..15cb3d8d31f 100644 --- a/app/resources/brave_strings_si.xtb +++ b/app/resources/brave_strings_si.xtb @@ -709,4 +709,5 @@ Brave හට ඔබගේ සැකසුම් ප්‍රතිසාධන ඔබ ලිපින තීරුවේ හෝ සෙවුම් කොටුවේ ලියන විට වඩා හොඳ යෝජනා ලබා ගැනීමට Brave ඔබ ලියන දෑ ඔබගේ පෙරනිමි සෙවුම් යන්ත්‍රයට යවයි. මෙය පෞද්ගලික ප්‍රකාරයේ අක්‍රියයි. Brave පෞද්ගලික පෞද්ගලික ප්‍රකාරයේ පිරික්සන විට අනාරක්ෂිත සම්බන්ධතාවයකින් අඩවියක් පූරණයට පෙර Brave ඔබට අනතුරු අඟවයි +නිශ්චිත නොමැති දෝෂයක් හේතුවෙන් ස්ථාපනය අසාර්ථක විය. නැවතත් Brave බාගන්න. \ No newline at end of file diff --git a/app/resources/brave_strings_sk.xtb b/app/resources/brave_strings_sk.xtb index 16e251460f6..d5efea94907 100644 --- a/app/resources/brave_strings_sk.xtb +++ b/app/resources/brave_strings_sk.xtb @@ -700,4 +700,5 @@ Prehliadač Brave nedokáže obnoviť vaše nastavenia. Pri písaní do adresného riadka alebo vyhľadávacieho poľa posiela Brave vložený text vášmu predvolenému vyhľadávaču, čím získate lepšie návrhy. Táto možnosť je v súkromnom režime vypnutá. Brave Private Pri prehliadaní v súkromnom režime vás aplikácia Brave upozorní pred načítaním stránky prostredníctvom nezabezpečeného pripojenia. +Inštalácia zlyhala kvôli neznámej chybe. Skúste prehliadač Brave stiahnuť znova. \ No newline at end of file diff --git a/app/resources/brave_strings_sl.xtb b/app/resources/brave_strings_sl.xtb index 3b1b0cae220..ce3553d8821 100644 --- a/app/resources/brave_strings_sl.xtb +++ b/app/resources/brave_strings_sl.xtb @@ -701,4 +701,5 @@ Brave ne more obnoviti vaših nastavitev. Ko v naslovno vrstico ali iskalno polje vtipkate besedilo, Brave vneseno besedilo pošlje vašemu privzetemu iskalniku, da tako dobi boljše predloge. Ta funkcija je v zasebnem načinu izključena. Brave Private Ko brskate v zasebnem načinu, vas Brave opozori pred nalaganjem spletnega mesta prek nezanesljive povezave. +Namestitev ni uspela zaradi nenavedene napake. Znova prenesite Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_sq.xtb b/app/resources/brave_strings_sq.xtb index fd940c6fcec..20c5bbb981b 100644 --- a/app/resources/brave_strings_sq.xtb +++ b/app/resources/brave_strings_sq.xtb @@ -700,4 +700,5 @@ Brave nuk është në gjendje të rikuperojë cilësimet e tua. Kur shkruani në shiritin e adresave apo kutinë e kërkimit, Brave dërgon atë që shkruani tek motori juaj i paracaktuar i kërkimit për të marrë sugjerime më të mira. Kjo është e çaktivizuar në Private. Brave Private Kur shfletoni në modalitetin Private, Brave do t'ju paralajmërojë para se të ngarkojë një sajt që përdor një lidhje të pasigurtë +Instalimi dështoi për shkak të një gabimi të papërcaktuar. Shkarko përsëri Brave. \ No newline at end of file diff --git a/app/resources/brave_strings_sr-Latn.xtb b/app/resources/brave_strings_sr-Latn.xtb index c313731dfb5..ad326f004e0 100644 --- a/app/resources/brave_strings_sr-Latn.xtb +++ b/app/resources/brave_strings_sr-Latn.xtb @@ -707,4 +707,5 @@ Brave ne može da vrati podešavanja. Kada kucate u traku za adresu ili polje za pretragu, Brave šalje to što unosite u vaš podrazumevani pretraživač da biste dobili bolje predloge. To je isključeno u privatnom režimu. Brave – privatni režim Kada pregledate u privatnom režimu, Brave će vas upozoriti pre nego što učitate sajt preko nebezbedne veze +Instalacija nije uspela zbog neodređene greške. Preuzmite Brave ponovo. \ No newline at end of file diff --git a/app/resources/brave_strings_sr.xtb b/app/resources/brave_strings_sr.xtb index 79f807d25db..0107683e933 100644 --- a/app/resources/brave_strings_sr.xtb +++ b/app/resources/brave_strings_sr.xtb @@ -698,4 +698,5 @@ Brave не може да врати подешавања. Да бисте користили локацију, одобрите Brave-у приступ у подешавањима система Google Chrome бета Програмерска верзија Google Chrome-а +Инсталација није успела због неодређене грешке. Преузмите Браве поново. \ No newline at end of file diff --git a/app/resources/brave_strings_sv.xtb b/app/resources/brave_strings_sv.xtb index d7112ee6423..f8f3451df58 100644 --- a/app/resources/brave_strings_sv.xtb +++ b/app/resources/brave_strings_sv.xtb @@ -701,4 +701,5 @@ Brave kan inte återställa dina inställningar. När du skriver i adressfältet eller sökrutan skickas det du skriver till din standardsökmotor för att du ska få bättre förslag. Detta är avstängt i Privat läge. Brave privat När du surfar i privat läge varnar Brave dig innan du laddar en webbplats med en osäker anslutning +Installationen misslyckades på grund av ett okänt fel. Ladda ned Brave igen. \ No newline at end of file diff --git a/app/resources/brave_strings_sw.xtb b/app/resources/brave_strings_sw.xtb index 07af2d48e1e..457a22ffe0f 100644 --- a/app/resources/brave_strings_sw.xtb +++ b/app/resources/brave_strings_sw.xtb @@ -698,4 +698,5 @@ Brave haiwezi kufufua mipangilio yako. Unapoandika kwenye upau wa anwani au kisanduku cha utafutaji, Brave hutuma unachoandika kwenye injini yako chaguomsingi ya utafutaji ili kupata mapendekezo bora zaidi. Hili limezimwa katika Faragha. Brave ya Faragha Unapovinjari katika modi ya faragha, Brave itakupa onyo kabla ya kupakia tovuti kwa kutumia muunganisho usio salama +Usakinishaji ulishindwa kwa sababu ya hitilafu isiyobainika. Tafadhali pakua Brave tena. \ No newline at end of file diff --git a/app/resources/brave_strings_ta.xtb b/app/resources/brave_strings_ta.xtb index 58fccd2561d..7a0a28e162e 100644 --- a/app/resources/brave_strings_ta.xtb +++ b/app/resources/brave_strings_ta.xtb @@ -696,4 +696,5 @@ முகவரிப் பட்டியிலோ தேடல் பெட்டியிலோ நீங்கள் டைப்செய்யும்போது, சிறப்பான பரிந்துரைகளைப் பெறுவதற்காக அவற்றை உங்களின் வழக்கமான தேடல் இன்ஜினுக்கு Brave அனுப்பும். இந்த அம்சம் மறைநிலைப் பயன்முறையில் முடக்கப்பட்டிருக்கும். Brave மறைநிலை மறைநிலைப் பயன்முறையில் உலாவும்போது, பாதுகாப்பற்ற இணைப்பைப் பயன்படுத்தி ஒரு தளத்தை ஏற்றும் முன் Brave உங்களை எச்சரிக்கும் +குறிப்பிடப்படாத பிழை காரணமாக நிறுவல் தோல்வியடைந்தது. Braveமை மீண்டும் பதிவிறக்கம் செய்க. \ No newline at end of file diff --git a/app/resources/brave_strings_te.xtb b/app/resources/brave_strings_te.xtb index 4bafad38ff9..53f103c8b12 100644 --- a/app/resources/brave_strings_te.xtb +++ b/app/resources/brave_strings_te.xtb @@ -692,4 +692,5 @@ మీరు అడ్రస్ బార్‌లో లేదా సెర్చ్ బాక్స్‌లో టైప్ చేసినప్పుడు, మెరుగైన సూచనలను పొందడానికి Brave మీరు టైప్ చేసిన దానిని మీ ఆటోమేటిక్ సెర్చ్ ఇంజిన్‌కు పంపుతుంది. అజ్ఞాత మోడ్‌లో ఇది ఆఫ్‌లో ఉంటుంది. Brave అజ్ఞాత మోడ్ అజ్ఞాత మోడ్‌లో బ్రౌజ్ చేస్తున్నప్పుడు, సురక్షితం కాని కనెక్షన్‌ను ఉపయోగించి సైట్‌ను లోడ్ చేసే ముందు Brave మిమ్మల్ని హెచ్చరిస్తుంది +తెలియ‌ని ఎర్ర‌ర్‌ కారణంగా ఇన‌స్ట‌లేష‌న్‌ విఫలమైంది. దయచేసి Braveను మళ్లీ డౌన్‌లోడ్ చేయండి. \ No newline at end of file diff --git a/app/resources/brave_strings_th.xtb b/app/resources/brave_strings_th.xtb index 20c091f1d8b..e3abd1693cd 100644 --- a/app/resources/brave_strings_th.xtb +++ b/app/resources/brave_strings_th.xtb @@ -698,4 +698,5 @@ Brave ไม่สามารถกู้คืนการตั้งค่ เมื่อคุณพิมพ์ในแถบที่อยู่หรือช่องค้นหา Brave จะส่งข้อมูลที่คุณพิมพ์ไปยังเครื่องมือค้นหาเริ่มต้นเพื่อรับคำแนะนำที่ดีขึ้น และจะถูกปิดใน Private Brave Private เมื่อท่องเว็บในโหมดส่วนตัว Brave จะทำการเตือนคุณก่อนโหลดเว็บไซต์ที่ใช้การเชื่อมต่อที่ไม่ปลอดภัย +การติดตั้งล้มเหลวเนื่องจากเกิดข้อผิดพลาดที่ไม่ระบุ โปรดดาวน์โหลด Brave อีกครั้ง \ No newline at end of file diff --git a/app/resources/brave_strings_tr.xtb b/app/resources/brave_strings_tr.xtb index 533e19f41fc..c103ca54962 100644 --- a/app/resources/brave_strings_tr.xtb +++ b/app/resources/brave_strings_tr.xtb @@ -696,4 +696,5 @@ Brave ayarlarınızı kurtaramıyor. Bir adres çubuğuna veya arama kutusuna yazdığınız zaman, Brave daha iyi öneriler almanız için yazdığınız şeyi varsayılan arama motorunuza gönderir. Bu Gizli modda kapalıdır. Brave Gizli Mod Gizli modda gezinirken Brave, güvenli olmayan bir bağlantı kullanan bir siteyi yüklemeden önce sizi uyaracaktır +Yükleme belirtilmeyen bir hata nedeniyle başarısız oldu. Lütfen Brave'u tekrar indirin. \ No newline at end of file diff --git a/app/resources/brave_strings_uk.xtb b/app/resources/brave_strings_uk.xtb index 17866065e57..2d5135086f0 100644 --- a/app/resources/brave_strings_uk.xtb +++ b/app/resources/brave_strings_uk.xtb @@ -714,4 +714,5 @@ Brave не може відновити ваші налаштування.Коли ви вводите запит у панелі адреси чи полі пошуку, Brave надсилає його до типової пошукової системи, щоб отримати кращі пропозиції. Цю функцію вимкнено в приватному режимі перегляду. Приватний режим Brave Під час перегляду сторінок у приватному режимі Brave попереджатиме вас, перш ніж завантажити вебсайт із незахищеним з’єднанням +Не вдалося встановити через невизначену помилку. Завантажте Brave ще раз. \ No newline at end of file diff --git a/app/resources/brave_strings_ur.xtb b/app/resources/brave_strings_ur.xtb index 9dae2a80f9b..1e1f37ba61c 100644 --- a/app/resources/brave_strings_ur.xtb +++ b/app/resources/brave_strings_ur.xtb @@ -697,4 +697,5 @@ Brave آپ کی ترتیبات کو بازیافت کرنے سے قاصر ہے۔ ‏اپنے مقام کا استعمال کرنے کے لیے، سسٹم کی ترتیبات میں Brave کو رسائی فراہم کریں ‏Google Chrome بی ٹا Google Chrome Dev +‏غیر متعین خرابی کی وجہ سے انسٹالیشن ناکام ہوگیا۔ براہ کرم Brave دوبارہ ڈاؤن لوڈ کریں۔ \ No newline at end of file diff --git a/app/resources/brave_strings_uz.xtb b/app/resources/brave_strings_uz.xtb index 8167c7e990d..be40b69e072 100644 --- a/app/resources/brave_strings_uz.xtb +++ b/app/resources/brave_strings_uz.xtb @@ -702,4 +702,5 @@ Brave sozlamalaringizni qaytadan tiklay olmadi. Manzil qatori va qidiruv maydonchasida matn kiritganingizda, yaxshiroq tavsiyalar berilishi uchun Brave kiritilganlarni birlamchi qidiruv tizimingizga yuboradi. Bu funksiya Maxfiy rejimda faolsizlantiriladi. Brave Maxfiy rejimi Maxfiy rejimdan foydalanilganda, Brave saytni yuklashdan oldin sizni xavfsiz boʻlmagan ulanish usuli orqali ogohlantiradi +O‘rnatish vaqtida kutilmagan xatolik yuz berdi. Brave‘ni qaytadan yuklab oling. \ No newline at end of file diff --git a/app/resources/brave_strings_vi.xtb b/app/resources/brave_strings_vi.xtb index 582ecd0b8c1..d74f31904b9 100644 --- a/app/resources/brave_strings_vi.xtb +++ b/app/resources/brave_strings_vi.xtb @@ -699,4 +699,5 @@ Brave không thể khôi phục cài đặt của bạn. Khi bạn nhập vào thanh địa chỉ hoặc hộp tìm kiếm, Brave sẽ gửi nội dung bạn nhập tới công cụ tìm kiếm mặc định của bạn để nhận các đề xuất tốt hơn. Điều này được tắt trong Riêng tư. Brave Riêng tư Khi duyệt ở chế độ Riêng tư, Brave sẽ cảnh báo bạn trước khi tải trang web bằng kết nối không an toàn +Không thể cài đặt do xảy ra lỗi không xác định. Hãy tải xuống Brave lại lần nữa. \ No newline at end of file diff --git a/app/resources/brave_strings_zh-CN.xtb b/app/resources/brave_strings_zh-CN.xtb index 38beee95f17..b1195c5d930 100644 --- a/app/resources/brave_strings_zh-CN.xtb +++ b/app/resources/brave_strings_zh-CN.xtb @@ -698,4 +698,5 @@ Brave 无法恢复您的设置。 当您在地址栏或搜索框中输入时,Brave 会将您输入的内容发送到默认搜索引擎,以获得更好的建议。这是私密的。 Brave 隐私 在隐私模式下浏览时,Brave 会在使用不安全连接加载网站之前向您发出警告 +未指定的错误导致安装失败。请重新下载 Brave。 \ No newline at end of file diff --git a/app/resources/brave_strings_zh-HK.xtb b/app/resources/brave_strings_zh-HK.xtb index 2f1599267ad..3f006e9ee26 100644 --- a/app/resources/brave_strings_zh-HK.xtb +++ b/app/resources/brave_strings_zh-HK.xtb @@ -695,4 +695,5 @@ Brave 無法復原您的設定。 如要使用位置,請在系統設定中向 Brave 授予存取權 Google Chrome 測試版 Google Chrome 開發人員版 +不明錯誤導致安裝失敗,請重新下載 Brave。 \ No newline at end of file diff --git a/app/resources/brave_strings_zh-TW.xtb b/app/resources/brave_strings_zh-TW.xtb index 4dbb17493fa..f2f8ceabc54 100644 --- a/app/resources/brave_strings_zh-TW.xtb +++ b/app/resources/brave_strings_zh-TW.xtb @@ -698,4 +698,5 @@ Brave 無法復原你的設定。 當您在網址列或搜尋方塊輸入內容時,Brave 會將您輸入的內容傳送至您的預設搜尋引擎,以便取得更好的建議。在無痕模式下會停用此功能。 Brave 隱私模式 以私密模式瀏覽時,Brave 會在使用不安全連線載入網站前向您發出警告 +不明錯誤導致安裝失敗,請重新下載 Brave。 \ No newline at end of file diff --git a/app/resources/brave_strings_zu.xtb b/app/resources/brave_strings_zu.xtb index 3e4753ca17c..eb21a0fc18f 100644 --- a/app/resources/brave_strings_zu.xtb +++ b/app/resources/brave_strings_zu.xtb @@ -697,4 +697,5 @@ I-Brave ayikwazi ukubuyisela izilungiselelo zakho. Ukuze usebenzise indawo yakho, nikeza iBrave ukufinyelela amasethingi ohlelo I-beta ye-Google Chrome I-Google Chrome Dev +Ukufakwa kuhlulekile ngenxa yephutha elingacacisiwe. Sicela ulande i-Brave futhi. \ No newline at end of file diff --git a/chromium_src/check_chromium_src_config.json5 b/chromium_src/check_chromium_src_config.json5 index fd05f6ac67f..acd68688593 100644 --- a/chromium_src/check_chromium_src_config.json5 +++ b/chromium_src/check_chromium_src_config.json5 @@ -90,6 +90,9 @@ "chrome/grit/generated_resources.h": [ "IDS_PERMISSIONS_BUBBLE_PROMPT", ], + "chrome/install_static/chromium_install_modes.h": [ + "CHROMIUM_INDEX", + ], "chrome/install_static/install_constants.h": [ "BUILDFLAG_INTERNAL_USE_GOOGLE_UPDATE_INTEGRATION", ], diff --git a/chromium_src/chrome/install_static/chromium_install_modes.h b/chromium_src/chrome/install_static/chromium_install_modes.h index 4283bfb699f..7d5988e7e5e 100644 --- a/chromium_src/chrome/install_static/chromium_install_modes.h +++ b/chromium_src/chrome/install_static/chromium_install_modes.h @@ -31,6 +31,9 @@ enum InstallConstantIndex { }; #if defined(OFFICIAL_BUILD) + +#define CHROMIUM_INDEX STABLE_INDEX + // Regarding the install switch, use the same values that are in // chrome/installer/mini_installer/configuration.cc inline constexpr auto kInstallModes = std::to_array({ @@ -226,6 +229,9 @@ inline constexpr auto kInstallModes = std::to_array({ }, }); #else + +#define CHROMIUM_INDEX DEVELOPER_INDEX + inline constexpr auto kInstallModes = std::to_array({ // The primary (and only) install mode for Brave developer build. { diff --git a/chromium_src/chrome/installer/DEPS b/chromium_src/chrome/installer/DEPS index cfd118008f7..174c6646279 100644 --- a/chromium_src/chrome/installer/DEPS +++ b/chromium_src/chrome/installer/DEPS @@ -6,4 +6,7 @@ include_rules += [ "+brave/components/brave_vpn/browser/connection/ikev2/win", "+brave/components/brave_vpn/common/buildflags", "+brave/installer", + # We need bspatch for delta updates on Windows until we are on Omaha 4. See: + # github.com/brave/brave-core/pull/31937 + "+brave/third_party/bspatch" ] diff --git a/chromium_src/chrome/installer/mini_installer/configuration.cc b/chromium_src/chrome/installer/mini_installer/configuration.cc new file mode 100644 index 00000000000..49e6719d2fe --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/configuration.cc @@ -0,0 +1,104 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(https://github.com/brave/brave-browser/issues/50977): Remove this and +// convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include "chrome/installer/mini_installer/configuration.h" + +#include + +#include "build/branding_buildflags.h" +#include "chrome/installer/mini_installer/appid.h" +#include "chrome/installer/mini_installer/mini_string.h" + +#define Initialize() Initialize(HMODULE module) + +#define kAppGuid \ + kAppGuid; \ + previous_version_ = nullptr + +#if defined(OFFICIAL_BUILD) && !BUILDFLAG(GOOGLE_CHROME_BRANDING) +#undef BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING +#define BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING() (1) +#define NEED_TO_RESET_BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING +#endif + +#if defined(OFFICIAL_BUILD) +namespace { +DWORD BraveGetEnvironmentVariableW(const wchar_t* var, + wchar_t* value, + DWORD bufSize) { + assert(::lstrcmp(var, L"GoogleUpdateIsMachine") == 0); + return ::GetEnvironmentVariableW(L"BraveSoftwareUpdateIsMachine", value, + bufSize); +} +} // namespace +#define GetEnvironmentVariableW BraveGetEnvironmentVariableW +#endif + +#define BRAVE_READ_RESOURCES ReadResources(module); + +#include + +#undef BRAVE_READ_RESOURCES + +#if defined(OFFICIAL_BUILD) +#undef GetEnvironmentVariableW +#endif + +#if defined(NEED_TO_RESET_BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING) +#undef BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING +#define BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING() (0) +#undef NEED_TO_RESET_BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING +#endif + +#undef kAppGuid +#undef Initialize + +namespace mini_installer { + +void Configuration::ReadResources(HMODULE module) { + HRSRC resource_info_block = + FindResource(module, MAKEINTRESOURCE(ID_PREVIOUS_VERSION), RT_RCDATA); + if (!resource_info_block) { + return; + } + + HGLOBAL data_handle = LoadResource(module, resource_info_block); + if (!data_handle) { + return; + } + + // The data is a Unicode string, so it must be a multiple of two bytes. + DWORD version_size = SizeofResource(module, resource_info_block); + if (!version_size || (version_size & 0x01) != 0) { + return; + } + + void* version_data = LockResource(data_handle); + if (!version_data) { + return; + } + + const wchar_t* version_string = reinterpret_cast(version_data); + size_t version_len = version_size / sizeof(wchar_t); + + // The string must be terminated. + if (version_string[version_len - 1]) { + return; + } + + previous_version_ = version_string; +} + +} // namespace mini_installer diff --git a/chromium_src/chrome/installer/mini_installer/configuration.h b/chromium_src/chrome/installer/mini_installer/configuration.h new file mode 100644 index 00000000000..41194adb971 --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/configuration.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_CONFIGURATION_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_CONFIGURATION_H_ + +#include + +#define Initialize() Initialize(HMODULE module) +#define program() \ + previous_version() const { \ + return previous_version_; \ + } \ + const wchar_t* program() +#define Clear() \ + Clear(); \ + void ReadResources(HMODULE module); \ + const wchar_t* previous_version_ +#include // IWYU pragma: export +#undef Clear +#undef program +#undef Initialize + +#endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_CONFIGURATION_H_ diff --git a/chromium_src/chrome/installer/mini_installer/configuration_test.cc b/chromium_src/chrome/installer/mini_installer/configuration_test.cc new file mode 100644 index 00000000000..03eff51cb57 --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/configuration_test.cc @@ -0,0 +1,20 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#include "chrome/installer/mini_installer/configuration.h" + +// Need to include registry.h because it has an `Initialize` method, and we +// define a macro with the same name below. +#include "base/win/registry.h" + +#define Initialize() Initialize(::GetModuleHandle(nullptr)) + +#include + +#undef Initialize diff --git a/chromium_src/chrome/installer/mini_installer/mini_installer.cc b/chromium_src/chrome/installer/mini_installer/mini_installer.cc index d9279cbf718..25ee303db49 100644 --- a/chromium_src/chrome/installer/mini_installer/mini_installer.cc +++ b/chromium_src/chrome/installer/mini_installer/mini_installer.cc @@ -3,38 +3,115 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at https://mozilla.org/MPL/2.0/. */ +// This file contains a lot of code that used to be upstream and had to be +// restored in Brave to support delta updates on Windows until we are on Omaha +// 4. See github.com/brave/brave-core/pull/31937. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(https://github.com/brave/brave-browser/issues/50977): Remove this and +// convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include "chrome/installer/mini_installer/mini_installer.h" + #include "base/compiler_specific.h" #include "build/branding_buildflags.h" +#include "chrome/installer/mini_installer/configuration.h" +#include "chrome/installer/mini_installer/mini_installer_constants.h" +#include "chrome/installer/mini_installer/mini_string.h" +#include "chrome/installer/mini_installer/regkey.h" -#define BRAVE_RUN_SETUP \ - PathString installer_filename; \ - wchar_t value[MAX_PATH] = {0, }; \ - const bool result = \ - RegKey::ReadSZValue(HKEY_CURRENT_USER, \ - L"Software\\BraveSoftware\\Promo", \ - L"StubInstallerPath", value, _countof(value)) ; \ - if (result && \ - installer_filename.assign(value) && \ - installer_filename.length() != 0) { \ - ReferralCodeString referral_code; \ - if (ParseReferralCode(installer_filename.get(), &referral_code)) { \ - cmd_line.append(L" --brave-referral-code"); \ - cmd_line.append(L"=\""); \ - cmd_line.append(referral_code.get()); \ - cmd_line.append(L"\""); \ - } \ - } - -#if defined(OFFICIAL_BUILD) +#if defined(OFFICIAL_BUILD) && !BUILDFLAG(GOOGLE_CHROME_BRANDING) #undef BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING #define BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING() (1) +#define NEED_TO_RESET_BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING #endif // defined(OFFICIAL_BUILD) +#define BRAVE_STUFF_PATCH_FLAG_INTO_WINDOWS_ERROR \ + if (exit_code.IsSuccess() && setup_type.compare(kLZMAResourceType) == 0) { \ + exit_code.windows_error = kNotAnErrorIsPatchUpdate; \ + } + +#define BRAVE_ASSIGN_PREVIOUS_SETUP_EXE_IF_SETUP_PATH_EMPTY \ + if (*setup_path == L'\0') { \ + ProcessExitResult exit_code = GetPreviousSetupExePath( \ + configuration, setup_exe.get(), setup_exe.capacity()); \ + if (!exit_code.IsSuccess()) { \ + return exit_code; \ + } \ + } + +#define BRAVE_MAYBE_APPEND_PREVIOUS_VERSION_AND_PARSE_REFERRAL_CODE \ + if (configuration.previous_version() && \ + (!cmd_line.append(L" --") || !cmd_line.append(kCmdPreviousVersion) || \ + !cmd_line.append(L"=\"") || \ + !cmd_line.append(configuration.previous_version()) || \ + !cmd_line.append(L"\""))) { \ + return ProcessExitResult(COMMAND_STRING_OVERFLOW); \ + } \ + PathString installer_filename; \ + wchar_t value[MAX_PATH] = { \ + 0, \ + }; \ + const bool result = RegKey::ReadSZValue( \ + HKEY_CURRENT_USER, L"Software\\BraveSoftware\\Promo", \ + L"StubInstallerPath", value, _countof(value)); \ + if (result && installer_filename.assign(value) && \ + installer_filename.length() != 0) { \ + ReferralCodeString referral_code; \ + if (ParseReferralCode(installer_filename.get(), &referral_code)) { \ + cmd_line.append(L" --brave-referral-code"); \ + cmd_line.append(L"=\""); \ + cmd_line.append(referral_code.get()); \ + cmd_line.append(L"\""); \ + } \ + } + +#define BRAVE_APPEND_FULL_SUFFIX_IN_REGISTRY SetInstallerFlags(configuration); + +// If a compressed setup patch was found, run the previous setup.exe to +// patch and generate the new setup.exe. +#define BRAVE_MAYBE_PATCH_PREVIOUS_SETUP_EXE \ + if (exit_code.IsSuccess() && \ + exit_code.windows_error == kNotAnErrorIsPatchUpdate) { \ + PathString setup_dest_path; \ + if (!setup_dest_path.assign(base_path.get()) || \ + !setup_dest_path.append(kSetupExe)) { \ + return ProcessExitResult(PATH_STRING_OVERFLOW); \ + } \ + exit_code = PatchSetup(configuration, setup_path, setup_dest_path, \ + max_delete_attempts); \ + if (exit_code.IsSuccess()) { \ + setup_path.assign(setup_dest_path); \ + } else { \ + setup_path.clear(); \ + } \ + } + +namespace mini_installer { + +namespace { +ProcessExitResult PatchSetup(const Configuration& configuration, + const PathString& patch_path, + const PathString& dest_path, + int& max_delete_attempts); +} // namespace + +void SetInstallerFlags(const Configuration& configuration); + +} // namespace mini_installer + +#define Initialize() Initialize(module) + #include -#if defined(OFFICIAL_BUILD) -#undef BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING -#endif // defined(OFFICIAL_BUILD) -#undef BRAVE_RUN_SETUP + +#undef Initialize +#undef BRAVE_MAYBE_PATCH_PREVIOUS_SETUP_EXE +#undef BRAVE_APPEND_FULL_SUFFIX_IN_REGISTRY +#undef BRAVE_MAYBE_APPEND_PREVIOUS_VERSION_AND_PARSE_REFERRAL_CODE +#undef BRAVE_ASSIGN_PREVIOUS_SETUP_EXE_IF_SETUP_PATH_EMPTY +#undef BRAVE_STUFF_PATCH_FLAG_INTO_WINDOWS_ERROR namespace mini_installer { @@ -189,4 +266,141 @@ bool ParseReferralCode(const wchar_t* installer_filename, return true; } +void SetInstallerFlags(const Configuration& configuration) { +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + // Set the magic suffix in registry to try full installer next time. We ignore + // any errors here and we try to set the suffix for user level unless + // GoogleUpdateIsMachine=1 is present in the environment or --system-level is + // on the command line in which case we set it for system level instead. If + // the current installer works, the flag to try full installer is cleared by + // setup.exe at the end of install. + + StackString<128> value; + + RegKey key; + if (!OpenInstallStateKey(configuration, &key)) { + return; + } + + LONG ret = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); + + // The conditions below are handling two cases: + // 1. When ap value is present, we want to add the required tag only if it + // is not present. + // 2. When ap value is missing, we are going to create it with the required + // tag. + if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { + if (ret == ERROR_FILE_NOT_FOUND) { + value.clear(); + } + + if (!StrEndsWith(value.get(), kFullInstallerSuffix) && + value.append(kFullInstallerSuffix)) { + key.WriteSZValue(kApRegistryValue, value.get()); + } + } +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) +} + +// Gets the setup.exe path from Registry by looking at the value of Uninstall +// string. |size| is measured in wchar_t units. +ProcessExitResult GetSetupExePathForAppGuid(bool system_level, + const wchar_t* app_guid, + const wchar_t* previous_version, + wchar_t* path, + size_t size) { + const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + RegKey key; + LONG result = OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key); + if (result == ERROR_SUCCESS) { + result = key.ReadSZValue(kUninstallRegistryValue, path, size); + } + if (result != ERROR_SUCCESS) { + return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY, result); + } + + // Check that the path to the existing installer includes the expected + // version number. It's not necessary for accuracy to verify before/after + // delimiters. + if (!SearchStringI(path, previous_version)) { + return ProcessExitResult(PATCH_NOT_FOR_INSTALLED_VERSION); + } + + // Strip double-quotes surrounding the string, if present. + if (size >= 1 && path[0] == '\"') { + size_t path_length = SafeStrLen(path, size); + if (path_length >= 2 && path[path_length - 1] == '\"') { + if (!SafeStrCopy(path, size, path + 1)) { + return ProcessExitResult(PATH_STRING_OVERFLOW); + } + path[path_length - 2] = '\0'; + } + } + + return ProcessExitResult(SUCCESS_EXIT_CODE); +} + +// Gets the path to setup.exe of the previous version. The overall path is found +// in the Uninstall string in the registry. A previous version number specified +// in |configuration| is used if available. |size| is measured in wchar_t units. +ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration, + wchar_t* path, + size_t size) { + // Check Chrome's ClientState key for the path to setup.exe. This will have + // the correct path for all well-functioning installs. + return GetSetupExePathForAppGuid( + configuration.is_system_level(), configuration.chrome_app_guid(), + configuration.previous_version(), path, size); +} + +namespace { + +// Applies an differential update to the previous setup.exe provided by +// `patch_path` and produces a new setup.exe at the path `target_path`. +ProcessExitResult PatchSetup(const Configuration& configuration, + const PathString& patch_path, + const PathString& dest_path, + int& max_delete_attempts) { + CommandString cmd_line; + PathString exe_path; + ProcessExitResult exit_code = GetPreviousSetupExePath( + configuration, exe_path.get(), exe_path.capacity()); + if (!exit_code.IsSuccess()) { + return exit_code; + } + + if (!cmd_line.append(L"\"") || !cmd_line.append(exe_path.get()) || + !cmd_line.append(L"\" --") || !cmd_line.append(kCmdUpdateSetupExe) || + !cmd_line.append(L"=\"") || !cmd_line.append(patch_path.get()) || + !cmd_line.append(L"\" --") || !cmd_line.append(kCmdNewSetupExe) || + !cmd_line.append(L"=\"") || !cmd_line.append(dest_path.get()) || + !cmd_line.append(L"\"")) { + exit_code = ProcessExitResult(COMMAND_STRING_OVERFLOW); + } + + if (!exit_code.IsSuccess()) { + return exit_code; + } + + // Get any command line option specified for mini_installer and pass them + // on to setup.exe. + AppendCommandLineFlags(configuration.command_line(), &cmd_line); + + exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get(), + SETUP_PATCH_FAILED_FILE_NOT_FOUND, + SETUP_PATCH_FAILED_PATH_NOT_FOUND, + SETUP_PATCH_FAILED_COULD_NOT_CREATE_PROCESS); + DeleteWithRetryAndMetrics(patch_path.get(), max_delete_attempts); + + return exit_code; +} + +} // namespace + } // namespace mini_installer + +#if defined(NEED_TO_RESET_BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING) +#undef BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING +#define BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING() (0) +#undef NEED_TO_RESET_BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING +#endif diff --git a/chromium_src/chrome/installer/mini_installer/mini_installer.h b/chromium_src/chrome/installer/mini_installer/mini_installer.h index 32a390cd71f..a5bb6e3c4fb 100644 --- a/chromium_src/chrome/installer/mini_installer/mini_installer.h +++ b/chromium_src/chrome/installer/mini_installer/mini_installer.h @@ -17,6 +17,17 @@ typedef StackString<128> ReferralCodeString; bool ParseReferralCode(const wchar_t* installer_filename, ReferralCodeString* referral_code); + +// Upstream's UnpackBinaryResources function used to have a parameter +// ResourceTypeString& setup_type. When this had value kLZMAResourceType after +// the function, then upstream used to run the previous setup.exe to patch and +// generate the new setup.exe. Upstream removed this functionality when it +// switched to Omaha 4. We are still on Omaha 3. To restore the feature with +// minimal changes in upstream even though UnpackBinaryResources's has changed, +// we stuff the information whether a differential update is to be applied into +// the Windows error code, with this special value: +inline constexpr DWORD kNotAnErrorIsPatchUpdate = 0x12345678; + } // namespace mini_installer #endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_MINI_INSTALLER_H_ diff --git a/chromium_src/chrome/installer/mini_installer/mini_installer_unittest.cc b/chromium_src/chrome/installer/mini_installer/mini_installer_unittest.cc new file mode 100644 index 00000000000..3bdf46f6488 --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/mini_installer_unittest.cc @@ -0,0 +1,95 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#include + +#define PREVIOUS_VERSION L"62.0.1234.0" + +namespace mini_installer { + +namespace { + +constexpr wchar_t kPreviousVersion[] = PREVIOUS_VERSION; + +class FakeConfiguration : public Configuration { + public: + FakeConfiguration() { previous_version_ = kPreviousVersion; } +}; + +} // namespace + +// A test harness for GetPreviousSetupExePath. +class GetPreviousSetupExePathTest : public ::testing::Test { + public: + GetPreviousSetupExePathTest(const GetPreviousSetupExePathTest&) = delete; + GetPreviousSetupExePathTest& operator=(const GetPreviousSetupExePathTest&) = + delete; + + protected: + GetPreviousSetupExePathTest() = default; + ~GetPreviousSetupExePathTest() override = default; + + void SetUp() override { + ASSERT_NO_FATAL_FAILURE( + registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER)); + } + + const Configuration& configuration() const { return configuration_; } + + // Writes |path| to the registry in Chrome's ClientState...UninstallString + // value. + void SetPreviousSetup(const wchar_t* path) { + base::win::RegKey key; + const install_static::InstallDetails& details = + install_static::InstallDetails::Get(); + ASSERT_EQ( + key.Create(HKEY_CURRENT_USER, details.GetClientStateKeyPath().c_str(), + KEY_SET_VALUE | KEY_WOW64_32KEY), + ERROR_SUCCESS); + ASSERT_EQ(key.WriteValue(installer::kUninstallStringField, path), + ERROR_SUCCESS); + } + + private: + registry_util::RegistryOverrideManager registry_override_manager_; + FakeConfiguration configuration_; +}; + +// Tests that the path is returned. +TEST_F(GetPreviousSetupExePathTest, SimpleTest) { + static constexpr wchar_t kSetupExePath[] = + L"C:\\SomePath\\To\\" PREVIOUS_VERSION L"\\setup.exe"; + ASSERT_NO_FATAL_FAILURE(SetPreviousSetup(kSetupExePath)); + + StackString path; + ProcessExitResult result = + GetPreviousSetupExePath(configuration(), path.get(), path.capacity()); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_STREQ(path.get(), kSetupExePath); +} + +// Tests that quotes are removed, if present. +TEST_F(GetPreviousSetupExePathTest, QuoteStripping) { + static constexpr wchar_t kSetupExePath[] = + L"C:\\SomePath\\To\\" PREVIOUS_VERSION L"\\setup.exe"; + std::wstring quoted_path(L"\""); + quoted_path += kSetupExePath; + quoted_path += L"\""; + ASSERT_NO_FATAL_FAILURE(SetPreviousSetup(quoted_path.c_str())); + + StackString path; + ProcessExitResult result = + GetPreviousSetupExePath(configuration(), path.get(), path.capacity()); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_STREQ(path.get(), kSetupExePath); +} + +} // namespace mini_installer + +#undef PREVIOUS_VERSION diff --git a/chromium_src/chrome/installer/mini_installer/mini_string.cc b/chromium_src/chrome/installer/mini_installer/mini_string.cc new file mode 100644 index 00000000000..d283c4705b2 --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/mini_string.cc @@ -0,0 +1,62 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(https://github.com/brave/brave-browser/issues/50977): Remove this and +// convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include + +namespace mini_installer { + +const wchar_t* SearchStringI(const wchar_t* source, const wchar_t* find) { + if (!find || find[0] == L'\0') { + return source; + } + + const wchar_t* scan = source; + while (*scan) { + const wchar_t* s = scan; + const wchar_t* f = find; + + while (*s && *f && EqualASCIICharI(*s, *f)) { + ++s, ++f; + } + + if (!*f) { + return scan; + } + + ++scan; + } + + return nullptr; +} + +bool FindTagInStr(const wchar_t* str, + const wchar_t* tag, + const wchar_t** position) { + int tag_length = ::lstrlen(tag); + const wchar_t* scan = str; + for (const wchar_t* tag_start = SearchStringI(scan, tag); + tag_start != nullptr; tag_start = SearchStringI(scan, tag)) { + scan = tag_start + tag_length; + if (*scan == L'-' || *scan == L'\0') { + if (position != nullptr) { + *position = tag_start; + } + return true; + } + } + return false; +} + +} // namespace mini_installer diff --git a/chromium_src/chrome/installer/mini_installer/mini_string.h b/chromium_src/chrome/installer/mini_installer/mini_string.h new file mode 100644 index 00000000000..b6c0fee5df3 --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/mini_string.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_ + +#include // IWYU pragma: export + +namespace mini_installer { + +// Case insensitive search of the first occurrence of |find| in |source|. +const wchar_t* SearchStringI(const wchar_t* source, const wchar_t* find); + +// Searches for |tag| within |str|. Returns true if |tag| is found and is +// immediately followed by '-' or is at the end of the string. If |position| +// is non-nullptr, the location of the tag is returned in |*position| on +// success. +bool FindTagInStr(const wchar_t* str, + const wchar_t* tag, + const wchar_t** position); + +} // namespace mini_installer + +#endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_ diff --git a/chromium_src/chrome/installer/mini_installer/mini_string_test.cc b/chromium_src/chrome/installer/mini_installer/mini_string_test.cc new file mode 100644 index 00000000000..5f94d3ba076 --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/mini_string_test.cc @@ -0,0 +1,28 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include + +// Tests the case insensitive find support of the StackString class. +// This test used to be upstream and had to be restored in Brave to support +// delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +TEST_F(MiniInstallerStringTest, StackStringFind) { + static const wchar_t kTestStringSource[] = L"1234ABcD567890"; + static const wchar_t kTestStringFind[] = L"abcd"; + static const wchar_t kTestStringNotFound[] = L"80"; + + StackString str; + EXPECT_TRUE(str.assign(kTestStringSource)); + EXPECT_EQ(str.get(), + mini_installer::SearchStringI(str.get(), kTestStringSource)); + EXPECT_EQ(nullptr, + mini_installer::SearchStringI(str.get(), kTestStringNotFound)); + const wchar_t* found = + mini_installer::SearchStringI(str.get(), kTestStringFind); + EXPECT_NE(nullptr, found); + std::wstring check(found, _countof(kTestStringFind) - 1); + EXPECT_EQ(0, lstrcmpi(check.c_str(), kTestStringFind)); +} diff --git a/chromium_src/chrome/installer/mini_installer/regkey.cc b/chromium_src/chrome/installer/mini_installer/regkey.cc index f296fa59487..5f536ad6a22 100644 --- a/chromium_src/chrome/installer/mini_installer/regkey.cc +++ b/chromium_src/chrome/installer/mini_installer/regkey.cc @@ -19,3 +19,16 @@ #if defined(OFFICIAL_BUILD) #undef BUILDFLAG_INTERNAL_GOOGLE_CHROME_BRANDING #endif + +namespace mini_installer { + +// This function used to be upstream and had to be restored in Brave to support +// delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +LONG RegKey::WriteSZValue(const wchar_t* value_name, const wchar_t* value) { + return ::RegSetValueEx(key_, value_name, 0, REG_SZ, + reinterpret_cast(value), + (lstrlen(value) + 1) * sizeof(wchar_t)); +} + +} // namespace mini_installer diff --git a/chromium_src/chrome/installer/mini_installer/regkey.h b/chromium_src/chrome/installer/mini_installer/regkey.h new file mode 100644 index 00000000000..d6740640292 --- /dev/null +++ b/chromium_src/chrome/installer/mini_installer/regkey.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_REGKEY_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_REGKEY_H_ + +// The WriteSZValue function used to be upstream and had to be restored in Brave +// to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +#define WriteDWValue(...) \ + WriteDWValue(__VA_ARGS__); \ + LONG WriteSZValue(const wchar_t* value_name, const wchar_t* value) + +#include // IWYU pragma: export + +#undef WriteDWValue + +#endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_MINI_INSTALLER_REGKEY_H_ diff --git a/chromium_src/chrome/installer/setup/DEPS b/chromium_src/chrome/installer/setup/DEPS new file mode 100644 index 00000000000..211cd551a28 --- /dev/null +++ b/chromium_src/chrome/installer/setup/DEPS @@ -0,0 +1,5 @@ +# Upstream used to have zucchini in include_rules until it moved the delta +# update logic from the browser installer into the updater. We need to keep it +# here until we are on Omaha 4 on Windows. See +# github.com/brave/brave-core/pull/31937 +include_rules = [ "+components/zucchini" ] diff --git a/chromium_src/chrome/installer/setup/brand_behaviors.h b/chromium_src/chrome/installer/setup/brand_behaviors.h new file mode 100644 index 00000000000..1ac5ebb8425 --- /dev/null +++ b/chromium_src/chrome/installer/setup/brand_behaviors.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_BRAND_BEHAVIORS_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_BRAND_BEHAVIORS_H_ + +// UpdateInstallStatus used to have a different signature in upstream. We need +// to restore it here to support delta updates on Windows until we are on Omaha +// 4. See github.com/brave/brave-core/pull/31937. +#define UpdateInstallStatus() \ + UpdateInstallStatus(installer::ArchiveType archive_type, \ + installer::InstallStatus install_status) + +#include // IWYU pragma: export + +#undef UpdateInstallStatus + +#endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_BRAND_BEHAVIORS_H_ diff --git a/chromium_src/chrome/installer/setup/brave_behaviors.cc b/chromium_src/chrome/installer/setup/brave_behaviors.cc index fcc13a0ac53..c6e6c83cfcb 100644 --- a/chromium_src/chrome/installer/setup/brave_behaviors.cc +++ b/chromium_src/chrome/installer/setup/brave_behaviors.cc @@ -7,19 +7,23 @@ #include "base/check_op.h" #include "base/dcheck_is_on.h" +#include "base/notreached.h" #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" +#include "base/win/windows_version.h" +#include "chrome/install_static/install_util.h" #include "chrome/installer/setup/brand_behaviors.h" +#include "chrome/installer/util/google_update_settings.h" +#include "chrome/installer/util/install_util.h" #include "third_party/abseil-cpp/absl/strings/str_format.h" -#define DoPostUninstallOperations DoPostUninstallOperations_UNUSED -#include -#undef DoPostUninstallOperations - namespace installer { namespace { +bool NavigateToUrlWithHttps(const std::wstring& url); +void NavigateToUrlWithIExplore(const std::wstring& url); + // This code is copied from `DoPostUninstallOperations` implementation in // `chrome/installer/setup/google_chrome_behaviors.cc` with the following // changes: @@ -32,6 +36,23 @@ constexpr std::wstring_view kBraveUninstallSurveyUrl( } // namespace +// If |archive_type| is INCREMENTAL_ARCHIVE_TYPE and |install_status| does not +// indicate a successful update, "-full" is appended to Chrome's "ap" value in +// its ClientState key if it is not present, resulting in the full installer +// being returned from the next update check. If |archive_type| is +// FULL_ARCHIVE_TYPE or |install_status| indicates a successful update, "-full" +// is removed from the "ap" value. "-stage:*" values are +// unconditionally removed from the "ap" value. +// This function used to be upstream and had to be restored in Brave to support +// delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +void UpdateInstallStatus(installer::ArchiveType archive_type, + installer::InstallStatus install_status) { + GoogleUpdateSettings::UpdateInstallStatus( + install_static::IsSystemInstall(), archive_type, + InstallUtil::GetInstallReturnCode(install_status)); +} + void DoPostUninstallOperations(const base::Version& version, const base::FilePath& local_data_path, const std::wstring& distribution_data) { @@ -64,4 +85,15 @@ void DoPostUninstallOperations(const base::Version& version, } } +class GoogleUpdateSettings_UNUSED { + public: + static void UpdateInstallStatus() { NOTREACHED(); } +}; + } // namespace installer + +#define GoogleUpdateSettings GoogleUpdateSettings_UNUSED +#define DoPostUninstallOperations DoPostUninstallOperations_UNUSED +#include +#undef DoPostUninstallOperations +#undef GoogleUpdateSettings diff --git a/chromium_src/chrome/installer/setup/install_worker.cc b/chromium_src/chrome/installer/setup/install_worker.cc index c1c420ee324..4417425cbee 100644 --- a/chromium_src/chrome/installer/setup/install_worker.cc +++ b/chromium_src/chrome/installer/setup/install_worker.cc @@ -186,7 +186,28 @@ void UpdateBraveVpn(const base::FilePath& target_path, #endif // BUILDFLAG(ENABLE_BRAVE_VPN) +// The code in BRAVE_ADD_INSTALLER_COPY_TASKS and +// BRAVE_MAYBE_ABORT_ADD_CHROME_WORK_ITEMS used to be upstream and had to be +// restored in Brave to support delta updates on Windows until we are on Omaha +// 4. See github.com/brave/brave-core/pull/31937. +#define BRAVE_ADD_INSTALLER_COPY_TASKS \ + const base::FilePath& archive_path = installer_state.uncompressed_archive; \ + base::FilePath archive_dst(installer_dir.Append(archive_path.BaseName())); \ + if (archive_path != archive_dst) { \ + if (temp_path.IsParent(archive_path)) { \ + install_list->AddMoveTreeWorkItem(archive_path, archive_dst, temp_path, \ + WorkItem::ALWAYS_MOVE); \ + } else { \ + install_list->AddCopyTreeWorkItem(archive_path, archive_dst, temp_path, \ + WorkItem::ALWAYS); \ + } \ + } +#define BRAVE_MAYBE_ABORT_ADD_CHROME_WORK_ITEMS \ + if (old_archive == installer_state.uncompressed_archive) \ + return; #include +#undef BRAVE_MAYBE_ABORT_ADD_CHROME_WORK_ITEMS +#undef BRAVE_ADD_INSTALLER_COPY_TASKS #if BUILDFLAG(ENABLE_BRAVE_VPN) #undef AddUpdateDowngradeVersionItem #endif // BUILDFLAG(ENABLE_BRAVE_VPN) diff --git a/chromium_src/chrome/installer/setup/installer_state.h b/chromium_src/chrome/installer/setup/installer_state.h new file mode 100644 index 00000000000..ec36a98eedb --- /dev/null +++ b/chromium_src/chrome/installer/setup/installer_state.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_INSTALLER_STATE_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_INSTALLER_STATE_H_ + +#include "base/files/file_path.h" +#include "chrome/installer/util/util_constants.h" + +// Needed for delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +#define RequiresActiveSetup \ + RequiresActiveSetup() const; \ + ArchiveType archive_type = ArchiveType::UNKNOWN_ARCHIVE_TYPE; \ + base::FilePath uncompressed_archive; \ + void Unused + +#include // IWYU pragma: export + +#undef RequiresActiveSetup + +#endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_INSTALLER_STATE_H_ diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources.grd b/chromium_src/chrome/installer/setup/resources/setup_resources.grd new file mode 100644 index 00000000000..7494397655f --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources.grd @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Installation failed due to unspecified error. Please download Brave again. + + + + + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_af.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_af.xtb new file mode 100644 index 00000000000..eea50508e40 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_af.xtb @@ -0,0 +1,5 @@ + + + +Kon weens 'n ongespesifiseerde fout nie installeer nie. Laai Brave asseblief weer af. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_am.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_am.xtb new file mode 100644 index 00000000000..f677a447389 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_am.xtb @@ -0,0 +1,5 @@ + + + +ተለይቶ ባልታወቀ ስህተት ምክንያት ጭነት ከሽፏል። እባክዎ Braveን እንደገና ያውርዱ። + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ar.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ar.xtb new file mode 100644 index 00000000000..2499381ac86 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ar.xtb @@ -0,0 +1,5 @@ + + + +‏تعذّر التثبيت نظرًا لحدوث خطأ غير محدد. يُرجى إعادة تنزيل Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_as.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_as.xtb new file mode 100644 index 00000000000..be5fcedd1ee --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_as.xtb @@ -0,0 +1,5 @@ + + + +অনির্দিষ্ট আসোঁৱাহৰ বাবে ইনষ্টলেশ্বন কৰিব পৰা নগ’ল। অনুগ্ৰহ কৰি পুনৰ Brave ডাউনল’ড কৰক। + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_az.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_az.xtb new file mode 100644 index 00000000000..db78312c72b --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_az.xtb @@ -0,0 +1,5 @@ + + + +Naməlum xəta üzündən quraşdırmaq alınmadı. Brave'u yenidən endirin. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_be.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_be.xtb new file mode 100644 index 00000000000..3ef2e93438c --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_be.xtb @@ -0,0 +1,5 @@ + + + +Збой усталявання з-за нявызначанай памылкі. Спампуйце Brave зноў. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_bg.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_bg.xtb new file mode 100644 index 00000000000..7081d459330 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_bg.xtb @@ -0,0 +1,5 @@ + + + +Инсталирането не бе успешно поради неизвестна грешка. Моля, изтеглете отново Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_bn.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_bn.xtb new file mode 100644 index 00000000000..e81e71bee30 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_bn.xtb @@ -0,0 +1,5 @@ + + + +অনির্দিষ্ট ত্রুটির কারণে ইনস্টল করা যায়নি৷ অনুগ্রহ করে Brave আবার ডাউনলোড করুন৷ + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_bs.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_bs.xtb new file mode 100644 index 00000000000..e5d610d78cb --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_bs.xtb @@ -0,0 +1,5 @@ + + + +Instalacija nije uspjela zbog neodređene greške. Ponovo preuzmite Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ca.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ca.xtb new file mode 100644 index 00000000000..5eca7233b8b --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ca.xtb @@ -0,0 +1,5 @@ + + + +La instal·lació ha fallat a causa d'un error no especificat. Torneu a baixar Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_cs.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_cs.xtb new file mode 100644 index 00000000000..6b2b7ec8691 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_cs.xtb @@ -0,0 +1,5 @@ + + + +Instalace se z neznámého důvodu nezdařila. Stáhněte prosím Brave znovu. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_cy.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_cy.xtb new file mode 100644 index 00000000000..445633782ae --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_cy.xtb @@ -0,0 +1,5 @@ + + + +Methwyd y gosodiad oherwydd gwall amhenodol. Lawrlwythwch Brave eto. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_da.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_da.xtb new file mode 100644 index 00000000000..e9451a5fb6c --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_da.xtb @@ -0,0 +1,5 @@ + + + +Installationen mislykkedes på grund af en uspecificeret fejl. Download Brave igen. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_de.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_de.xtb new file mode 100644 index 00000000000..3be561fcaac --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_de.xtb @@ -0,0 +1,5 @@ + + + +Die Installation konnte aufgrund eines undefinierten Fehlers nicht abgeschlossen werden. Bitte lade Brave erneut herunter. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_el.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_el.xtb new file mode 100644 index 00000000000..0c44217d600 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_el.xtb @@ -0,0 +1,5 @@ + + + +Η εγκατάσταση απέτυχε λόγω μη καθορισμένου σφάλματος. Κατεβάστε το Brave ξανά. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_en-GB.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_en-GB.xtb new file mode 100644 index 00000000000..8056184a8d1 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_en-GB.xtb @@ -0,0 +1,5 @@ + + + +Installation failed due to unspecified error. Please download Brave again. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_es-419.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_es-419.xtb new file mode 100644 index 00000000000..2ab7a6008ad --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_es-419.xtb @@ -0,0 +1,5 @@ + + + +La instalación falló debido a un error no especificado. Descarga Brave otra vez. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_es.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_es.xtb new file mode 100644 index 00000000000..3cbe4b8e496 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_es.xtb @@ -0,0 +1,5 @@ + + + +La instalación ha fallado debido a un error no especificado. Vuelve a descargar Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_et.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_et.xtb new file mode 100644 index 00000000000..6affa0b8d51 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_et.xtb @@ -0,0 +1,5 @@ + + + +Installimine ebaõnnestus tundmatu vea tõttu. Laadige Brave uuesti alla. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_eu.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_eu.xtb new file mode 100644 index 00000000000..6d1d26047a8 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_eu.xtb @@ -0,0 +1,5 @@ + + + +Instalazioak huts egin du zehaztu gabeko errore batengatik. Deskargatu Brave berriro. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_fa.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_fa.xtb new file mode 100644 index 00000000000..e65a68d8b93 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_fa.xtb @@ -0,0 +1,5 @@ + + + +‏به دلیل خطای نامشخص، نصب ناموفق بود. لطفاً دوباره Brave را بارگیری کنید. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_fi.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_fi.xtb new file mode 100644 index 00000000000..e1acc34ebc6 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_fi.xtb @@ -0,0 +1,5 @@ + + + +Asennus epäonnistui määrittelemättömän virheen vuoksi. Lataa Brave uudelleen. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_fil.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_fil.xtb new file mode 100644 index 00000000000..eefa3356dba --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_fil.xtb @@ -0,0 +1,5 @@ + + + +Nabigo ang pag-install dahil sa hindi natukoy na error. Mangyaring i-download muli ang Brave. + \ No newline at end of file diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_fr-CA.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_fr-CA.xtb new file mode 100644 index 00000000000..2399d6d779d --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_fr-CA.xtb @@ -0,0 +1,5 @@ + + + +Échec de l'installation en raison d'une erreur non spécifiée. Veuillez télécharger Brave à nouveau. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_fr.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_fr.xtb new file mode 100644 index 00000000000..f2a1f2446c0 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_fr.xtb @@ -0,0 +1,5 @@ + + + +Échec de l'installation en raison d'une erreur non spécifiée. Veuillez télécharger Brave à nouveau. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_gl.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_gl.xtb new file mode 100644 index 00000000000..7222c6a6edb --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_gl.xtb @@ -0,0 +1,5 @@ + + + +Non se puido efectuar a instalación debido a un erro. Volve descargar Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_gu.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_gu.xtb new file mode 100644 index 00000000000..2adb7f804db --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_gu.xtb @@ -0,0 +1,5 @@ + + + +અનુલ્લેખિત ભૂલને કારણે ઇન્સ્ટોલેશન નિષ્ફળ રહ્યું. કૃપા કરીને Brave ફરીથી ડાઉનલોડ કરો. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_hi.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_hi.xtb new file mode 100644 index 00000000000..ab17f450c39 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_hi.xtb @@ -0,0 +1,5 @@ + + + +अनिर्दिष्ट कारणों से इंस्‍टॉलेशन विफल हुआ. कृपया Brave फिर से डाउनलोड करें. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_hr.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_hr.xtb new file mode 100644 index 00000000000..2289c464f6e --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_hr.xtb @@ -0,0 +1,5 @@ + + + +Instalacija nije uspjela zbog nepoznate pogreške. Ponovo preuzmite Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_hu.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_hu.xtb new file mode 100644 index 00000000000..78bff59ad21 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_hu.xtb @@ -0,0 +1,5 @@ + + + +A telepítés egy meg nem határozott hiba miatt nem sikerült. Kérjük, töltse le újra a Braveot. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_hy.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_hy.xtb new file mode 100644 index 00000000000..df6a9613786 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_hy.xtb @@ -0,0 +1,5 @@ + + + +Անհայտ սխալի պատճառով տեղադրումը չհաջողվեց: Նորից ներբեռնեք Brave-ը: + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_id.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_id.xtb new file mode 100644 index 00000000000..63c3d3d82aa --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_id.xtb @@ -0,0 +1,5 @@ + + + +Pemasangan gagal karena kesalahan yang tidak ditentukan. Download Brave lagi. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_is.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_is.xtb new file mode 100644 index 00000000000..6de38bc41fc --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_is.xtb @@ -0,0 +1,5 @@ + + + +Uppsetning mistókst vegna ótilgreindrar villu. Sæktu Brave aftur. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_it.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_it.xtb new file mode 100644 index 00000000000..000511061a3 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_it.xtb @@ -0,0 +1,5 @@ + + + +Installazione non riuscita a causa di un errore imprecisato. Scarica di nuovo Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_iw.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_iw.xtb new file mode 100644 index 00000000000..9f0514a3569 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_iw.xtb @@ -0,0 +1,5 @@ + + + +‏ההתקנה נכשלה בשל שגיאה לא מזוהה. יש להוריד שוב את Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ja.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ja.xtb new file mode 100644 index 00000000000..0fcc1db3495 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ja.xtb @@ -0,0 +1,5 @@ + + + +原因不明のエラーによりインストールに失敗しました。Brave をもう一度ダウンロードしてください。 + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ka.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ka.xtb new file mode 100644 index 00000000000..5de578a00a9 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ka.xtb @@ -0,0 +1,5 @@ + + + +ინსტალაცია ვერ განხორციელდა გაურკვეველი შეცდომის გამო. ხელახლა ჩამოტვირთეთ Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_kk.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_kk.xtb new file mode 100644 index 00000000000..4150d7601bc --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_kk.xtb @@ -0,0 +1,5 @@ + + + +Орнату анықталмаған қате себебінен сәтсіз аяқталды. Brave браузерін қайта жүктеңіз. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_km.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_km.xtb new file mode 100644 index 00000000000..91b41dd2ae9 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_km.xtb @@ -0,0 +1,5 @@ + + + +ការតំឡើងបានបរាជ័យដោយសារកំហុសឆ្គងដែលមិនជាក់លាក់។ សូមទាញយក Brave ម្តងទៀត។ + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_kn.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_kn.xtb new file mode 100644 index 00000000000..649f5b97249 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_kn.xtb @@ -0,0 +1,5 @@ + + + +ಅನಿರ್ದಿಷ್ಟ ದೋಷದಿಂದಾಗಿ ಸ್ಥಾಪನೆ ವಿಫಲವಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೊಮ್ಮೆ Brave ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ko.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ko.xtb new file mode 100644 index 00000000000..444d927de1c --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ko.xtb @@ -0,0 +1,5 @@ + + + +알 수 없는 오류로 인해 설치에 실패했습니다. Brave을 다시 다운로드하세요. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ky.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ky.xtb new file mode 100644 index 00000000000..84f7922dce4 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ky.xtb @@ -0,0 +1,5 @@ + + + +Белгиси катадан улам, орнотулбай калды. Brave'ду кайра жүктөп алыңыз. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_lo.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_lo.xtb new file mode 100644 index 00000000000..43f1aae55fa --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_lo.xtb @@ -0,0 +1,5 @@ + + + +ການ​ຕິດ​ຕັ້ງ​ບໍ່​ສໍາ​ເລັດ ​ເນື່ອງ​ຈາກ​ຄວາມຜິດພາດທີ່ບໍ່ໄດ້ລະບຸ​. ກະ​ລຸ​ນາ​ດາວ​ໂຫລດ Brave ອີກ​. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_lt.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_lt.xtb new file mode 100644 index 00000000000..7ca0a78e43d --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_lt.xtb @@ -0,0 +1,5 @@ + + + +Nepavyko įdiegti dėl nenurodytos klaidos. Atsisiųskite „Brave“ dar kartą. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_lv.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_lv.xtb new file mode 100644 index 00000000000..fc4d93af30a --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_lv.xtb @@ -0,0 +1,5 @@ + + + +Instalēšana neizdevās nenoteiktas kļūdas dēļ. Lejupielādējiet pārlūku Brave vēlreiz. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_mk.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_mk.xtb new file mode 100644 index 00000000000..482c10f3bdc --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_mk.xtb @@ -0,0 +1,5 @@ + + + +Инсталирањето не успеа поради неназначена грешка. Преземете го Brave повторно. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ml.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ml.xtb new file mode 100644 index 00000000000..dfb4e13894a --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ml.xtb @@ -0,0 +1,5 @@ + + + +അവ്യക്തമായ പിശകിനാൽ ഇൻസ്റ്റാൾ ചെയ്യൽ പരാജയപ്പെട്ടു. Brave വീണ്ടും ഡൗൺലോഡ് ചെയ്യുക. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_mn.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_mn.xtb new file mode 100644 index 00000000000..8fd48fb38ef --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_mn.xtb @@ -0,0 +1,5 @@ + + + +Гэнэтийн алдаанаас болж суулгах ажиллагаа амжилтгүй боллоо. Brave-ыг дахин татаж авна уу. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_mr.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_mr.xtb new file mode 100644 index 00000000000..06efce7b677 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_mr.xtb @@ -0,0 +1,5 @@ + + + +नमूद न केलेल्या एररमुळे स्थापना अयशस्वी झाली. कृपया Brave पुन्‍हा डाउनलोड करा. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ms.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ms.xtb new file mode 100644 index 00000000000..2f277daf052 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ms.xtb @@ -0,0 +1,5 @@ + + + +Pemasangan gagal disebabkan ralat yang tidak dinyatakan. Sila muat turun semula Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_my.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_my.xtb new file mode 100644 index 00000000000..e30ebb3f2f2 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_my.xtb @@ -0,0 +1,5 @@ + + + +မသိရသည့် အမှားတစ်ခုကြောင့် တပ်ဆင်မှု မအေင်မြင်ခဲ့ပါ။ ကျေးဇူးပြုပြီး Brave ကို ထပ်ပြီး ဒေါင်းလုဒ် လုပ်ယူပါ။ + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ne.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ne.xtb new file mode 100644 index 00000000000..959f06f512d --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ne.xtb @@ -0,0 +1,5 @@ + + + +अनिश् + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_nl.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_nl.xtb new file mode 100644 index 00000000000..02ced5831e8 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_nl.xtb @@ -0,0 +1,5 @@ + + + +De installatie is mislukt wegens een onbekende fout. Download Brave opnieuw. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_no.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_no.xtb new file mode 100644 index 00000000000..4b646c66d9e --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_no.xtb @@ -0,0 +1,5 @@ + + + +Installeringen mislyktes på grunn av en uspesifisert feil. Last ned Brave på nytt. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_or.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_or.xtb new file mode 100644 index 00000000000..88e52fb6d59 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_or.xtb @@ -0,0 +1,5 @@ + + + +ଅନିର୍ଦ୍ଦିଷ୍ଟ ତ୍ରୁଟି ଯୋଗୁଁ ଇନ୍‌ଷ୍ଟଲେସନ୍ ବିଫଳ ହୋଇଛି। ଦୟାକରି Brave ପୁଣି ଡାଉନ୍‌ଲୋଡ୍ କରନ୍ତୁ। + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_pa.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_pa.xtb new file mode 100644 index 00000000000..e60e2613a8c --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_pa.xtb @@ -0,0 +1,5 @@ + + + +ਅਨਿਸ਼ਚਿਤ ਗੜਬੜ ਕਾਰਨ ਸਥਾਪਨਾ ਅਸਫਲ ਹੋ ਗਈ। ਕਿਰਪਾ ਕਰਕੇ Brave ਨੂੰ ਦੁਬਾਰਾ ਡਾਊਨਲੋਡ ਕਰੋ। + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_pl.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_pl.xtb new file mode 100644 index 00000000000..a2cbecd9a10 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_pl.xtb @@ -0,0 +1,5 @@ + + + +Instalacja nie powiodła się z powodu nieokreślonego błędu. Pobierz Brave ponownie. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_pt-BR.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_pt-BR.xtb new file mode 100644 index 00000000000..946b57da979 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_pt-BR.xtb @@ -0,0 +1,5 @@ + + + +Falha na instalação devido a um erro não especificado. Baixe o Brave novamente. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_pt-PT.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_pt-PT.xtb new file mode 100644 index 00000000000..228562783d0 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_pt-PT.xtb @@ -0,0 +1,5 @@ + + + +A instalação falhou devido a um erro não especificado. Descarregue novamente o Brave . + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ro.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ro.xtb new file mode 100644 index 00000000000..e465f104c2f --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ro.xtb @@ -0,0 +1,5 @@ + + + +Instalarea nu a reușit din cauza unei erori neprecizate. Descărcați Brave din nou. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ru.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ru.xtb new file mode 100644 index 00000000000..5dc0df9d528 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ru.xtb @@ -0,0 +1,5 @@ + + + +В процессе установки произошла неизвестная ошибка. Скачайте Brave ещё раз. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_si.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_si.xtb new file mode 100644 index 00000000000..958b3bfe905 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_si.xtb @@ -0,0 +1,5 @@ + + + +නිශ්චිත නොමැති දෝෂයක් හේතුවෙන් ස්ථාපනය අසාර්ථක විය. නැවතත් Brave බාගන්න. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_sk.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_sk.xtb new file mode 100644 index 00000000000..cc6a40596e6 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_sk.xtb @@ -0,0 +1,5 @@ + + + +Inštalácia zlyhala kvôli neznámej chybe. Skúste prehliadač Brave stiahnuť znova. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_sl.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_sl.xtb new file mode 100644 index 00000000000..ca90abf34a3 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_sl.xtb @@ -0,0 +1,5 @@ + + + +Namestitev ni uspela zaradi nenavedene napake. Znova prenesite Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_sq.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_sq.xtb new file mode 100644 index 00000000000..f79a2353c78 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_sq.xtb @@ -0,0 +1,5 @@ + + + +Instalimi dështoi për shkak të një gabimi të papërcaktuar. Shkarko përsëri Brave. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_sr-Latn.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_sr-Latn.xtb new file mode 100644 index 00000000000..f2c2b9177b6 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_sr-Latn.xtb @@ -0,0 +1,5 @@ + + + +Instalacija nije uspela zbog neodređene greške. Preuzmite Brave ponovo. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_sr.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_sr.xtb new file mode 100644 index 00000000000..5ab9ce86dd1 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_sr.xtb @@ -0,0 +1,5 @@ + + + +Инсталација није успела због неодређене грешке. Преузмите Браве поново. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_sv.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_sv.xtb new file mode 100644 index 00000000000..379973793da --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_sv.xtb @@ -0,0 +1,5 @@ + + + +Installationen misslyckades på grund av ett okänt fel. Ladda ned Brave igen. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_sw.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_sw.xtb new file mode 100644 index 00000000000..9347e5609c8 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_sw.xtb @@ -0,0 +1,5 @@ + + + +Usakinishaji ulishindwa kwa sababu ya hitilafu isiyobainika. Tafadhali pakua Brave tena. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ta.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ta.xtb new file mode 100644 index 00000000000..4bbde3efe47 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ta.xtb @@ -0,0 +1,5 @@ + + + +குறிப்பிடப்படாத பிழை காரணமாக நிறுவல் தோல்வியடைந்தது. Braveமை மீண்டும் பதிவிறக்கம் செய்க. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_te.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_te.xtb new file mode 100644 index 00000000000..e8beeeb2a0a --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_te.xtb @@ -0,0 +1,5 @@ + + + +తెలియ‌ని ఎర్ర‌ర్‌ కారణంగా ఇన‌స్ట‌లేష‌న్‌ విఫలమైంది. దయచేసి Braveను మళ్లీ డౌన్‌లోడ్ చేయండి. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_th.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_th.xtb new file mode 100644 index 00000000000..4035f44247d --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_th.xtb @@ -0,0 +1,5 @@ + + + +การติดตั้งล้มเหลวเนื่องจากเกิดข้อผิดพลาดที่ไม่ระบุ โปรดดาวน์โหลด Brave อีกครั้ง + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_tr.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_tr.xtb new file mode 100644 index 00000000000..12719c3c21a --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_tr.xtb @@ -0,0 +1,5 @@ + + + +Yükleme belirtilmeyen bir hata nedeniyle başarısız oldu. Lütfen Brave'u tekrar indirin. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_uk.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_uk.xtb new file mode 100644 index 00000000000..54a36ea311f --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_uk.xtb @@ -0,0 +1,5 @@ + + + +Не вдалося встановити через невизначену помилку. Завантажте Brave ще раз. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_ur.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_ur.xtb new file mode 100644 index 00000000000..dec8789e1b3 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_ur.xtb @@ -0,0 +1,5 @@ + + + +‏غیر متعین خرابی کی وجہ سے انسٹالیشن ناکام ہوگیا۔ براہ کرم Brave دوبارہ ڈاؤن لوڈ کریں۔ + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_uz.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_uz.xtb new file mode 100644 index 00000000000..924c28e2b52 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_uz.xtb @@ -0,0 +1,5 @@ + + + +O‘rnatish vaqtida kutilmagan xatolik yuz berdi. Brave‘ni qaytadan yuklab oling. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_vi.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_vi.xtb new file mode 100644 index 00000000000..651bc6111f4 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_vi.xtb @@ -0,0 +1,5 @@ + + + +Không thể cài đặt do xảy ra lỗi không xác định. Hãy tải xuống Brave lại lần nữa. + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_zh-CN.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_zh-CN.xtb new file mode 100644 index 00000000000..53f18e25325 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_zh-CN.xtb @@ -0,0 +1,5 @@ + + + +未指定的错误导致安装失败。请重新下载 Brave。 + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_zh-HK.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_zh-HK.xtb new file mode 100644 index 00000000000..6d6fdbf1640 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_zh-HK.xtb @@ -0,0 +1,5 @@ + + + +不明錯誤導致安裝失敗,請重新下載 Brave。 + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_zh-TW.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_zh-TW.xtb new file mode 100644 index 00000000000..12f90468c81 --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_zh-TW.xtb @@ -0,0 +1,5 @@ + + + +不明錯誤導致安裝失敗,請重新下載 Brave。 + diff --git a/chromium_src/chrome/installer/setup/resources/setup_resources_zu.xtb b/chromium_src/chrome/installer/setup/resources/setup_resources_zu.xtb new file mode 100644 index 00000000000..ffbe5a16e2d --- /dev/null +++ b/chromium_src/chrome/installer/setup/resources/setup_resources_zu.xtb @@ -0,0 +1,5 @@ + + + +Ukufakwa kuhlulekile ngenxa yephutha elingacacisiwe. Sicela ulande i-Brave futhi. + diff --git a/chromium_src/chrome/installer/setup/setup_main.cc b/chromium_src/chrome/installer/setup/setup_main.cc index d7289877927..653430e6f06 100644 --- a/chromium_src/chrome/installer/setup/setup_main.cc +++ b/chromium_src/chrome/installer/setup/setup_main.cc @@ -10,13 +10,74 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/path_service.h" +#include "brave/installer/setup/archive_patch_helper.h" #include "chrome/common/chrome_paths.h" +#include "chrome/installer/setup/brand_behaviors.h" +#include "chrome/installer/setup/installer_state.h" +#include "chrome/installer/setup/modify_params.h" #include "chrome/installer/setup/setup_util.h" +#include "chrome/installer/util/google_update_settings.h" +#include "chrome/installer/util/initial_preferences.h" #include "chrome/installer/util/install_util.h" +#include "chrome/installer/util/installation_state.h" +#include "chrome/installer/util/installer_util_strings.h" #include "chrome/installer/util/util_constants.h" namespace { +// The code in this function used to be upstream and had to be restored in Brave +// to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +bool BraveHandleNonInstallCmdLineOptions( + installer::ModifyParams& modify_params, + const base::CommandLine& cmd_line, + const installer::InitialPreferences& prefs, + int* exit_code) { + if (!cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { + return false; + } + installer::InstallerState* installer_state = + &(*modify_params.installer_state); + const base::FilePath& setup_exe = *modify_params.setup_path; + + installer_state->SetStage(installer::UPDATING_SETUP); + installer::InstallStatus status = installer::SETUP_PATCH_FAILED; + // If --update-setup-exe command line option is given, we apply the given + // patch to current exe, and store the resulting binary in the path + // specified by --new-setup-exe. But we need to first unpack the file + // given in --update-setup-exe. + + const base::FilePath compressed_archive( + cmd_line.GetSwitchValuePath(installer::switches::kUpdateSetupExe)); + VLOG(1) << "Opening archive " << compressed_archive.value(); + // The top unpack failure result with 28 days aggregation (>=0.01%) + // Setup.Install.LzmaUnPackResult_SetupExePatch + // 0.02% PATH_NOT_FOUND + // + // More information can also be found with metric: + // Setup.Install.LzmaUnPackNTSTATUS_SetupExePatch + + // We use the `new_setup_exe` directory as the working directory for + // `ArchivePatchHelper::UncompressAndPatch`. For System installs, this + // directory would be under %ProgramFiles% (a directory that only admins can + // write to by default) and hence a secure location. + const base::FilePath new_setup_exe( + cmd_line.GetSwitchValuePath(installer::switches::kNewSetupExe)); + if (installer::ArchivePatchHelper::UncompressAndPatch( + new_setup_exe.DirName(), compressed_archive, setup_exe, new_setup_exe, + installer::UnPackConsumer::SETUP_EXE_PATCH)) { + status = installer::NEW_VERSION_UPDATED; + } + + *exit_code = InstallUtil::GetInstallReturnCode(status); + if (*exit_code) { + LOG(WARNING) << "setup.exe patching failed."; + installer_state->WriteInstallerResult(status, IDS_SETUP_PATCH_FAILED_BASE, + nullptr); + } + return true; +} + constexpr char kBraveReferralCode[] = "brave-referral-code"; void SavePromoCode(installer::InstallStatus install_status) { @@ -44,5 +105,23 @@ void SavePromoCode(installer::InstallStatus install_status) { #define DoLegacyCleanups \ SavePromoCode(install_status); \ DoLegacyCleanups + +// The macros BRAVE_SETUP_MAIN, UpdateInstallStatus and BRAVE_INSTALL_PRODUCTS +// contain code that used to be upstream and had to be restored in Brave to +// support delta updates on Windows until we are on Omaha 4. See +// github.com/brave/brave-core/pull/31937. +#define BRAVE_SETUP_MAIN \ + if (BraveHandleNonInstallCmdLineOptions(modify_params, cmd_line, prefs, \ + &exit_code)) { \ + return exit_code; \ + } +#define BRAVE_INSTALL_PRODUCTS UpdateInstallStatus(); +#define UpdateInstallStatus() \ + UpdateInstallStatus(installer_state->archive_type, install_status) + #include + +#undef UpdateInstallStatus +#undef BRAVE_INSTALL_PRODUCTS +#undef BRAVE_SETUP_MAIN #undef DoLegacyCleanups diff --git a/chromium_src/chrome/installer/setup/sources.gni b/chromium_src/chrome/installer/setup/sources.gni index 62a7aaee600..df7a05942a7 100644 --- a/chromium_src/chrome/installer/setup/sources.gni +++ b/chromium_src/chrome/installer/setup/sources.gni @@ -5,31 +5,47 @@ import("//brave/components/brave_vpn/common/buildflags/buildflags.gni") -brave_chromium_src_chrome_installer_setup_sources = [] -brave_chromium_src_chrome_installer_setup_deps = [] +assert(is_win) -if (is_win) { +brave_chromium_src_chrome_installer_setup_sources = [ + # We try to avoid adding entries to upstream `sources`, but there is a + # circular dependency here that seems hard to avoid in any other way: + # archive_patch_helper.cc depends on chrome/installer/setup:lib because it + # needs setup_util.cc. At the same time, chrome/installer/setup:lib indirectly + # depends on archive_patch_helper.cc via its own unpack_archive.cc. + "//brave/installer/setup/archive_patch_helper.cc", + "//brave/installer/setup/archive_patch_helper.h", + + # Similarly to above, brave_setup_util.cc depends on + # chrome/installer/setup:lib via installer_state.cc. And that GN target + # depends on brave_setup_util.cc via unpack_archive.cc. The only feasible way + # to resolve this circular dependency seems to be add to upstream's `sources`. + "//brave/installer/setup/brave_setup_util.cc", + "//brave/installer/setup/brave_setup_util.h", +] +brave_chromium_src_chrome_installer_setup_deps = [ + "//brave/components/brave_vpn/common/buildflags", + "//brave/installer/util", + "//brave/third_party/bspatch", + "//chrome/installer/util:work_item", + "//components/zucchini:zucchini_io", + "//components/zucchini:zucchini_lib", +] + +if (enable_brave_vpn) { brave_chromium_src_chrome_installer_setup_deps += [ - "//brave/components/brave_vpn/common/buildflags", - "//brave/installer/util", - "//chrome/installer/util:work_item", + "//brave/browser/brave_vpn/win:wireguard_utils", + "//brave/browser/brave_vpn/win/brave_vpn_helper:common", + "//brave/browser/brave_vpn/win/brave_vpn_wireguard_service:install_utils", + "//brave/components/brave_vpn/browser/connection/ikev2/win:ras_utils", + ] +} + +if (is_official_build) { + # These should be added to the lib target, but don't want to add another + # patch. + brave_chromium_src_chrome_installer_setup_sources += [ + "channel_override_work_item.cc", + "channel_override_work_item.h", ] - - if (enable_brave_vpn) { - brave_chromium_src_chrome_installer_setup_deps += [ - "//brave/browser/brave_vpn/win:wireguard_utils", - "//brave/browser/brave_vpn/win/brave_vpn_helper:common", - "//brave/browser/brave_vpn/win/brave_vpn_wireguard_service:install_utils", - "//brave/components/brave_vpn/browser/connection/ikev2/win:ras_utils", - ] - } - - if (is_official_build) { - # These should be added to the lib target, but don't want to add another - # patch. - brave_chromium_src_chrome_installer_setup_sources += [ - "channel_override_work_item.cc", - "channel_override_work_item.h", - ] - } } diff --git a/chromium_src/chrome/installer/setup/unpack_archive.cc b/chromium_src/chrome/installer/setup/unpack_archive.cc new file mode 100644 index 00000000000..46e6ce5c77f --- /dev/null +++ b/chromium_src/chrome/installer/setup/unpack_archive.cc @@ -0,0 +1,254 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// The code in this file used to be upstream and had to be restored in Brave to +// support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +// N.B.: This file does not #include upstream's implementation. + +#include "chrome/installer/setup/unpack_archive.h" + +#include + +#include "base/check.h" +#include "base/check_op.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/types/expected.h" +#include "base/types/expected_macros.h" +#include "base/version.h" +#include "brave/installer/setup/archive_patch_helper.h" +#include "brave/installer/setup/brave_setup_util.h" +#include "chrome/installer/setup/installer_state.h" +#include "chrome/installer/setup/setup_constants.h" +#include "chrome/installer/util/installation_state.h" +#include "chrome/installer/util/installer_util_strings.h" +#include "chrome/installer/util/util_constants.h" + +namespace installer { + +namespace { + +// Returns nullptr if no compressed archive is available for processing, +// otherwise returns a patch helper configured to uncompress and patch. +std::unique_ptr CreateChromeArchiveHelper( + const base::FilePath& setup_exe, + const base::FilePath& install_archive, + const InstallerState& installer_state, + const base::FilePath& working_directory, + UnPackConsumer consumer) { + // A compressed archive is ordinarily given on the command line by the mini + // installer. If one was not given, look for chrome.packed.7z next to the + // running program. + base::FilePath compressed_archive = + install_archive.empty() + ? setup_exe.DirName().Append(kChromeCompressedArchive) + : install_archive; + + // Fail if no compressed archive is found. + if (!base::PathExists(compressed_archive)) { + LOG_IF(ERROR, !install_archive.empty()) + << switches::kInstallArchive << "=" << compressed_archive.value() + << " not found."; + return nullptr; + } + + // chrome.7z is either extracted directly from the compressed archive into the + // working dir or is the target of patching in the working dir. + base::FilePath target(working_directory.Append(kChromeArchive)); + DCHECK(!base::PathExists(target)); + + // Specify an empty path for the patch source since it isn't yet known that + // one is needed. It will be supplied in UncompressAndPatchChromeArchive if it + // is. + return std::make_unique( + working_directory, compressed_archive, base::FilePath(), target, + consumer); +} + +} // namespace + +// Workhorse for producing an uncompressed archive (chrome.7z) given a +// chrome.packed.7z containing either a patch file based on the version of +// chrome being updated or the full uncompressed archive. Returns true on +// success, in which case |archive_type| is populated based on what was found. +// Returns false on failure, in which case |install_status| contains the error +// code and the result is written to the registry (via WriteInstallerResult). +base::expected UncompressAndPatchChromeArchive( + const InstallationState& original_state, + const InstallerState& installer_state, + ArchivePatchHelper* archive_helper, + ArchiveType* archive_type, + const base::Version& previous_version) { + installer_state.SetStage(UNCOMPRESSING); + + // UMA tells us the following about the time required for uncompression as of + // M75: + // --- Foreground (<10%) --- + // Full archive: 7.5s (50%ile) / 52s (99%ile) + // Archive patch: <2s (50%ile) / 10-20s (99%ile) + // --- Background (>90%) --- + // Full archive: 22s (50%ile) / >3m (99%ile) + // Archive patch: ~2s (50%ile) / 1.5m - >3m (99%ile) + // + // The top unpack failure result with 28 days aggregation (>=0.01%) + // Setup.Install.LzmaUnPackResult_CompressedChromeArchive + // 13.50% DISK_FULL + // 0.67% ERROR_NO_SYSTEM_RESOURCES + // 0.12% ERROR_IO_DEVICE + // 0.05% INVALID_HANDLE + // 0.01% INVALID_LEVEL + // 0.01% FILE_NOT_FOUND + // 0.01% LOCK_VIOLATION + // 0.01% ACCESS_DENIED + // + // Setup.Install.LzmaUnPackResult_ChromeArchivePatch + // 0.09% DISK_FULL + // 0.01% FILE_NOT_FOUND + // + // More information can also be found with metrics: + // Setup.Install.LzmaUnPackNTSTATUS_CompressedChromeArchive + // Setup.Install.LzmaUnPackNTSTATUS_ChromeArchivePatch + if (!archive_helper->Uncompress(nullptr)) { + installer_state.WriteInstallerResult( + UNCOMPRESSION_FAILED, IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, nullptr); + return base::unexpected(UNCOMPRESSION_FAILED); + } + + // Short-circuit if uncompression produced the uncompressed archive rather + // than a patch file. + if (base::PathExists(archive_helper->target())) { + *archive_type = FULL_ARCHIVE_TYPE; + return base::ok(); + } + + // Find the installed version's archive to serve as the source for patching. + base::FilePath patch_source( + FindArchiveToPatch(original_state, installer_state, previous_version)); + if (patch_source.empty()) { + LOG(ERROR) << "Failed to find archive to patch."; + installer_state.WriteInstallerResult(DIFF_PATCH_SOURCE_MISSING, + IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, + nullptr); + return base::unexpected(DIFF_PATCH_SOURCE_MISSING); + } + archive_helper->set_patch_source(patch_source); + + // UMA tells us the following about the time required for patching as of M75: + // --- Foreground --- + // 12s (50%ile) / 3-6m (99%ile) + // --- Background --- + // 1m (50%ile) / >60m (99%ile) + installer_state.SetStage(PATCHING); + if (!archive_helper->ApplyAndDeletePatch()) { + installer_state.WriteInstallerResult(APPLY_DIFF_PATCH_FAILED, + IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, + nullptr); + return base::unexpected(APPLY_DIFF_PATCH_FAILED); + } + + *archive_type = INCREMENTAL_ARCHIVE_TYPE; + return base::ok(); +} + +base::expected UnpackChromeArchive( + const base::FilePath& unpack_path, + InstallationState& original_state, + const base::FilePath& setup_exe, + const base::CommandLine& cmd_line, + InstallerState& installer_state) { + installer_state.archive_type = UNKNOWN_ARCHIVE_TYPE; + base::FilePath install_archive = + cmd_line.GetSwitchValuePath(switches::kInstallArchive); + // If this is an uncompressed installation then pass the uncompressed + // chrome.7z directly, so the chrome.packed.7z unpacking step will be + // bypassed. + installer_state.uncompressed_archive = + cmd_line.GetSwitchValuePath(switches::kUncompressedArchive); + if (!install_archive.empty() || + installer_state.uncompressed_archive.empty()) { + if (!installer_state.uncompressed_archive.empty()) { + LOG(ERROR) + << "A compressed archive and an uncompressed archive were both " + "provided. This is unsupported. Please provide one archive."; + return base::unexpected(UNSUPPORTED_OPTION); + } + base::Version previous_version; + if (cmd_line.HasSwitch(switches::kPreviousVersion)) { + previous_version = base::Version( + cmd_line.GetSwitchValueASCII(switches::kPreviousVersion)); + } + + std::unique_ptr archive_helper( + CreateChromeArchiveHelper( + setup_exe, install_archive, installer_state, unpack_path, + (previous_version.IsValid() + ? UnPackConsumer::CHROME_ARCHIVE_PATCH + : UnPackConsumer::COMPRESSED_CHROME_ARCHIVE))); + if (archive_helper) { + VLOG(1) << "Installing Chrome from compressed archive " + << archive_helper->compressed_archive().value(); + RETURN_IF_ERROR(UncompressAndPatchChromeArchive( + original_state, installer_state, archive_helper.get(), + &installer_state.archive_type, previous_version)); + installer_state.uncompressed_archive = archive_helper->target(); + DCHECK(!installer_state.uncompressed_archive.empty()); + } + } + + // Check for an uncompressed archive alongside the current executable if one + // was not given or generated. + if (installer_state.uncompressed_archive.empty()) { + installer_state.uncompressed_archive = + setup_exe.DirName().Append(kChromeArchive); + } + + if (installer_state.archive_type == UNKNOWN_ARCHIVE_TYPE) { + // An archive was not uncompressed or patched above. + if (installer_state.uncompressed_archive.empty() || + !base::PathExists(installer_state.uncompressed_archive)) { + LOG(ERROR) << "Cannot install Chrome without an uncompressed archive."; + installer_state.WriteInstallerResult( + INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, nullptr); + return base::unexpected(INVALID_ARCHIVE); + } + installer_state.archive_type = FULL_ARCHIVE_TYPE; + } + + // Unpack the uncompressed archive. + // UMA tells us the following about the time required to unpack as of M75: + // --- Foreground --- + // <2.7s (50%ile) / 45s (99%ile) + // --- Background --- + // ~14s (50%ile) / >3m (99%ile) + // + // The top unpack failure result with 28 days aggregation (>=0.01%) + // Setup.Install.LzmaUnPackResult_UncompressedChromeArchive + // 0.66% DISK_FULL + // 0.04% ACCESS_DENIED + // 0.01% INVALID_HANDLE + // 0.01% ERROR_NO_SYSTEM_RESOURCES + // 0.01% PATH_NOT_FOUND + // 0.01% ERROR_IO_DEVICE + // + // More information can also be found with metric: + // Setup.Install.LzmaUnPackNTSTATUS_UncompressedChromeArchive + installer_state.SetStage(UNPACKING); + UnPackStatus unpack_status = + UnPackArchive(installer_state.uncompressed_archive, unpack_path, + /*output_file=*/nullptr); + RecordUnPackMetrics(unpack_status, + UnPackConsumer::UNCOMPRESSED_CHROME_ARCHIVE); + if (unpack_status != UNPACK_NO_ERROR) { + installer_state.WriteInstallerResult( + UNPACKING_FAILED, IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, nullptr); + return base::unexpected(UNPACKING_FAILED); + } + return base::ok(installer_state.uncompressed_archive); +} + +} // namespace installer diff --git a/chromium_src/chrome/installer/setup/unpack_archive.h b/chromium_src/chrome/installer/setup/unpack_archive.h new file mode 100644 index 00000000000..74511d815bb --- /dev/null +++ b/chromium_src/chrome/installer/setup/unpack_archive.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_UNPACK_ARCHIVE_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_UNPACK_ARCHIVE_H_ + +// N.B. This file does not #include upstream's implementation. + +#include "base/types/expected.h" +#include "chrome/installer/util/util_constants.h" + +namespace base { +class CommandLine; +class FilePath; +} // namespace base + +namespace installer { + +class InstallationState; +class InstallerState; + +// The sole purpose of this declaration is to change the installer_state +// parameter from const to non-const. This lets us stuff return values into +// installer_state in a way that otherwise preserves upstream's function +// signatures. Specifically: +// +// This function used to have additional parameters ArchiveType* archive_type +// and base::FilePath& uncompressed_archive. Upstream removed them when it +// moved the logic for differential updates into Omaha 4. But we are still on +// Omaha 3 on Windows and therefore need to preserve the old functionality. We +// do this by storing (and returning) the archive_type and uncompressed_archive +// values in the installer_state object. +base::expected UnpackChromeArchive( + const base::FilePath& unpack_path, + InstallationState& original_state, + const base::FilePath& setup_exe, + const base::CommandLine& cmd_line, + InstallerState& installer_state); + +} // namespace installer + +#endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_SETUP_UNPACK_ARCHIVE_H_ diff --git a/chromium_src/chrome/installer/setup/unpack_archive_unittest.cc b/chromium_src/chrome/installer/setup/unpack_archive_unittest.cc new file mode 100644 index 00000000000..3151289b83b --- /dev/null +++ b/chromium_src/chrome/installer/setup/unpack_archive_unittest.cc @@ -0,0 +1,38 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include + +namespace installer { + +// This test used to be upstream and had to be restored in Brave to support +// delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +TEST_P(SetupUnpackArchiveTest, UnpackArchiveSetsUncompressedArchive) { + base::FilePath chrome_archive = GetParam().test_file; + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + InstallationState original_state; // Unused when not patching. + base::CommandLine cmd_line = base::CommandLine::FromString(L"setup.exe"); + cmd_line.AppendSwitchPath(GetParam().archive_switch, chrome_archive); + FakeInstallerState installer_state; + + ASSERT_THAT( + UnpackChromeArchive( + temp_dir.GetPath(), original_state, + base::FilePath(), // Unused when archive is provided via cmd_line. + cmd_line, installer_state), + base::test::HasValue()); + + EXPECT_EQ(installer_state.uncompressed_archive, + GetParam().uncompressed_output_matches_input_file + ? chrome_archive + : temp_dir.GetPath().Append(FILE_PATH_LITERAL("chrome.7z"))); + ASSERT_EQ(installer_state.archive_type, ArchiveType::FULL_ARCHIVE_TYPE); +} + +} // namespace installer diff --git a/chromium_src/chrome/installer/util/google_update_settings.cc b/chromium_src/chrome/installer/util/google_update_settings.cc new file mode 100644 index 00000000000..9efa6699b04 --- /dev/null +++ b/chromium_src/chrome/installer/util/google_update_settings.cc @@ -0,0 +1,66 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#include "chrome/installer/util/google_update_settings.h" + +#define UpdateInstallStatus UpdateInstallStatus_Unused +#define UpdateGoogleUpdateApKey UpdateGoogleUpdateApKey_Unused +#include +#undef UpdateGoogleUpdateApKey +#undef UpdateInstallStatus + +void GoogleUpdateSettings::UpdateInstallStatus( + bool system_install, + installer::ArchiveType archive_type, + int install_return_code) { + DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE || + install_return_code != 0); + + installer::AdditionalParameters additional_parameters; + if (UpdateGoogleUpdateApKey(archive_type, install_return_code, + &additional_parameters) && + !additional_parameters.Commit()) { + PLOG(ERROR) << "Failed to write to application's ClientState key " + << google_update::kRegApField << " = " + << additional_parameters.value(); + } +} + +bool GoogleUpdateSettings::UpdateGoogleUpdateApKey( + installer::ArchiveType archive_type, + int install_return_code, + installer::AdditionalParameters* additional_parameters) { + DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE || + install_return_code != 0); + bool modified = false; + + if (archive_type == installer::FULL_ARCHIVE_TYPE || !install_return_code) { + if (additional_parameters->SetFullSuffix(false)) { + VLOG(1) << "Removed incremental installer failure key; " + "switching to channel: " + << additional_parameters->value(); + modified = true; + } + } else if (archive_type == installer::INCREMENTAL_ARCHIVE_TYPE) { + if (additional_parameters->SetFullSuffix(true)) { + VLOG(1) << "Incremental installer failed; switching to channel: " + << additional_parameters->value(); + modified = true; + } else { + VLOG(1) << "Incremental installer failure; already on channel: " + << additional_parameters->value(); + } + } else { + // It's okay if we don't know the archive type. In this case, leave the + // "-full" suffix as we found it. + DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE, archive_type); + } + + return modified; +} diff --git a/chromium_src/chrome/installer/util/google_update_settings.h b/chromium_src/chrome/installer/util/google_update_settings.h new file mode 100644 index 00000000000..64d30f934fb --- /dev/null +++ b/chromium_src/chrome/installer/util/google_update_settings.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file changes function signatures that used to be upstream and had to be +// restored in Brave to support delta updates on Windows until we are on Omaha +// 4. See github.com/brave/brave-core/pull/31937. + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_UTIL_GOOGLE_UPDATE_SETTINGS_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_UTIL_GOOGLE_UPDATE_SETTINGS_H_ + +// This method changes the Google Update "ap" value to move the installation +// on to or off of one of the recovery channels. +// - If incremental installer fails we append a magic string ("-full"), if +// it is not present already, so that Google Update server next time will send +// full installer to update Chrome on the local machine +// - If we are currently running full installer, we remove this magic +// string (if it is present) regardless of whether installer failed or not. +// There is no fall-back for full installer :) +// - Unconditionally clear a legacy "-stage:" modifier. +#define UpdateInstallStatus \ + UpdateInstallStatus(bool system_install, \ + installer::ArchiveType archive_type, \ + int install_return_code); \ + static void UpdateInstallStatus_Unused + +// This method updates the value for Google Update "ap" key for Chrome +// based on whether we are doing incremental install (or not) and whether +// the install succeeded. +// - If install worked, remove the magic string (if present). +// - If incremental installer failed, append a magic string (if +// not present already). +// - If full installer failed, still remove this magic +// string (if it is present already). +// Additionally, any legacy ""-stage:*" values are +// unconditionally removed. +// +// archive_type: tells whether this is incremental install or not. +// install_return_code: if 0, means installation was successful. +// value: current value of Google Update "ap" key. +#define UpdateGoogleUpdateApKey \ + UpdateGoogleUpdateApKey(installer::ArchiveType archive_type, \ + int install_return_code, \ + installer::AdditionalParameters* value); \ + static bool UpdateGoogleUpdateApKey_Unused + +#include // IWYU pragma: export + +#undef UpdateGoogleUpdateApKey +#undef UpdateInstallStatus + +#endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_UTIL_GOOGLE_UPDATE_SETTINGS_H_ diff --git a/chromium_src/chrome/installer/util/google_update_settings_unittest.cc b/chromium_src/chrome/installer/util/google_update_settings_unittest.cc new file mode 100644 index 00000000000..bb66e5f9b79 --- /dev/null +++ b/chromium_src/chrome/installer/util/google_update_settings_unittest.cc @@ -0,0 +1,173 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains tests that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(https://github.com/brave/brave-browser/issues/50977): Remove this and +// convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include "chrome/installer/util/google_update_settings.h" + +#define UpdateGoogleUpdateApKey UpdateGoogleUpdateApKey_Unused +#define UpdateInstallStatus UpdateInstallStatus_Unused +#include +#undef UpdateInstallStatus +#undef UpdateGoogleUpdateApKey + +// Run through all combinations of diff vs. full install, success and failure +// results, and a fistful of initial "ap" values checking that the expected +// final "ap" value is generated by +// GoogleUpdateSettings::UpdateGoogleUpdateApKey. +TEST_F(GoogleUpdateSettingsTest, UpdateGoogleUpdateApKey) { + const installer::ArchiveType archive_types[] = { + installer::UNKNOWN_ARCHIVE_TYPE, installer::FULL_ARCHIVE_TYPE, + installer::INCREMENTAL_ARCHIVE_TYPE}; + const int results[] = {installer::FIRST_INSTALL_SUCCESS, + installer::INSTALL_FAILED}; + const wchar_t* const plain[] = {L"", L"1.1", L"1.1-dev"}; + const wchar_t* const full[] = {L"-full", L"1.1-full", L"1.1-dev-full"}; + static_assert(std::size(full) == std::size(plain), "bad full array size"); + const wchar_t* const* input_arrays[] = {plain, full}; + for (const installer::ArchiveType archive_type : archive_types) { + SCOPED_TRACE(::testing::Message() + << "archive_type=" + << (archive_type == installer::UNKNOWN_ARCHIVE_TYPE + ? "UNKNOWN" + : (archive_type == installer::FULL_ARCHIVE_TYPE + ? "FULL" + : "INCREMENTAL"))); + for (const int result : results) { + SCOPED_TRACE(::testing::Message() + << "result=" + << (result == installer::FIRST_INSTALL_SUCCESS ? "SUCCESS" + : "FAILED")); + // The archive type will/must always be known on install success. + if (archive_type == installer::UNKNOWN_ARCHIVE_TYPE && + result == installer::FIRST_INSTALL_SUCCESS) { + continue; + } + const wchar_t* const* outputs = nullptr; + if (result == installer::FIRST_INSTALL_SUCCESS || + archive_type == installer::FULL_ARCHIVE_TYPE) { + outputs = plain; + } else if (archive_type == installer::INCREMENTAL_ARCHIVE_TYPE) { + outputs = full; + } // else if (archive_type == UNKNOWN) see below + + for (const wchar_t* const* inputs : input_arrays) { + if (archive_type == installer::UNKNOWN_ARCHIVE_TYPE) { + // "-full" is untouched if the archive type is unknown. + if (inputs == full) { + outputs = full; + } else { + outputs = plain; + } + } + for (size_t input_idx = 0; input_idx < std::size(plain); ++input_idx) { + const wchar_t* input = inputs[input_idx]; + const wchar_t* output = outputs[input_idx]; + SCOPED_TRACE(::testing::Message() << "input=\"" << input << "\""); + SCOPED_TRACE(::testing::Message() << "output=\"" << output << "\""); + + std::unique_ptr work_item_list( + WorkItem::CreateWorkItemList()); + + ASSERT_TRUE(CreateApKey(work_item_list.get(), input)); + installer::AdditionalParameters ap; + if (std::wstring_view(output) == ap.value()) { + EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey( + archive_type, result, &ap)); + } else { + EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey( + archive_type, result, &ap)); + } + EXPECT_STREQ(output, ap.value()); + } + } + } + } +} + +TEST_F(GoogleUpdateSettingsTest, UpdateInstallStatusTestIncremental) { + std::unique_ptr work_item_list(WorkItem::CreateWorkItemList()); + // Test incremental install failure + ASSERT_TRUE(CreateApKey(work_item_list.get(), L"")) + << "Failed to create ap key."; + GoogleUpdateSettings::UpdateInstallStatus( + false, installer::INCREMENTAL_ARCHIVE_TYPE, installer::INSTALL_FAILED); + EXPECT_STREQ(ReadApKeyValue().c_str(), L"-full"); + work_item_list->Rollback(); + + work_item_list.reset(WorkItem::CreateWorkItemList()); + // Test incremental install success + ASSERT_TRUE(CreateApKey(work_item_list.get(), L"")) + << "Failed to create ap key."; + GoogleUpdateSettings::UpdateInstallStatus(false, + installer::INCREMENTAL_ARCHIVE_TYPE, + installer::FIRST_INSTALL_SUCCESS); + EXPECT_STREQ(ReadApKeyValue().c_str(), L""); + work_item_list->Rollback(); + + work_item_list.reset(WorkItem::CreateWorkItemList()); + // Test full install failure + ASSERT_TRUE(CreateApKey(work_item_list.get(), L"-full")) + << "Failed to create ap key."; + GoogleUpdateSettings::UpdateInstallStatus(false, installer::FULL_ARCHIVE_TYPE, + installer::INSTALL_FAILED); + EXPECT_STREQ(ReadApKeyValue().c_str(), L""); + work_item_list->Rollback(); + + work_item_list.reset(WorkItem::CreateWorkItemList()); + // Test full install success + ASSERT_TRUE(CreateApKey(work_item_list.get(), L"-full")) + << "Failed to create ap key."; + GoogleUpdateSettings::UpdateInstallStatus(false, installer::FULL_ARCHIVE_TYPE, + installer::FIRST_INSTALL_SUCCESS); + EXPECT_STREQ(ReadApKeyValue().c_str(), L""); + work_item_list->Rollback(); + + work_item_list.reset(WorkItem::CreateWorkItemList()); + // Test the case of when "ap" key doesnt exist at all + std::wstring ap_key_value = ReadApKeyValue(); + std::wstring reg_key = GetApKeyPath(); + HKEY reg_root = HKEY_CURRENT_USER; + bool ap_key_deleted = false; + RegKey key; + if (key.Open(HKEY_CURRENT_USER, reg_key.c_str(), + KEY_WOW64_32KEY | KEY_SET_VALUE) != ERROR_SUCCESS) { + work_item_list->AddCreateRegKeyWorkItem(reg_root, reg_key, KEY_WOW64_32KEY); + ASSERT_TRUE(work_item_list->Do()) << "Failed to create ClientState key."; + } else if (key.DeleteValue(google_update::kRegApField) == ERROR_SUCCESS) { + ap_key_deleted = true; + } + // try differential installer + GoogleUpdateSettings::UpdateInstallStatus( + false, installer::INCREMENTAL_ARCHIVE_TYPE, installer::INSTALL_FAILED); + EXPECT_STREQ(ReadApKeyValue().c_str(), L"-full"); + // try full installer now + GoogleUpdateSettings::UpdateInstallStatus(false, installer::FULL_ARCHIVE_TYPE, + installer::INSTALL_FAILED); + EXPECT_STREQ(ReadApKeyValue().c_str(), L""); + // Now cleanup to leave the system in unchanged state. + // - Diff installer creates an ap key if it didn't exist, so delete this ap + // key + // - If we created any reg key path for ap, roll it back + // - Finally restore the original value of ap key. + if (key.Open(HKEY_CURRENT_USER, reg_key.c_str(), + KEY_WOW64_32KEY | KEY_SET_VALUE) == ERROR_SUCCESS) { + key.DeleteValue(google_update::kRegApField); + } + work_item_list->Rollback(); + if (ap_key_deleted) { + work_item_list.reset(WorkItem::CreateWorkItemList()); + ASSERT_TRUE(CreateApKey(work_item_list.get(), ap_key_value)) + << "Failed to restore ap key."; + } +} diff --git a/chromium_src/chrome/installer/util/sources.gni b/chromium_src/chrome/installer/util/sources.gni index d8a78c35024..f08f1dd439e 100644 --- a/chromium_src/chrome/installer/util/sources.gni +++ b/chromium_src/chrome/installer/util/sources.gni @@ -3,7 +3,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -brave_chromium_src_chrome_installer_util_sources = [] brave_chromium_src_chrome_installer_util_deps = [] if (is_win) { diff --git a/chromium_src/chrome/installer/util/util_constants.cc b/chromium_src/chrome/installer/util/util_constants.cc index 0dfa27e9491..6e125b14f9d 100644 --- a/chromium_src/chrome/installer/util/util_constants.cc +++ b/chromium_src/chrome/installer/util/util_constants.cc @@ -11,6 +11,28 @@ namespace installer { +namespace switches { + +// The switches kNewSetupExe, kPreviousVersion and kUpdateSetupExe used to be +// upstream and had to be restored in Brave to support delta updates on Windows +// until we are on Omaha 4. See github.com/brave/brave-core/pull/31937. + +// Useful only when used with --update-setup-exe; otherwise ignored. Specifies +// the full path where the updated setup.exe will be written. Any other files +// created in the indicated directory may be deleted by the caller after process +// termination. +const char kNewSetupExe[] = "new-setup-exe"; + +// Provide the previous version that patch is for. +const char kPreviousVersion[] = "previous-version"; + +// Also see --new-setup-exe. This command line option specifies a diff patch +// that setup.exe will apply to itself and store the resulting binary in the +// path given by --new-setup-exe. +const char kUpdateSetupExe[] = "update-setup-exe"; + +} // namespace switches + const wchar_t kChromeExe[] = L"brave.exe"; } // namespace installer diff --git a/chromium_src/chrome/installer/util/util_constants.h b/chromium_src/chrome/installer/util/util_constants.h index 352ac9e48d8..55b3b790a9b 100644 --- a/chromium_src/chrome/installer/util/util_constants.h +++ b/chromium_src/chrome/installer/util/util_constants.h @@ -3,14 +3,44 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at https://mozilla.org/MPL/2.0/. */ +// The macros INSTALL_FAILED, NO_STAGE, UNCOMPRESSING and the enum ArchiveType +// below contain code that used to be upstream and had to be restored in Brave +// to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + #ifndef BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_ #define BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_ +#define INSTALL_FAILED \ + SETUP_PATCH_FAILED = 8, APPLY_DIFF_PATCH_FAILED = 42, \ + PATCH_INVALID_ARGUMENTS = 49, DIFF_PATCH_SOURCE_MISSING = 50, INSTALL_FAILED + +#define NO_STAGE \ + NO_STAGE, UPDATING_SETUP // Patching setup.exe with differential update. + +#define UNCOMPRESSING \ + UNCOMPRESSING, PATCHING // Patching chrome.7z with differential update. + #define kGoogleUpdateIsMachineEnvVar \ kGoogleUpdateIsMachineEnvVar[] = "BraveSoftwareUpdateIsMachine"; \ inline constexpr char kGoogleUpdateIsMachineEnvVar_UnUsed #include // IWYU pragma: export + +#undef UNCOMPRESSING +#undef NO_STAGE +#undef INSTALL_FAILED #undef kGoogleUpdateIsMachineEnvVar +namespace installer { + +// The type of an update archive. +enum ArchiveType { + UNKNOWN_ARCHIVE_TYPE, // Unknown or uninitialized. + FULL_ARCHIVE_TYPE, // Full chrome.7z archive. + INCREMENTAL_ARCHIVE_TYPE // Incremental or differential archive. +}; + +} // namespace installer + #endif // BRAVE_CHROMIUM_SRC_CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_ diff --git a/installer/mini_installer/DEPS b/installer/mini_installer/DEPS new file mode 100644 index 00000000000..532345948c0 --- /dev/null +++ b/installer/mini_installer/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "+chrome/installer/mini_installer", + "+chrome/install_static/install_modes.h", +] diff --git a/installer/setup/BUILD.gn b/installer/setup/BUILD.gn new file mode 100644 index 00000000000..b5504b5f75a --- /dev/null +++ b/installer/setup/BUILD.gn @@ -0,0 +1,38 @@ +# Copyright (c) 2025 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//testing/test.gni") + +assert(is_win) + +source_set("unit_tests") { + sources = [ + "archive_patch_helper_unittest.cc", + "brave_setup_util_unittest.cc", + ] + deps = [ + "//base", + "//base/test:test_support", + "//chrome/common:constants", + "//chrome/installer/setup:lib", + "//chrome/installer/util:constants", + "//chrome/installer/util:metainstaller_utils", + "//chrome/installer/util:with_no_strings", + "//testing/gtest", + ] + testonly = true +} + +# As of this writing, the sole purpose of this GN target is to call +# chrome::RegisterPathProvider() for archive_patch_helper_unittest.cc. +source_set("run_all_unittests") { + sources = [ "run_all_unittests.cc" ] + deps = [ + "//base", + "//base/test:test_support", + "//chrome/common:constants", + ] + testonly = true +} diff --git a/installer/setup/DEPS b/installer/setup/DEPS new file mode 100644 index 00000000000..57532dae99c --- /dev/null +++ b/installer/setup/DEPS @@ -0,0 +1,10 @@ +include_rules = [ + "+brave/third_party/bspatch", + "+chrome/common/chrome_paths.h", + "+chrome/installer/setup", + "+chrome/installer/util/lzma_util.h", + "+chrome/installer/util/installation_state.h", + "+chrome/installer/util/util_constants.h", + "+components/zucchini/zucchini.h", + "+components/zucchini/zucchini_integration.h", +] diff --git a/installer/setup/archive_patch_helper.cc b/installer/setup/archive_patch_helper.cc new file mode 100644 index 00000000000..31b4fb82b0d --- /dev/null +++ b/installer/setup/archive_patch_helper.cc @@ -0,0 +1,125 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#include "brave/installer/setup/archive_patch_helper.h" + +#include + +#include + +#include "base/files/file_util.h" +#include "base/logging.h" +#include "brave/third_party/bspatch/mbspatch.h" +#include "chrome/installer/util/lzma_util.h" +#include "components/zucchini/zucchini.h" +#include "components/zucchini/zucchini_integration.h" + +namespace installer { + +ArchivePatchHelper::ArchivePatchHelper(const base::FilePath& working_directory, + const base::FilePath& compressed_archive, + const base::FilePath& patch_source, + const base::FilePath& target, + UnPackConsumer consumer) + : working_directory_(working_directory), + compressed_archive_(compressed_archive), + patch_source_(patch_source), + target_(target), + consumer_(consumer) {} + +ArchivePatchHelper::~ArchivePatchHelper() = default; + +// static +bool ArchivePatchHelper::UncompressAndPatch( + const base::FilePath& working_directory, + const base::FilePath& compressed_archive, + const base::FilePath& patch_source, + const base::FilePath& target, + UnPackConsumer consumer) { + ArchivePatchHelper instance(working_directory, compressed_archive, + patch_source, target, consumer); + return (instance.Uncompress(nullptr) && instance.ApplyAndDeletePatch()); +} + +bool ArchivePatchHelper::Uncompress(base::FilePath* last_uncompressed_file) { + // The target shouldn't already exist. + DCHECK(!base::PathExists(target_)); + + // UnPackArchive takes care of logging. + base::FilePath output_file; + UnPackStatus unpack_status = + UnPackArchive(compressed_archive_, working_directory_, &output_file); + RecordUnPackMetrics(unpack_status, consumer_); + if (unpack_status != UNPACK_NO_ERROR) { + return false; + } + + last_uncompressed_file_ = output_file; + if (last_uncompressed_file) { + *last_uncompressed_file = last_uncompressed_file_; + } + return true; +} + +bool ArchivePatchHelper::ApplyAndDeletePatch() { + const bool succeeded = ZucchiniEnsemblePatch() || BinaryPatch(); + if (!last_uncompressed_file_.empty()) { + base::DeleteFile(last_uncompressed_file_); + } + return succeeded; +} + +bool ArchivePatchHelper::ZucchiniEnsemblePatch() { + if (last_uncompressed_file_.empty()) { + LOG(ERROR) << "No patch file found in compressed archive."; + return false; + } + + zucchini::status::Code result = + zucchini::Apply(patch_source_, last_uncompressed_file_, target_); + + if (result == zucchini::status::kStatusSuccess) { + return true; + } + + LOG(ERROR) << "Failed to apply patch " << last_uncompressed_file_.value() + << " to file " << patch_source_.value() << " and generating file " + << target_.value() + << " using Zucchini. err=" << static_cast(result); + + // Ensure a partial output is not left behind. + base::DeleteFile(target_); + + return false; +} + +bool ArchivePatchHelper::BinaryPatch() { + if (last_uncompressed_file_.empty()) { + LOG(ERROR) << "No patch file found in compressed archive."; + return false; + } + + int result = ApplyBinaryPatch(patch_source_.value().c_str(), + last_uncompressed_file_.value().c_str(), + target_.value().c_str()); + if (result == OK) { + return true; + } + + LOG(ERROR) << "Failed to apply patch " << last_uncompressed_file_.value() + << " to file " << patch_source_.value() << " and generating file " + << target_.value() << " using bsdiff. err=" << result; + + // Ensure a partial output is not left behind. + base::DeleteFile(target_); + + return false; +} + +} // namespace installer diff --git a/installer/setup/archive_patch_helper.h b/installer/setup/archive_patch_helper.h new file mode 100644 index 00000000000..c44f7af3d5e --- /dev/null +++ b/installer/setup/archive_patch_helper.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#ifndef BRAVE_INSTALLER_SETUP_ARCHIVE_PATCH_HELPER_H_ +#define BRAVE_INSTALLER_SETUP_ARCHIVE_PATCH_HELPER_H_ + +#include "base/files/file_path.h" +#include "chrome/installer/setup/setup_util.h" +#include "chrome/installer/util/lzma_util.h" + +namespace installer { + +// A helper class that facilitates uncompressing and patching the chrome archive +// and installer. +// +// Chrome's installer is deployed along with a compressed archive containing +// either 1) an uncompressd archive of the product binaries or 2) a patch file +// to be applied to the uncompressed archive of the version being updated. To +// obtain the uncompressed archive, the contents of the compressed archive are +// uncompressed and extracted. Installation proceeds directly if the +// uncompressed archive is found after this step. Otherwise, the patch is +// applied to the previous version's uncompressed archive using either +// Zucchini's patching or bspatch. +// +// Chrome's installer itself may also be deployed as a patch against the +// previous version's saved installer binary. The same process is followed to +// obtain the new installer. The compressed archive unconditionally contains a +// patch file in this case. +class ArchivePatchHelper { + public: + // Constructs an instance that can uncompress |compressed_archive| into + // |working_directory| and optionally apply the extracted patch file to + // |patch_source|, writing the result to |target|. + ArchivePatchHelper(const base::FilePath& working_directory, + const base::FilePath& compressed_archive, + const base::FilePath& patch_source, + const base::FilePath& target, + UnPackConsumer consumer); + + ArchivePatchHelper(const ArchivePatchHelper&) = delete; + ArchivePatchHelper& operator=(const ArchivePatchHelper&) = delete; + + ~ArchivePatchHelper(); + + // Uncompresses |compressed_archive| in |working_directory| then applies the + // extracted patch file to |patch_source|, writing the result to |target|. + // Ensemble patching via Zucchini is attempted first (if it is enabled). If + // that fails bspatch is attempted. Returns false if uncompression or all + // patching steps fail. + static bool UncompressAndPatch(const base::FilePath& working_directory, + const base::FilePath& compressed_archive, + const base::FilePath& patch_source, + const base::FilePath& target, + UnPackConsumer consumer); + + // Uncompresses compressed_archive() into the working directory. On success, + // last_uncompressed_file (if not nullptr) is populated with the path to the + // last file extracted from the archive. + bool Uncompress(base::FilePath* last_uncompressed_file); + + // Performs ensemble patching on the uncompressed version of + // |compressed_archive| in |working_directory| as specified in the constructor + // using files from |patch_source|. Ensemble patching via Zucchini is + // attempted first (if it is enabled). Zucchini falls back to bspatch if + // unsuccessful. The uncompressed patch file is unconditionally deleted at the + // end. + bool ApplyAndDeletePatch(); + + // Attempts to use Zucchini to apply last_uncompressed_file() to + // patch_source() to generate target(). Returns false if patching fails. + bool ZucchiniEnsemblePatch(); + + // Attempts to use bspatch to apply last_uncompressed_file() to patch_source() + // to generate target(). Returns false if patching fails. + bool BinaryPatch(); + + const base::FilePath& compressed_archive() const { + return compressed_archive_; + } + void set_patch_source(const base::FilePath& patch_source) { + patch_source_ = patch_source; + } + const base::FilePath& patch_source() const { return patch_source_; } + const base::FilePath& target() const { return target_; } + + // Returns the path of the last file extracted by Uncompress(). + const base::FilePath& last_uncompressed_file() const { + return last_uncompressed_file_; + } + void set_last_uncompressed_file( + const base::FilePath& last_uncompressed_file) { + last_uncompressed_file_ = last_uncompressed_file; + } + + private: + base::FilePath working_directory_; + base::FilePath compressed_archive_; + base::FilePath patch_source_; + base::FilePath target_; + base::FilePath last_uncompressed_file_; + UnPackConsumer consumer_; +}; + +} // namespace installer + +#endif // BRAVE_INSTALLER_SETUP_ARCHIVE_PATCH_HELPER_H_ diff --git a/installer/setup/archive_patch_helper_unittest.cc b/installer/setup/archive_patch_helper_unittest.cc new file mode 100644 index 00000000000..51480b93202 --- /dev/null +++ b/installer/setup/archive_patch_helper_unittest.cc @@ -0,0 +1,83 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This file contains code that used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 + +#include "brave/installer/setup/archive_patch_helper.h" + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/path_service.h" +#include "chrome/common/chrome_paths.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class ArchivePatchHelperTest : public testing::Test { + protected: + void SetUp() override { + // This requires chrome::RegisterPathProvider() to have been called. + ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &data_dir_)); + data_dir_ = data_dir_.AppendASCII("installer"); + ASSERT_TRUE(base::PathExists(data_dir_)); + + // Create a temp directory for testing. + ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); + } + + void TearDown() override { + data_dir_.clear(); + // Clean up test directory manually so we can fail if it leaks. + ASSERT_TRUE(test_dir_.Delete()); + } + + // The path to input data used in tests. + base::FilePath data_dir_; + + // The temporary directory used to contain the test operations. + base::ScopedTempDir test_dir_; +}; + +} // namespace + +TEST_F(ArchivePatchHelperTest, ZucchiniPatching) { + base::FilePath src = data_dir_.AppendASCII("archive1.7z"); + base::FilePath patch = data_dir_.AppendASCII("zucchini_archive.diff"); + base::FilePath dest = test_dir_.GetPath().AppendASCII("archive2.7z"); + installer::ArchivePatchHelper archive_helper( + test_dir_.GetPath(), base::FilePath(), src, dest, + installer::UnPackConsumer::SETUP_EXE_PATCH); + archive_helper.set_last_uncompressed_file(patch); + EXPECT_TRUE(archive_helper.ZucchiniEnsemblePatch()); + base::FilePath base = data_dir_.AppendASCII("archive2.7z"); + EXPECT_TRUE(base::ContentsEqual(dest, base)); +} + +TEST_F(ArchivePatchHelperTest, InvalidDiff_MisalignedCblen) { + base::FilePath src = data_dir_.AppendASCII("bin.old"); + base::FilePath patch = data_dir_.AppendASCII("misaligned_cblen.diff"); + base::FilePath dest = test_dir_.GetPath().AppendASCII("bin.new"); + installer::ArchivePatchHelper archive_helper( + test_dir_.GetPath(), base::FilePath(), src, dest, + installer::UnPackConsumer::SETUP_EXE_PATCH); + archive_helper.set_last_uncompressed_file(patch); + // Should fail, but not crash. + EXPECT_FALSE(archive_helper.BinaryPatch()); +} + +TEST_F(ArchivePatchHelperTest, InvalidDiff_NegativeSeek) { + base::FilePath src = data_dir_.AppendASCII("bin.old"); + base::FilePath patch = data_dir_.AppendASCII("negative_seek.diff"); + base::FilePath dest = test_dir_.GetPath().AppendASCII("bin.new"); + installer::ArchivePatchHelper archive_helper( + test_dir_.GetPath(), base::FilePath(), src, dest, + installer::UnPackConsumer::SETUP_EXE_PATCH); + archive_helper.set_last_uncompressed_file(patch); + // Should fail, but not crash. + EXPECT_FALSE(archive_helper.BinaryPatch()); +} diff --git a/installer/setup/brave_setup_util.cc b/installer/setup/brave_setup_util.cc new file mode 100644 index 00000000000..d96097e743f --- /dev/null +++ b/installer/setup/brave_setup_util.cc @@ -0,0 +1,56 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/installer/setup/brave_setup_util.h" + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/version.h" +#include "chrome/installer/setup/installer_state.h" +#include "chrome/installer/setup/setup_constants.h" +#include "chrome/installer/setup/setup_util.h" +#include "chrome/installer/util/installation_state.h" + +namespace installer { + +// This function implementation used to be upstream and had to be restored in +// Brave to support delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +base::FilePath FindArchiveToPatch(const InstallationState& original_state, + const InstallerState& installer_state, + const base::Version& desired_version) { + if (desired_version.IsValid()) { + base::FilePath archive( + installer_state.GetInstallerDirectory(desired_version) + .Append(kChromeArchive)); + return base::PathExists(archive) ? archive : base::FilePath(); + } + + // Check based on the version number advertised to Google Update, since that + // is the value used to select a specific differential update. If an archive + // can't be found using that, fallback to using the newest version present. + base::FilePath patch_source; + const ProductState* product = + original_state.GetProductState(installer_state.system_install()); + if (product) { + patch_source = installer_state.GetInstallerDirectory(product->version()) + .Append(installer::kChromeArchive); + if (base::PathExists(patch_source)) { + return patch_source; + } + } + std::unique_ptr version( + installer::GetMaxVersionFromArchiveDir(installer_state.target_path())); + if (version) { + patch_source = installer_state.GetInstallerDirectory(*version).Append( + installer::kChromeArchive); + if (base::PathExists(patch_source)) { + return patch_source; + } + } + return base::FilePath(); +} + +} // namespace installer diff --git a/installer/setup/brave_setup_util.h b/installer/setup/brave_setup_util.h new file mode 100644 index 00000000000..c9b2d29c301 --- /dev/null +++ b/installer/setup/brave_setup_util.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_INSTALLER_SETUP_BRAVE_SETUP_UTIL_H_ +#define BRAVE_INSTALLER_SETUP_BRAVE_SETUP_UTIL_H_ + +namespace base { +class FilePath; +class Version; +} // namespace base + +namespace installer { + +class InstallationState; +class InstallerState; + +// Returns the uncompressed archive of the installed version that serves as the +// source for patching. If |desired_version| is valid, only the path to that +// version will be returned, or empty if it doesn't exist. +// +// This function used to be upstream and had to be restored in Brave to support +// delta updates on Windows until we are on Omaha 4. See: +// github.com/brave/brave-core/pull/31937 +base::FilePath FindArchiveToPatch(const InstallationState& original_state, + const InstallerState& installer_state, + const base::Version& desired_version); + +} // namespace installer + +#endif // BRAVE_INSTALLER_SETUP_BRAVE_SETUP_UTIL_H_ diff --git a/installer/setup/brave_setup_util_unittest.cc b/installer/setup/brave_setup_util_unittest.cc new file mode 100644 index 00000000000..5045c08c0f1 --- /dev/null +++ b/installer/setup/brave_setup_util_unittest.cc @@ -0,0 +1,181 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/installer/setup/brave_setup_util.h" + +#include + +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/test/test_reg_util_win.h" +#include "base/version.h" +#include "chrome/installer/setup/installer_state.h" +#include "chrome/installer/setup/setup_constants.h" +#include "chrome/installer/util/installation_state.h" +#include "chrome/installer/util/util_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// A test fixture that configures an InstallationState and an InstallerState +// with a product being updated. +// +// FindArchiveToPatchTest and its test cases used to be upstream and had to be +// restored in Brave to support delta updates on Windows until we are on +// Omaha 4. See github.com/brave/brave-core/pull/31937. +class FindArchiveToPatchTest : public testing::Test { + public: + FindArchiveToPatchTest(const FindArchiveToPatchTest&) = delete; + FindArchiveToPatchTest& operator=(const FindArchiveToPatchTest&) = delete; + + protected: + class FakeInstallationState : public installer::InstallationState {}; + + class FakeProductState : public installer::ProductState { + public: + static FakeProductState* FromProductState(const ProductState* product) { + return static_cast(const_cast(product)); + } + + void set_version(const base::Version& version) { + if (version.IsValid()) { + version_ = std::make_unique(version); + } else { + version_.reset(); + } + } + + void set_uninstall_command(const base::CommandLine& uninstall_command) { + uninstall_command_ = uninstall_command; + } + }; + + FindArchiveToPatchTest() = default; + + void SetUp() override { + ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); + ASSERT_NO_FATAL_FAILURE( + registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER)); + ASSERT_NO_FATAL_FAILURE( + registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE)); + product_version_ = base::Version("30.0.1559.0"); + max_version_ = base::Version("47.0.1559.0"); + + // Install the product according to the version. + original_state_ = std::make_unique(); + InstallProduct(); + + // Prepare to update the product in the temp dir. + installer_state_ = std::make_unique( + installer::InstallerState::USER_LEVEL); + installer_state_->set_target_path_for_testing(test_dir_.GetPath()); + + // Create archives in the two version dirs. + ASSERT_TRUE( + base::CreateDirectory(GetProductVersionArchivePath().DirName())); + ASSERT_TRUE(base::WriteFile(GetProductVersionArchivePath(), "a")); + ASSERT_TRUE(base::CreateDirectory(GetMaxVersionArchivePath().DirName())); + ASSERT_TRUE(base::WriteFile(GetMaxVersionArchivePath(), "b")); + } + + void TearDown() override { original_state_.reset(); } + + base::FilePath GetArchivePath(const base::Version& version) const { + return test_dir_.GetPath() + .AppendASCII(version.GetString()) + .Append(installer::kInstallerDir) + .Append(installer::kChromeArchive); + } + + base::FilePath GetMaxVersionArchivePath() const { + return GetArchivePath(max_version_); + } + + base::FilePath GetProductVersionArchivePath() const { + return GetArchivePath(product_version_); + } + + void InstallProduct() { + FakeProductState* product = FakeProductState::FromProductState( + original_state_->GetNonVersionedProductState(false)); + + product->set_version(product_version_); + base::CommandLine uninstall_command( + test_dir_.GetPath() + .AppendASCII(product_version_.GetString()) + .Append(installer::kInstallerDir) + .Append(installer::kSetupExe)); + uninstall_command.AppendSwitch(installer::switches::kUninstall); + product->set_uninstall_command(uninstall_command); + } + + void UninstallProduct() { + FakeProductState::FromProductState( + original_state_->GetNonVersionedProductState(false)) + ->set_version(base::Version()); + } + + base::ScopedTempDir test_dir_; + base::Version product_version_; + base::Version max_version_; + std::unique_ptr original_state_; + std::unique_ptr installer_state_; + + private: + registry_util::RegistryOverrideManager registry_override_manager_; +}; + +} // namespace + +// Test that the path to the advertised product version is found. +TEST_F(FindArchiveToPatchTest, ProductVersionFound) { + base::FilePath patch_source(installer::FindArchiveToPatch( + *original_state_, *installer_state_, base::Version())); + EXPECT_EQ(GetProductVersionArchivePath().value(), patch_source.value()); +} + +// Test that the path to the max version is found if the advertised version is +// missing. +TEST_F(FindArchiveToPatchTest, MaxVersionFound) { + // The patch file is absent. + ASSERT_TRUE(base::DeleteFile(GetProductVersionArchivePath())); + base::FilePath patch_source(installer::FindArchiveToPatch( + *original_state_, *installer_state_, base::Version())); + EXPECT_EQ(GetMaxVersionArchivePath().value(), patch_source.value()); + + // The product doesn't appear to be installed, so the max version is found. + UninstallProduct(); + patch_source = installer::FindArchiveToPatch( + *original_state_, *installer_state_, base::Version()); + EXPECT_EQ(GetMaxVersionArchivePath().value(), patch_source.value()); +} + +// Test that an empty path is returned if no version is found. +TEST_F(FindArchiveToPatchTest, NoVersionFound) { + // The product doesn't appear to be installed and no archives are present. + UninstallProduct(); + ASSERT_TRUE(base::DeleteFile(GetProductVersionArchivePath())); + ASSERT_TRUE(base::DeleteFile(GetMaxVersionArchivePath())); + + base::FilePath patch_source(installer::FindArchiveToPatch( + *original_state_, *installer_state_, base::Version())); + EXPECT_EQ(base::FilePath::StringType(), patch_source.value()); +} + +TEST_F(FindArchiveToPatchTest, DesiredVersionFound) { + base::FilePath patch_source1(installer::FindArchiveToPatch( + *original_state_, *installer_state_, product_version_)); + EXPECT_EQ(GetProductVersionArchivePath().value(), patch_source1.value()); + base::FilePath patch_source2(installer::FindArchiveToPatch( + *original_state_, *installer_state_, max_version_)); + EXPECT_EQ(GetMaxVersionArchivePath().value(), patch_source2.value()); +} + +TEST_F(FindArchiveToPatchTest, DesiredVersionNotFound) { + base::FilePath patch_source(installer::FindArchiveToPatch( + *original_state_, *installer_state_, base::Version("1.2.3.4"))); + EXPECT_EQ(base::FilePath().value(), patch_source.value()); +} diff --git a/installer/setup/run_all_unittests.cc b/installer/setup/run_all_unittests.cc new file mode 100644 index 00000000000..96f62e490cc --- /dev/null +++ b/installer/setup/run_all_unittests.cc @@ -0,0 +1,20 @@ +/* Copyright (c) 2025 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "base/functional/bind.h" +#include "base/test/launcher/unit_test_launcher.h" +#include "base/test/test_suite.h" +#include "chrome/common/chrome_paths.h" + +int main(int argc, char* argv[]) { + base::TestSuite test_suite(argc, argv); + + // For archive_patch_helper_unittest.cc. + chrome::RegisterPathProvider(); + + return base::LaunchUnitTests( + argc, argv, + base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite))); +} diff --git a/installer/util/BUILD.gn b/installer/util/BUILD.gn index bf7b4bd2a99..f64a4c4bf1f 100644 --- a/installer/util/BUILD.gn +++ b/installer/util/BUILD.gn @@ -1,3 +1,8 @@ +# Copyright (c) 2021 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + source_set("util") { sources = [ "brave_shell_util.cc", diff --git a/installer/util/prebuild/create_installer_string_rc.py b/installer/util/prebuild/create_installer_string_rc.py index b9f612e9791..031bcec7dab 100644 --- a/installer/util/prebuild/create_installer_string_rc.py +++ b/installer/util/prebuild/create_installer_string_rc.py @@ -30,3 +30,8 @@ MODE_SPECIFIC_STRINGS = { ], }, } + +# IDS_SETUP_PATCH_FAILED used to be upstream and had to be restored in Brave to +# support delta updates on Windows until we are on Omaha 4. See: +# github.com/brave/brave-core/pull/31937 +STRING_IDS.append('IDS_SETUP_PATCH_FAILED') diff --git a/installer/util/prebuild/create_installer_string_rc_official.py b/installer/util/prebuild/create_installer_string_rc_official.py index fd7b548923d..628bbb367d8 100644 --- a/installer/util/prebuild/create_installer_string_rc_official.py +++ b/installer/util/prebuild/create_installer_string_rc_official.py @@ -5,7 +5,7 @@ from brave_chromium_utils import inline_file -inline_file("//chrome/installer/util/prebuild/create_installer_string_rc.py", +inline_file("//brave/installer/util/prebuild/create_installer_string_rc.py", globals(), locals()) MODE_SPECIFIC_STRINGS = { diff --git a/patches/build-config-unsafe_buffers_paths.txt.patch b/patches/build-config-unsafe_buffers_paths.txt.patch index 6c36fa4170b..63356e9344a 100644 --- a/patches/build-config-unsafe_buffers_paths.txt.patch +++ b/patches/build-config-unsafe_buffers_paths.txt.patch @@ -1,13 +1,14 @@ diff --git a/build/config/unsafe_buffers_paths.txt b/build/config/unsafe_buffers_paths.txt -index 4433777ae40e045da1b9f8747e3fefff67d68ac0..3dc37fc965afe923ea222ca73bb886d0e5be0540 100644 +index 4433777ae40e045da1b9f8747e3fefff67d68ac0..32257a1f70e251fdcf1aa38b00427bb84a27ff17 100644 --- a/build/config/unsafe_buffers_paths.txt +++ b/build/config/unsafe_buffers_paths.txt -@@ -32,3 +32,8 @@ $../../ +@@ -32,3 +32,9 @@ $../../ -ui/gl/ # Unsafe generated files. -url/third_party/ -v8/ +-brave/third_party/bip39wally-core-native/ +-brave/vendor/bat-native-tweetnacl/ +-brave/third_party/bitcoin-core/ ++-brave/third_party/bspatch/ +-brave/third_party/ethash/ +-brave/third_party/argon2/ diff --git a/patches/chrome-installer-mini_installer-configuration.cc.patch b/patches/chrome-installer-mini_installer-configuration.cc.patch index 82ebe17b1cf..4cfb7fd7e7f 100644 --- a/patches/chrome-installer-mini_installer-configuration.cc.patch +++ b/patches/chrome-installer-mini_installer-configuration.cc.patch @@ -1,27 +1,12 @@ diff --git a/chrome/installer/mini_installer/configuration.cc b/chrome/installer/mini_installer/configuration.cc -index f247568ff033121f2aeb6d66c505a514e392b9a6..b4fbb00f6d30090ee6be83a317feddd455a586bb 100644 +index f247568ff033121f2aeb6d66c505a514e392b9a6..edc94808d1b557e421e5adc87059b4750827ab2c 100644 --- a/chrome/installer/mini_installer/configuration.cc +++ b/chrome/installer/mini_installer/configuration.cc -@@ -30,7 +30,11 @@ namespace { - bool GetGoogleUpdateIsMachineEnvVar() { - const DWORD kBufferSize = 2; - StackString value; -+#if defined(OFFICIAL_BUILD) -+ DWORD length = ::GetEnvironmentVariableW(L"BraveSoftwareUpdateIsMachine", -+#else - DWORD length = ::GetEnvironmentVariableW(L"GoogleUpdateIsMachine", -+#endif - value.get(), kBufferSize); - return length == 1 && *value.get() == L'1'; +@@ -47,6 +47,7 @@ Configuration::~Configuration() { + + bool Configuration::Initialize() { + Clear(); ++ BRAVE_READ_RESOURCES + ReadRegistry(); + return ParseCommandLine(::GetCommandLine()); } -@@ -80,7 +84,9 @@ bool Configuration::ParseCommandLine(const wchar_t* command_line) { - for (int i = 1; i < argument_count_; ++i) { - if (0 == ::lstrcmpi(args_[i], L"--system-level")) - is_system_level_ = true; --#if BUILDFLAG(GOOGLE_CHROME_BRANDING) -+#if BUILDFLAG(GOOGLE_CHROME_BRANDING) || defined(OFFICIAL_BUILD) -+ // Use original install switch because it isn't visible to user. -+ // Sync this switch with brave/.../chromium_install_modes.cc - else if (0 == ::lstrcmpi(args_[i], L"--chrome-beta")) - chrome_app_guid_ = google_update::kBetaAppGuid; - else if (0 == ::lstrcmpi(args_[i], L"--chrome-dev")) diff --git a/patches/chrome-installer-mini_installer-mini_installer.cc.patch b/patches/chrome-installer-mini_installer-mini_installer.cc.patch index c4ee487f381..195fbd69a55 100644 --- a/patches/chrome-installer-mini_installer-mini_installer.cc.patch +++ b/patches/chrome-installer-mini_installer-mini_installer.cc.patch @@ -1,12 +1,44 @@ diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc -index 44f29f2fafda83685479c791da3aa4ddbd4cde73..6231ec19c1955931f1caf1cf7b862f8003095e8c 100644 +index 44f29f2fafda83685479c791da3aa4ddbd4cde73..14e01e32520b87ef5cbc96a346326f07d5ddf853 100644 --- a/chrome/installer/mini_installer/mini_installer.cc +++ b/chrome/installer/mini_installer/mini_installer.cc -@@ -499,6 +499,7 @@ ProcessExitResult RunSetup(const Configuration& configuration, +@@ -462,6 +462,7 @@ ProcessExitResult UnpackBinaryResources(HMODULE module, + } + #endif // defined(COMPONENT_BUILD) + ++ BRAVE_STUFF_PATCH_FLAG_INTO_WINDOWS_ERROR + return exit_code; + } + +@@ -475,6 +476,7 @@ ProcessExitResult RunSetup(const Configuration& configuration, + if (!setup_exe.assign(setup_path)) { + return ProcessExitResult(COMMAND_STRING_OVERFLOW); + } ++ BRAVE_ASSIGN_PREVIOUS_SETUP_EXE_IF_SETUP_PATH_EMPTY + + // There could be three full paths in the command line for setup.exe (path + // to exe itself, path to archive and path to log file), so we declare +@@ -499,6 +501,7 @@ ProcessExitResult RunSetup(const Configuration& configuration, // on to setup.exe AppendCommandLineFlags(configuration.command_line(), &cmd_line); -+ BRAVE_RUN_SETUP ++ BRAVE_MAYBE_APPEND_PREVIOUS_VERSION_AND_PARSE_REFERRAL_CODE return RunProcessAndWait(setup_exe.get(), cmd_line.get(), RUN_SETUP_FAILED_FILE_NOT_FOUND, RUN_SETUP_FAILED_PATH_NOT_FOUND, +@@ -729,6 +732,7 @@ ProcessExitResult WMain(HMODULE module) { + if (!GetWorkDir(module, &base_path, &exit_code)) { + return exit_code; + } ++ BRAVE_APPEND_FULL_SUFFIX_IN_REGISTRY + + int max_delete_attempts = 0; + PathString setup_path; +@@ -738,6 +742,7 @@ ProcessExitResult WMain(HMODULE module) { + exit_code = + UnpackBinaryResources(module, base_path.get(), setup_path, archive_path, + archive_type, max_delete_attempts); ++ BRAVE_MAYBE_PATCH_PREVIOUS_SETUP_EXE + + // While unpacking the binaries, we paged in a whole bunch of memory that + // we don't need anymore. Let's give it back to the pool before running diff --git a/patches/chrome-installer-setup-install_worker.cc.patch b/patches/chrome-installer-setup-install_worker.cc.patch new file mode 100644 index 00000000000..7168206b92b --- /dev/null +++ b/patches/chrome-installer-setup-install_worker.cc.patch @@ -0,0 +1,20 @@ +diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc +index 3393a297bb7120d8082cecc25df15f4e60324425..c418458f97f593fa5805dc9d125ea1ee08191591 100644 +--- a/chrome/installer/setup/install_worker.cc ++++ b/chrome/installer/setup/install_worker.cc +@@ -106,6 +106,7 @@ void AddInstallerCopyTasks(const InstallParams& install_params, + install_list->AddCopyTreeWorkItem(setup_path, active_setup_exe, temp_path, + WorkItem::ALWAYS); + } ++ BRAVE_ADD_INSTALLER_COPY_TASKS + } + + // A callback invoked by |work_item| that adds firewall rules for Chrome. Rules +@@ -216,6 +217,7 @@ void AddChromeWorkItems(const InstallParams& install_params, + installer_state.GetInstallerDirectory(current_version)); + base::FilePath old_archive( + old_installer_dir.Append(installer::kChromeArchive)); ++ BRAVE_MAYBE_ABORT_ADD_CHROME_WORK_ITEMS + auto* delete_old_archive_work_item = + install_list->AddDeleteTreeWorkItem(old_archive, temp_path); + // Don't cause failure of |install_list| if this WorkItem fails. diff --git a/patches/chrome-installer-setup-setup_main.cc.patch b/patches/chrome-installer-setup-setup_main.cc.patch new file mode 100644 index 00000000000..7532ea5c069 --- /dev/null +++ b/patches/chrome-installer-setup-setup_main.cc.patch @@ -0,0 +1,20 @@ +diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc +index bf5b9a610a7cd3ddfce42bf848a997b6ac26c529..14e65a5a8e3bbdfb0c259bbd09e4a80224ab64b8 100644 +--- a/chrome/installer/setup/setup_main.cc ++++ b/chrome/installer/setup/setup_main.cc +@@ -701,6 +701,7 @@ installer::InstallStatus InstallProducts(InstallationState& original_state, + } + } + ++ BRAVE_INSTALL_PRODUCTS + return install_status; + } + +@@ -1526,6 +1527,7 @@ int SetupMain() { + &exit_code)) { + return exit_code; + } ++ BRAVE_SETUP_MAIN + + if (system_install && !IsUserAnAdmin()) { + if (!cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { diff --git a/patches/chrome-installer-util-BUILD.gn.patch b/patches/chrome-installer-util-BUILD.gn.patch index 5535d78b02c..497552b46fa 100644 --- a/patches/chrome-installer-util-BUILD.gn.patch +++ b/patches/chrome-installer-util-BUILD.gn.patch @@ -1,12 +1,12 @@ diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn -index f7d3ac043e245288211974d9c9cc10ea327f83a6..f4aa9a068ab3c6f417b15c247fa34a00e71f8708 100644 +index f7d3ac043e245288211974d9c9cc10ea327f83a6..0d3ef781c071d7b83f25b657917a5ade73d716d4 100644 --- a/chrome/installer/util/BUILD.gn +++ b/chrome/installer/util/BUILD.gn @@ -202,6 +202,7 @@ static_library("with_no_strings") { "initial_preferences.h", ] } -+ import("//brave/chromium_src/chrome/installer/util/sources.gni") deps += brave_chromium_src_chrome_installer_util_deps sources += brave_chromium_src_chrome_installer_util_sources ++ import("//brave/chromium_src/chrome/installer/util/sources.gni") deps += brave_chromium_src_chrome_installer_util_deps } # Use this version of installer_util to link to the generated strings in .rc diff --git a/script/chromium-rebase-l10n.py b/script/chromium-rebase-l10n.py index c1c94c7bab8..4486bfb954f 100755 --- a/script/chromium-rebase-l10n.py +++ b/script/chromium-rebase-l10n.py @@ -17,6 +17,7 @@ import os.path import sys import glob from lib.l10n.grd_utils import (braveify_grd_in_place, braveify_grd_tree, + INSTALLER_STRINGS, GOOGLE_CHROME_STRINGS_MIGRATION_MAP, get_override_file_path, textify, write_xml_file_from_tree) @@ -108,6 +109,61 @@ def migrate_google_chrome_strings(brave_strings_xml_tree, return migrate_google_chrome_xtb_translations_for_messages(message_ids) +def add_installer_strings_xtb_translations_for_messages(message_ids): + installer_xtb_files = glob.glob( + os.path.join( + BRAVE_SOURCE_ROOT, + 'chromium_src/chrome/installer/setup/resources/setup_resources_*.xtb' + )) + for installer_xtb_path in installer_xtb_files: + installer_xtb_xml_tree = etree.parse(installer_xtb_path) + lang = os.path.basename(installer_xtb_path).replace( + 'setup_resources_', '').replace('.xtb', '') + if not lang: + print( + 'Skipping file {} because unable to determine language'.format( + installer_xtb_path)) + continue + brave_xtb_path = os.path.join( + BRAVE_SOURCE_ROOT, + 'app/resources/brave_strings_{}.xtb'.format(lang)) + if not os.path.exists(brave_xtb_path): + print('Unable to find brave translation file {}'.format( + brave_xtb_path)) + return False + messages = [(message_id, + installer_xtb_xml_tree.xpath('//translation[@id="' + + message_id + '"]')[0].text) + for message_id in message_ids] + + write_new_translations_to_xtb(brave_xtb_path, messages) + + return True + + +def add_installer_strings(brave_strings_xml_tree, installer_strings): + print('Adding installer strings...') + installer_strings_grd_path = os.path.join( + BRAVE_SOURCE_ROOT, + 'chromium_src/chrome/installer/setup/resources/setup_resources.grd') + installer_strings_xml_tree = etree.parse(installer_strings_grd_path) + message_ids = [] + messages_element = brave_strings_xml_tree.xpath('//messages')[0] + if_element = etree.SubElement(messages_element, 'if') + if_element.set('expr', 'is_win') + for item in installer_strings: + message_elem = installer_strings_xml_tree.xpath( + '//message[@name="{}"]'.format(item))[0] + message_text = message_elem.text.lstrip().rstrip() + message_id = tclib.GenerateMessageId(message_text) + message_ids.append(message_id) + new_element = etree.SubElement(if_element, 'message') + new_element.set('name', item) + new_element.text = message_elem.text + new_element.set('desc', message_elem.get('desc')) + return add_installer_strings_xtb_translations_for_messages(message_ids) + + def parse_args(): parser = argparse.ArgumentParser( description='Rebase strings/l10n on the current Chromium version.') @@ -234,6 +290,8 @@ def main(): if not migrate_google_chrome_strings( xml_tree, GOOGLE_CHROME_STRINGS_MIGRATION_MAP): return 1 + if not add_installer_strings(xml_tree, INSTALLER_STRINGS): + return 1 elem1 = xml_tree.xpath('//message[@name="IDS_SXS_SHORTCUT_NAME"]')[0] elem1.text = 'Brave Nightly' elem1.attrib.pop('desc') diff --git a/script/lib/l10n/grd_utils.py b/script/lib/l10n/grd_utils.py index fce53f931a4..4de56846752 100755 --- a/script/lib/l10n/grd_utils.py +++ b/script/lib/l10n/grd_utils.py @@ -28,6 +28,10 @@ GOOGLE_CHROME_STRINGS_MIGRATION_MAP = { 'IDS_SHORTCUT_NAME_DEV': 'IDS_CHROME_SHORTCUT_NAME_DEV' } +# Installer strings that need to be in brave_strings.grd until we move Windows +# to Omaha 4. +INSTALLER_STRINGS = ['IDS_SETUP_PATCH_FAILED'] + def braveify_grd_text(text, is_main_text, branding_replacements_only): """Replaces text string to Brave wording""" @@ -168,9 +172,12 @@ def update_xtbs_locally(grd_file_path, brave_source_root, only_for_lang): brave_strings_string_ids = [] if os.path.basename(grd_file_path) == 'brave_strings.grd': assert len(grd_strings) == len(chromium_grd_strings) + \ - len(GOOGLE_CHROME_STRINGS_MIGRATION_MAP) - brave_strings_string_ids = remove_google_chrome_strings( - grd_strings, GOOGLE_CHROME_STRINGS_MIGRATION_MAP) + len(GOOGLE_CHROME_STRINGS_MIGRATION_MAP) + \ + len(INSTALLER_STRINGS) + brave_strings_string_ids = remove_installer_strings( + remove_google_chrome_strings(grd_strings, + GOOGLE_CHROME_STRINGS_MIGRATION_MAP), + INSTALLER_STRINGS) assert len(grd_strings) == len(chromium_grd_strings), ( f'String count in {grd_file_path} and in {chromium_grd_file_path} do' + f'not match: {len(grd_strings)} vs {len(chromium_grd_strings)}.') @@ -403,6 +410,24 @@ def remove_google_chrome_strings(brave_grd_strings, google_chrome_strings_map): return string_ids +def remove_installer_strings(brave_grd_strings, installer_string): + string_ids = [] + string_names = [ + string_name[4:].lower() for string_name in installer_string + ] + to_remove = [] + for string_tuple in brave_grd_strings: + if string_tuple[0] in string_names: + to_remove.append(string_tuple) + string_ids.append(string_tuple[2]) + assert len(to_remove) == len(installer_string) + + for string_tuple in to_remove: + brave_grd_strings.remove(string_tuple) + + return string_ids + + def add_google_chrome_translations(brave_strings_xtb_file, xml_tree, string_ids): brave_xtb_tree = lxml.etree.parse(brave_strings_xtb_file) diff --git a/test/BUILD.gn b/test/BUILD.gn index 60cd612cce9..bb3f37c9134 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -623,7 +623,6 @@ source_set("crypto_unittests") { if (!is_android) { test("brave_installer_unittests") { deps = [ - "//base/test:run_all_unittests", "//base/test:test_support", "//brave/base/test:test_vendor_is_brave", ] @@ -645,6 +644,8 @@ if (!is_android) { include_dirs = [ "$target_gen_dir" ] deps += [ "//base", + "//brave/installer/setup:run_all_unittests", + "//brave/installer/setup:unit_tests", "//chrome/chrome_elf:nt_registry", "//chrome/install_static:install_static_util", "//chrome/install_static/test:test_support", @@ -662,6 +663,8 @@ if (!is_android) { "//brave/chromium_src/chrome/installer/setup/test:vpn_unit_tests", ] } + } else { + deps += [ "//base/test:run_all_unittests" ] } } } diff --git a/test/filters/installer_util_unittests.filter b/test/filters/installer_util_unittests.filter new file mode 100644 index 00000000000..9066a010743 --- /dev/null +++ b/test/filters/installer_util_unittests.filter @@ -0,0 +1,10 @@ +## +## Upstream tests to disable +## +## When adding a new filter to this list, please include a short description of +## why the filter is required and create an associated tracking issue. +## + +# The test hardcodes "GoogleUpdateIsMachine" in a non-easily-replaceable way, +# when we would need "BraveUpdateIsMachine". +-InitialPreferencesTest.GoogleUpdateIsMachine diff --git a/test/filters/setup_unittests.filter b/test/filters/setup_unittests.filter new file mode 100644 index 00000000000..19e0138479b --- /dev/null +++ b/test/filters/setup_unittests.filter @@ -0,0 +1,17 @@ +## +## Upstream tests to disable +## +## When adding a new filter to this list, please include a short description of +## why the filter is required and create an associated tracking issue. +## + +# We have "Chromium" hard-coded in some strings in non-official builds. This +# should be fixed. See https://github.com/brave/brave-browser/issues/51175. +-GetPreviousSetupExePathTest.* + +# This test hardcodes kCommandExecuteImplClsid in a non-easily-replaceable way. +-LegacyCleanupsTest.Do + +# This test hardcodes "GoogleUpdateIsMachine" in a non-easily-replaceable way, +# when we would need "BraveUpdateIsMachine". +-MiniInstallerConfigurationTest.IsSystemLevel diff --git a/third_party/bspatch/.clang-format b/third_party/bspatch/.clang-format new file mode 100644 index 00000000000..e3845288a2a --- /dev/null +++ b/third_party/bspatch/.clang-format @@ -0,0 +1 @@ +DisableFormat: true diff --git a/third_party/bspatch/BUILD.gn b/third_party/bspatch/BUILD.gn new file mode 100644 index 00000000000..faf130b460b --- /dev/null +++ b/third_party/bspatch/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright 2015 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("visibility.gni") + +source_set("bspatch") { + sources = [ + "mbspatch.cc", + "mbspatch.h", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + deps = [ "//third_party/lzma_sdk" ] +} diff --git a/third_party/bspatch/LICENSE b/third_party/bspatch/LICENSE new file mode 100644 index 00000000000..f2521d71cd6 --- /dev/null +++ b/third_party/bspatch/LICENSE @@ -0,0 +1,23 @@ +Copyright 2003,2004 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/bspatch/OWNERS b/third_party/bspatch/OWNERS new file mode 100644 index 00000000000..de16560211a --- /dev/null +++ b/third_party/bspatch/OWNERS @@ -0,0 +1 @@ +file://chrome/installer/OWNERS diff --git a/third_party/bspatch/README.chromium b/third_party/bspatch/README.chromium new file mode 100644 index 00000000000..f73c7f1381c --- /dev/null +++ b/third_party/bspatch/README.chromium @@ -0,0 +1,25 @@ +Name: bspatch +URL: https://github.com/mozilla-services/services-central-legacy/tree/master/toolkit/mozapps/update/updater +Version: N/A +Revision: 465265d0d473d107b76e74d969199eaf2cdc8750 +Update Mechanism: Static.HardFork (https://crbug.com/422918425) +License: BSD-2-Clause +License File: LICENSE +Security Critical: yes +Shipped: yes + +Description: +This is Chrome's locally patched copy of Colin Percival's bspatch tool. It used +to be in Chromium and had to be restored in Brave to support delta updates on +Windows until Brave is on Omaha 4. See github.com/brave/brave-core/pull/31937. + +Originally obtained from Mozilla's local copy/fork of bspatch; see: + +The license is shared in common with bsdiff. + +Local changes include CRC32 verification and improvements in error handling. + +Update(08 Sep 08): Changed ApplyBinaryPatch to accept wchar_t paths +instead of char paths. +Update(12 May 13): Report error on MBS_ApplyPatch failure. +Update(27 July 16): Improve validation of diffs. diff --git a/third_party/bspatch/mbspatch.cc b/third_party/bspatch/mbspatch.cc new file mode 100644 index 00000000000..d33ceeaafe8 --- /dev/null +++ b/third_party/bspatch/mbspatch.cc @@ -0,0 +1,302 @@ +/*- + * Copyright 2003,2004 Colin Percival + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Changelog: + * 2005-04-26 - Define the header as a C structure, add a CRC32 checksum to + * the header, and make all the types 32-bit. + * --Benjamin Smedberg + * 2007-11-14 - Added CalculateCrc() and ApplyBinaryPatch() methods. + * --Rahul Kuchhal + * 2016-07-27 - Improve validation of diffs. + * --Ricky Zhou + */ + +#include "mbspatch.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# include +#else +# include +# include +#endif + +extern "C" { +#include <7zCrc.h> +} + +#ifndef SSIZE_MAX +# define SSIZE_MAX LONG_MAX +#endif + +int +MBS_ReadHeader(int fd, MBSPatchHeader *header) +{ + int s = read(fd, header, sizeof(MBSPatchHeader)); + if (s != sizeof(MBSPatchHeader)) + return READ_ERROR; + + header->slen = ntohl(header->slen); + header->scrc32 = ntohl(header->scrc32); + header->dlen = ntohl(header->dlen); + header->cblen = ntohl(header->cblen); + header->difflen = ntohl(header->difflen); + header->extralen = ntohl(header->extralen); + + struct stat hs; + s = fstat(fd, &hs); + if (s != 0) + return READ_ERROR; + + if (memcmp(header->tag, "MBDIFF10", 8) != 0) + return UNEXPECTED_ERROR; + + if (hs.st_size > INT_MAX) + return UNEXPECTED_ERROR; + + size_t size = static_cast(hs.st_size); + if (size < sizeof(MBSPatchHeader)) + return UNEXPECTED_ERROR; + size -= sizeof(MBSPatchHeader); + + if (size < header->cblen) + return UNEXPECTED_ERROR; + size -= header->cblen; + + if (size < header->difflen) + return UNEXPECTED_ERROR; + size -= header->difflen; + + if (size < header->extralen) + return UNEXPECTED_ERROR; + size -= header->extralen; + + if (size != 0) + return UNEXPECTED_ERROR; + + return OK; +} + +int +MBS_ApplyPatch(const MBSPatchHeader *header, int patchfd, + unsigned char *fbuffer, int filefd) +{ + unsigned char *fbufstart = fbuffer; + unsigned char *fbufend = fbuffer + header->slen; + + unsigned char *buf = (unsigned char*) malloc(header->cblen + + header->difflen + + header->extralen); + if (!buf) + return MEM_ERROR; + + int rv = OK; + + int r = header->cblen + header->difflen + header->extralen; + unsigned char *wb = buf; + while (r) { + int c = read(patchfd, wb, (r > SSIZE_MAX) ? SSIZE_MAX : r); + if (c < 0) { + rv = READ_ERROR; + goto end; + } + + r -= c; + wb += c; + + if (c == 0 && r) { + rv = UNEXPECTED_ERROR; + goto end; + } + } + + { + MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf; + if (header->cblen % sizeof(MBSPatchTriple) != 0) { + rv = UNEXPECTED_ERROR; + goto end; + } + + unsigned char *diffsrc = buf + header->cblen; + unsigned char *extrasrc = diffsrc + header->difflen; + + MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc; + unsigned char *diffend = extrasrc; + unsigned char *extraend = extrasrc + header->extralen; + + while (ctrlsrc < ctrlend) { + ctrlsrc->x = ntohl(ctrlsrc->x); + ctrlsrc->y = ntohl(ctrlsrc->y); + ctrlsrc->z = ntohl(ctrlsrc->z); + +#ifdef DEBUG_bsmedberg + printf("Applying block:\n" + " x: %u\n" + " y: %u\n" + " z: %i\n", + ctrlsrc->x, + ctrlsrc->y, + ctrlsrc->z); +#endif + + /* Add x bytes from oldfile to x bytes from the diff block */ + + if (ctrlsrc->x > static_cast(fbufend - fbuffer) || + ctrlsrc->x > static_cast(diffend - diffsrc)) { + rv = UNEXPECTED_ERROR; + goto end; + } + for (unsigned int i = 0; i < ctrlsrc->x; ++i) { + diffsrc[i] += fbuffer[i]; + } + if ((int) write(filefd, diffsrc, ctrlsrc->x) != ctrlsrc->x) { + rv = WRITE_ERROR; + goto end; + } + fbuffer += ctrlsrc->x; + diffsrc += ctrlsrc->x; + + /* Copy y bytes from the extra block */ + + if (ctrlsrc->y > static_cast(extraend - extrasrc)) { + rv = UNEXPECTED_ERROR; + goto end; + } + if ((int) write(filefd, extrasrc, ctrlsrc->y) != ctrlsrc->y) { + rv = WRITE_ERROR; + goto end; + } + extrasrc += ctrlsrc->y; + + /* "seek" forwards in oldfile by z bytes */ + + if (ctrlsrc->z < fbufstart - fbuffer || + ctrlsrc->z > fbufend - fbuffer) { + rv = UNEXPECTED_ERROR; + goto end; + } + fbuffer += ctrlsrc->z; + + /* and on to the next control block */ + + ++ctrlsrc; + } + } + +end: + free(buf); + return rv; +} + +int CalculateCrc(const unsigned char *buf, int size) { + CrcGenerateTable(); + unsigned int crc = 0xffffffffL; + crc = ~CrcCalc(buf, size); + return crc; +} + +/* _O_BINARY is a MSWindows open() mode flag. When absent, MSWindows + * open() translates CR+LF to LF; when present, it passes bytes + * through faithfully. Under *nix, we are always in binary mode, so + * the following #define turns this flag into a no-op w.r.t. bitwise + * OR. Note that this would be DANGEROUS AND UNSOUND if we used + * _O_BINARY other than as a bitwise OR mask (e.g., as a bitwise AND + * mask to check for binary mode), but it seems OK in the limited + * context of the following small function. */ +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +int ApplyBinaryPatch(const wchar_t *old_file, const wchar_t *patch_file, + const wchar_t *new_file) { + int ret = OK; + int ofd = -1; + int nfd = -1; + unsigned char *buf = NULL; + + int pfd = _wopen(patch_file, O_RDONLY | _O_BINARY); + if (pfd < 0) return READ_ERROR; + + do { + MBSPatchHeader header; + if ((ret = MBS_ReadHeader(pfd, &header))) + break; + + ofd = _wopen(old_file, O_RDONLY | _O_BINARY); + if (ofd < 0) { + ret = READ_ERROR; + break; + } + + struct stat os; + if ((ret = fstat(ofd, &os))) { + ret = READ_ERROR; + break; + } + + if (os.st_size != header.slen) { + ret = UNEXPECTED_ERROR; + break; + } + + buf = (unsigned char*) malloc(header.slen); + if (!buf) { + ret = MEM_ERROR; + break; + } + + if (read(ofd, buf, header.slen) != header.slen) { + ret = READ_ERROR; + break; + } + + if (CalculateCrc(buf, header.slen) != header.scrc32) { + ret = CRC_ERROR; + break; + } + + nfd = _wopen(new_file, O_WRONLY | O_TRUNC | O_CREAT | _O_BINARY); + if (nfd < 0) { + ret = READ_ERROR; + break; + } + + ret = MBS_ApplyPatch(&header, pfd, buf, nfd); + } while (0); + + free(buf); + close(pfd); + if (ofd >= 0) close(ofd); + if (nfd >= 0) close(nfd); + return ret; +} diff --git a/third_party/bspatch/mbspatch.h b/third_party/bspatch/mbspatch.h new file mode 100644 index 00000000000..1a901d7c6ed --- /dev/null +++ b/third_party/bspatch/mbspatch.h @@ -0,0 +1,112 @@ +/*- + * Copyright 2003,2004 Colin Percival + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Changelog: + * 2005-04-26 - Define the header as a C structure, add a CRC32 checksum to + * the header, and make all the types 32-bit. + * --Benjamin Smedberg + */ + +#ifndef bspatch_h__ +#define bspatch_h__ + +#define OK 0 +#define MEM_ERROR 1 +// #define IO_ERROR 2 // Use READ_ERROR or WRITE_ERROR instead +#define USAGE_ERROR 3 +#define CRC_ERROR 4 +#define PARSE_ERROR 5 +#define READ_ERROR 6 +#define WRITE_ERROR 7 +#define UNEXPECTED_ERROR 8 + +typedef struct MBSPatchHeader_ { + /* "MBDIFF10" */ + char tag[8]; + + /* Length of the file to be patched */ + unsigned int slen; + + /* CRC32 of the file to be patched */ + unsigned int scrc32; + + /* Length of the result file */ + unsigned int dlen; + + /* Length of the control block in bytes */ + unsigned int cblen; + + /* Length of the diff block in bytes */ + unsigned int difflen; + + /* Length of the extra block in bytes */ + unsigned int extralen; + + /* Control block (MBSPatchTriple[]) */ + /* Diff block (binary data) */ + /* Extra block (binary data) */ +} MBSPatchHeader; + +/** + * Read the header of a patch file into the MBSPatchHeader structure. + * + * @param fd Must have been opened for reading, and be at the beginning + * of the file. + */ +int MBS_ReadHeader(int fd, MBSPatchHeader *header); + +/** + * Apply a patch. This method does not validate the checksum of the original + * file: client code should validate the checksum before calling this method. + * + * @param patchfd Must have been processed by MBS_ReadHeader + * @param fbuffer The original file read into a memory buffer of length + * header->slen. + * @param filefd Must have been opened for writing. Should be truncated + * to header->dlen if it is an existing file. The offset + * should be at the beginning of the file. + */ +int MBS_ApplyPatch(const MBSPatchHeader *header, int patchfd, + unsigned char *fbuffer, int filefd); + +typedef struct MBSPatchTriple_ { + unsigned int x; /* add x bytes from oldfile to x bytes from the diff block */ + unsigned int y; /* copy y bytes from the extra block */ + int z; /* seek forwards in oldfile by z bytes */ +} MBSPatchTriple; + +/** + * Apply the given patch file to a given source file. This method validates + * the CRC of the original file stored in the patch file, before applying the + * patch to it. + */ +int ApplyBinaryPatch(const wchar_t *old_file, const wchar_t *patch_file, + const wchar_t *new_file); + +/** + * Calculates Crc of the given buffer by calling CRC method in LZMA SDK + */ +int CalculateCrc(const unsigned char *buf, int size); +#endif // bspatch_h__ diff --git a/third_party/bspatch/visibility.gni b/third_party/bspatch/visibility.gni new file mode 100644 index 00000000000..a966f9022cd --- /dev/null +++ b/third_party/bspatch/visibility.gni @@ -0,0 +1,6 @@ +# bspatch is infrequently updated and rarely used. New additions to the below +# list should be scrutinized. +visibility = [ + "//brave/third_party/bspatch", + "//chrome/installer/setup/*", +]