Как найти файл манифест json

I assume that it is for chrome. I have read that I can set the permissions in that file to avoid XSS errors while developing.

asked May 2, 2011 at 20:40

KevinDeus's user avatar

1

There are many json files for your chrome experience from Native chrome json files to json files for chrome extensions. Most of them can be found at

C:UsersusernameAppDataLocalGoogleChrome

Most manifest.json files are found for extensions in

C:UsersusernameAppDataLocalGoogleChromeUser DataDefaultExtensions

answered May 2, 2011 at 20:55

Tim Joyce's user avatar

Tim JoyceTim Joyce

4,4875 gold badges34 silver badges49 bronze badges

In linux mine are located in .config directory:

./.config/google-chrome/Default/Extensions/bjnkloegafmkhgpjglcbldhaokjpandj/1.0.0.0_0/manifest.json
./.config/google-chrome/Default/Extensions/gbammbheopgpmaagmckhpjbfgdfkpadb/1.9.1.8_0/manifest.json
./.config/google-chrome/Default/Extensions/aknpkdffaafgjchaibgeefbgmgeghloj/1.1.2.1_0/_locales/ar/messages.json
./.config/google-chrome/Default/Extensions/aknpkdffaafgjchaibgeefbgmgeghloj/1.1.2.1_0/_locales/zh-TW/messages.json
./.config/google-chrome/Default/Extensions/aknpkdffaafgjchaibgeefbgmgeghloj/1.1.2.1_0/_locales/es-419/messages.json
./.config/transmission/settings.json
./.config/transmission/stats.json

answered Feb 28, 2012 at 15:37

Peter Teoh's user avatar

Peter TeohPeter Teoh

6,3074 gold badges42 silver badges58 bronze badges

Nov 5, 2018 — Updated Sep 14, 2022

François Beaufort

Thomas Steiner

The web app manifest is a JSON file that tells the browser about your Progressive Web App and how it should behave when installed on the user’s desktop or mobile device. A typical manifest file includes the app name, the icons the app should use, and the URL that should be opened when the app is launched, among other things.

Browser support

  • Chrome 39, Supported 39
  • Firefox, Not supported
  • Edge 79, Supported 79
  • Safari, Not supported

Source

Create the manifest file #

The manifest file can have any name, but is commonly named manifest.json and served from the root (your website’s top-level directory). The specification suggests the extension should be .webmanifest, but browsers also support .json extensions, which may be easier for developers to understand.

A typical manifest looks something like this:

{
"short_name": "Weather",
"name": "Weather: Do I need an umbrella?",
"icons": [
{
"src": "/images/icons-vector.svg",
"type": "image/svg+xml",
"sizes": "512x512"
},
{
"src": "/images/icons-192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/images/icons-512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"id": "/?source=pwa",
"start_url": "/?source=pwa",
"background_color": "#3367D6",
"display": "standalone",
"scope": "/",
"theme_color": "#3367D6",
"shortcuts": [
{
"name": "How's weather today?",
"short_name": "Today",
"description": "View weather information for today",
"url": "/today?source=pwa",
"icons": [{ "src": "/images/today.png", "sizes": "192x192" }]
},
{
"name": "How's weather tomorrow?",
"short_name": "Tomorrow",
"description": "View weather information for tomorrow",
"url": "/tomorrow?source=pwa",
"icons": [{ "src": "/images/tomorrow.png", "sizes": "192x192" }]
}
],
"description": "Weather forecast information",
"screenshots": [
{
"src": "/images/screenshot1.png",
"type": "image/png",
"sizes": "540x720",
"form_factor": "narrow"
},
{
"src": "/images/screenshot2.jpg",
"type": "image/jpg",
"sizes": "720x540",
"form_factor": "wide"
}
]
}

Key manifest properties #

short_name and/or name #

You must provide at least the short_name or name property. If both are provided, short_name is used on the user’s home screen, launcher, or other places where space may be limited. name is used when the app is installed.

icons #

When a user installs your PWA, you can define a set of icons for the browser to use on the home screen, app launcher, task switcher, splash screen, and so on.

The icons property is an array of image objects. Each object must include the src, a sizes property, and the type of image. To use maskable icons, sometimes referred to as adaptive icons on Android, you’ll also need to add "purpose": "any maskable" to the icon property.

For Chromium, you must provide at least a 192×192 pixel icon, and a 512×512 pixel icon. If only those two icon sizes are provided, Chrome automatically scales the icons to fit the device. If you’d prefer to scale your own icons, and adjust them for pixel-perfection, provide icons in increments of 48dp.

id #

The id property allows you to explicitly define the identifier used for your application. Adding the id property to the manifest removes the dependency on the start_url or the location of the manifest, and makes it possible for them to be updated in the future. For more information, see Uniquely identifying PWAs with the web app manifest id property.

start_url #

The start_url is required and tells the browser where your application should start when it is launched, and prevents the app from starting on whatever page the user was on when they added your app to their home screen.

Your start_url should direct the user straight into your app, rather than a product landing page. Think about what the user will want to do once they open your app, and place them there.

background_color #

The background_color property is used on the splash screen when the application is first launched on mobile.

display #

You can customize what browser UI is shown when your app is launched. For example, you can hide the address bar and browser user interface elements. Games can even be made to launch full screen. The display property takes one of the following values:

display_override #

Web apps can choose how they are displayed by setting a display mode in their manifest as explained above. Browsers are not required to support all display modes, but they are required to support the spec-defined fallback chain ("fullscreen""standalone""minimal-ui""browser"). If they don’t support a given mode, they fall back to the next display mode in the chain. This inflexible behavior can be problematic in rare cases. For example, a developer cannot request "minimal-ui" without being forced back into the "browser" display mode when "minimal-ui" is not supported. Another problem is that the current behavior makes it impossible to introduce new display modes in a backward compatible way, since explorations like tabbed application mode don’t have a natural place in the fallback chain.

These problems are solved by the display_override property, which the browser considers before the display property. Its value is a sequence of strings that are considered in the listed order, and the first supported display mode is applied. If none are supported, the browser falls back to evaluating the display field.

Consider the example below. (The details of "window-control-overlay" are out-of-scope for this article.)

{
"display_override": ["window-control-overlay", "minimal-ui"],
"display": "standalone",
}

As stated, the browser will look at display_override first.

  1. "window-control-overlay"
  2. "minimal-ui"

If neither option is available, it falls back to display. If "standalone" is not available, it resumes spec-defined fallabck chain from that point.

  1. "standalone"
  2. "minimal-ui"
  3. "browser"

scope #

The scope defines the set of URLs that the browser considers to be within your app, and is used to decide when the user has left the app. The scope controls the URL structure that encompasses all the entry and exit points in your web app. Your start_url must reside within the scope.

A few other notes on scope:

  • If you don’t include a scope in your manifest, then the default implied scope is the directory that your web app manifest is served from.
  • The scope attribute can be a relative path (../), or any higher level path (/) which would allow for an increase in coverage of navigations in your web app.
  • The start_url must be in the scope.
  • The start_url is relative to the path defined in the scope attribute.
  • A start_url starting with / will always be the root of the origin.

theme_color #

The theme_color sets the color of the tool bar, and may be reflected in the app’s preview in task switchers. The theme_color should match the meta theme color specified in your document head.

An example of a PWA window with custom theme_color.

An example of a PWA window with custom theme_color.

As of Chromium 93 and Safari 15, you can adjust this color in a media query with the media attribute of the meta theme color element. The first one that matches will be picked. For example, you could have one color for light mode and another one for dark mode. At the time of writing, you can’t define those in your manifest. See w3c/manifest#975 GitHub issue.

<meta name="theme-color" media="(prefers-color-scheme: light)" content="white">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black">

shortcuts #

The shortcuts property is an array of app shortcut objects whose goal is to provide quick access to key tasks within your app. Each member is a dictionary that contains at least a name and a url.

description #

The description property describes the purpose of your app.

screenshots #

The screenshots property is an array of image objects representing your app in common usage scenarios. Each object must include the src, a sizes property, and the type of image. The form_factor property is optional. You can set it either to "wide" for screenshots applicable to wide screens only or "narrow" for narrow screenshots. You should only use it when the layout varies by screen size.

In Chrome, the image must respond to certain criteria:

  • Width and height must be at least 320px and at most 3840px.
  • The maximum dimension can’t be more than 2.3 times as long as the minimum dimension.
  • All screenshots matching the appropriate form factor must have the same aspect ratio.

Screenshots of richer installation UI on desktop and mobile

Richer installation UI on desktop and mobile.

Add the web app manifest to your pages #

After creating the manifest, add a <link> tag to all the pages of your Progressive Web App. For example:

<link rel="manifest" href="/manifest.json">

Test your manifest #

To verify your manifest is setup correctly, use the Manifest pane in the Application panel of Chrome DevTools.

The application panel in Chrome Devtools with the manifest tab selected.

Test your manifest in DevTools.

This pane provides a human-readable version of many of your manifest’s properties, and makes it easy to verify that all of the images are loading properly.

Splash screens on mobile #

When your app first launches on mobile, it can take a moment for the browser to spin up, and the initial content to begin rendering. Instead of showing a white screen that may look to the user like the app is stalled, the browser will show a splash screen until the first paint.

Chrome automatically creates the splash screen from the manifest properties, specifically:

  • name
  • background_color
  • icons

The background_color should be the same color as the load page, to provide a smooth transition from the splash screen to your app.

Chrome will choose the icon that closely matches the device resolution for the device. Providing 192px and 512px icons is sufficient for most cases, but you can provide additional icons for pixel perfection.

Further reading #

There are several additional properties that can be added to the web app manifest. Refer to the MDN Web App Manifest documentation for more information.

Return to all articles

manifest.json — это текстовый файл в формате json, который можно открыть любым текстовым редактором, например Блокнот.

Когда пользователь пожелает добавить ваш сайт в избранное, браузер будет использовать иконку из favicon.
Если посетитель вашего сайта добавить иконку на рабочий стол компьютера, то система будет искать картинку для отображения в файле manifest.json.
То же будет и на мобильном телефоне при добавлении ссылки на страницу сайта на рабочий стол.

По умолчанию файл manifest.json система будет искать в корне вашего сайта. Чтобы указать другое имя или пусть используйте тег

<link rel="manifest" href="/manifest.json">

Размещайте его в секции <head></head>

Пример содержимого файла manifest.json:Скачать пример

{"name": "WEB - технологии",
"short_name": "HtmlWeb",
"description": "Примеры, скрипты, справочник, уроки для начинающих по HTML, PHP, AJAX, JavaScript. Сервисы, базы данных и API для ваших сайтов. Продвижение и поисковая оптимизация.",
"display": "standalone",
"start_url": "https://htmlweb.ru",
"shortcuts": [
    {
        "name": "",
        "url": "/",
        "icons": [{ "src": "/pic/ico/192x192.png", "sizes": "192x192" }]
    }
    ],
"icons" : [
{
"src": "/pic/ico/44x44.png",
"sizes": "44x44",
"type": "image/png"
},
{
"src": "/pic/ico/48x48.png",
"sizes": "48x48"
},
{
"src": "/pic/ico/1240x600.png",
"sizes": "1240x600"
},
{
"src": "/pic/ico/300x300.png",
"sizes": "300x300"
},
{
"src": "/pic/ico/150x150.png",
"sizes": "150x150"
},
{
"src": "/pic/ico/88x88.png",
"sizes": "88x88"
},
{
"src": "/pic/ico/24x24.png",
"sizes": "24x24"
},
{
"src": "/pic/ico/50x50.png",
"sizes": "50x50"
},
{
"src": "/pic/ico/620x300.png",
"sizes": "620x300"
},
{
"src": "/pic/ico/192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/pic/ico/144x144.png",
"sizes": "144x144"
},
{
"src": "/pic/ico/96x96.png",
"sizes": "96x96"
},
{
"src": "/pic/ico/72x72.png",
"sizes": "72x72"
},
{
"src": "/pic/ico/36x36.png",
"sizes": "36x36"
},
{
"src": "/pic/ico/1024x1024.png",
"sizes": "1024x1024"
},
{
"src": "/pic/ico/180x180.png",
"sizes": "180x180"
},
{
"src": "/pic/ico/152x152.png",
"sizes": "152x152"
},
{
"src": "/pic/ico/120x120.png",
"sizes": "120x120"
},
{
"src": "/pic/ico/76x76.png",
"sizes": "76x76"
}]
}

manifest.json стал продолжением и расширяет возможности favicon.ico. Favicon.ico положено делать составной с несколькими разрешениями в одном файле.
Так же можно добавлять favicon.ico в png формате или svg-формате. Браузер сам выбирает из файла формата ico требуемое разрешение. Но для этого ему нужно скачать и разобрать файл формата ico.
В варианте с manifest.json вы даете ссылку на конкретный файл нужного размера.
Разрешение файла должно строго соответствовать указанному в атрибуте «sizes»!

Чтобы не было искажения или размытия файлы картинок делают из векторного формата.
Вы как вариант для маленьких картинок и крупных можно использовать разные лого или лого с разной проработкой деталей.
Можно указать в файле manifest.json другие форматы и разрешения, но главное чтобы были указанные здесь разрежение, который являются обязательными.

Поля и их описание:

  • name – имя, которое будет отображаться под иконкой, ну и вообще везде, где будет отображаться ваше «приложение»
  • short_name – будет использоваться в тех случаях, когда места для отображения полного имени недостаточно
  • icons – набор иконок разных размеров
  • start_url – определяет url, которые открывается при нажатии иконки (можно использовать, чтобы зафиксировать пользователей, которые открывают сайт через иконку на рабочем столе, добавив параметр, допустим, ?src=homescreen в url)
  • display — fullscreen, standalone, minimal-ui, browser – отвечает за то, как будет отображаться ваш сайт (с адресной строкой без нее и т.п.)
  • orientation – none, portrait, landscape — ориентация. Не фиксируется на Apple. Пути решения здесь.
  • theme_color – позволяет изменить цвет адресной строки браузера, например: theme_color: #2196F3
  • background_color – устанавливает цвет страницы до того как она загрузилась. Пока страница не загрузилась пользователь видит серое пустое поле.
    Оптимально изменить этот цвет на цвет фона сайта.
    theme_color и background_color можно увидеть только если «display»: «standalone» или «fullscreen»

У иконок Apple есть свои особенности, с ними можно ознакомиться на
офф.сайте

Полезные ссылки по теме:

  • manifest.json на w3.org
  • manifest.json на developer.mozilla.org
  • Создание Robots.txt
  • Создание favicon.ico
  • Создание sitemap.xml

Введение

Расширения браузера — это web-приложения, которые устанавливаются в web-браузер, чтобы расширить его возможности. Обычно, для того чтобы воспользоваться расширением, пользователю нужно найти его в Chrome Web Store и установить.

В этой статье я покажу как создать расширение для браузера Google Chrome с нуля. Это расширение будет использовать API браузера, для того чтобы получить доступ к содержимому web-страницы любой открытой вкладки. С помощью этих API можно не только читать информацию с открытых web-сайтов, но и взаимодействовать с этими страницами, например, переходить по ссылкам или нажимать на кнопки. Таким образом расширения браузера могут использоваться для широкого круга задач автоматизации на стороне клиента, таких как web-scrape или даже автоматизированное тестирование frontend.

Мы создадим расширение, которое называется Image Grabber. Оно будет содержать интерфейс для подключения к web-странице и для извлечения из нее информации о всех изображениях. Далее, при нажатии на кнопку «GRAB NOW» список абсолютных URL этих изображений будет скопирован в буфер обмена. В этом процессе вы познакомитесь с фундаментальными строительными блоками, которые в дальнейшем можно будет использовать для создания других расширений.

Расширения, создаваемые таким образом для браузера Chrome совместимы с другими браузерами, основанными на движке Chromium и могут быть установлены, например, в Yandex-браузер или Opera.

В результате при правильном выполнении всех шагов, вы получите расширение, которое будет выглядеть и работать так, как показано на следующем видео:

Это только первая часть истории. Во второй части я покажу, как расширить интерфейс, чтобы выгрузить все или выбранные изображения в виде ZIP-архива, а также, как опубликовать свое расширение в Chrome Web Store.

Базовая структура расширения

Расширение Google Chrome — это web-приложение, содержащее любое количество HTML-страниц, файлов CSS и изображений, а также, файл manifest.json, который определяет как расширение выглядит и работает. Все эти файлы должны быть в одной папке.

Минимальное расширение состоит только из одного файла manifest.json. Вот пример этого файла, который вы можете использовать как шаблон при начале создания любого расширения:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {},
    "action": {},
    "permissions": [],
    "background":{}
}

Здесь только manifest_version должен быть равен 3. Остальные поля заполняются произвольно в зависимости от назначения расширения: name — название расширения, description — краткое описание, version — версия. Остальные параметры мы будем заполнять по ходу разработки интерфейса. Полный список параметров manifest.json можно найти в официальной документации.

Папка с одним файлом manifest.json — это минимальное расширение, которое может быть установлено в Google Chrome и запущено. Оно ничего не будет делать, однако именно с установки нужно начинать. Поэтому создайте папку image_grabber, затем добавьте в нее текстовый файл manifest.json с содержимым приведенным выше.

Установка расширения

В процессе разработки расширения, оно представляет собой папку с файлами. В терминологии Google Chrome это называется «unpacked extension». После завершения разработки, его нужно упаковать в ZIP-архив и загрузить в Chrome Web Store, откуда оно потом может быть установлено в браузер.

Однако на этапе разработки, «unpacked extension» тоже можно установить, просто как папку с файлами. Для этого нужно ввести chrome://extensions в браузере, чтобы открыть Chrome Extensions Manager:

Это покажет список уже установленных расширений. Чтобы устанавливать в него «unpacked extensions», включите флажок «Developer mode» в правом верхнем углу. После этого должна отобразиться панель управления расширениями.

Затем нажмите первую кнопку Load unpacked и укажите папку, в которой находится расширение с файлом manifest.json. В нашем случае это папка image_grabber. Расширение должно отобразиться в списке:

Эта панель должна показывать данные расширения такие как имя, описание и версию, ранее указанные в manifest.json, а также уникальный идентификатор, присвоенный этому расширению. Каждый раз после изменения manifest.json и файлов, непосредственно указанных в нем, нужно обновлять расширение в браузере, нажимая на кнопку «Reload«:

Чтобы запустить и использовать установленное расширение в браузере, нажмите кнопку Extensions на панели инструментов Google Chrome рядом с URL и найдите «Image Grabber» в списке установленных расширений:

Также можно нажать иконку Pin в списке рядом с расширением, чтобы добавить кнопку данного расширения на панель Chrome, рядом с другими расширениями:

Вот как выглядит минимальное расширение — кнопка с серым прямоугольником и буквой внутри. При нажатии на эту кнопку ничего не происходит. Давайте заполним остальные поля файла manifest.json, чтобы изменить картинку расширения и заставить его выполнять нужные действия.

Добавление иконок

Параметр icons файла manifest.json принимает объект JavaScript, ключами которого являются размеры иконок, а значениями пути к файлам с этими иконками. Иконка это картинка с расширением PNG (для прозрачности). Расширение должно иметь иконки разных размеров: 16×16, 32×32, 48×48 и 128×128. Я создал иконки для всех этих размеров и поместил их в папку «icons» внутри папки с расширением. Сделайте то же самое. Имена файлов могут быть любыми:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {
        "16":"icons/16.png",
        "32":"icons/32.png",
        "48":"icons/48.png",
        "128":"icons/128.png"
    },
    "action": {},
    "permissions": [],
    "background":{}
}

Как видно, здесь указаны относительные пути к файлам в папке icons.

После изменения manifest.json нажмите кнопку «Reload» на панели расширения Image Grabber в Chrome Extensions Manager, чтобы обновить установленное расширение. Если все сделано как описано выше, то картинка на кнопке расширения должна измениться:

Так значительно лучше, однако когда мы нажимаем на эту кнопку все еще ничего не происходит. Пришло время добавить «действия» (actions) к расширению.

Создание интерфейса расширения

Расширение должно что-то делать, то есть запускать определенные действия. Расширение может выполнять действия двумя способами:

  • В фоне, при запуске расширения и при дальнейшей его работе

  • Из интерфейса, когда пользователь нажимает кнопку расширения и затем взаимодействует с различными интерфейсными элементами.

Расширение может использовать обе эти возможности одновременно.

Чтобы запускать действия в фоне, нужно создать Javascript-файл и указать путь к нему в параметре «background» файла manifest.json. Этот скрипт может содержать функции обработчики различных событий браузера и жизненного цикла самого расширения. Background-скрипт слушает эти события и запускает написанные для них функции обработчики.

Однако в этом расширении мы этим пользоваться не будем и параметр «background» останется пустым. Он присутствует только для того, чтобы показать что это возможно и что данный файл manifest.json может использоваться для создания расширений любого типа. Однако расширение Image Grabber выполняет действия только когда пользователь нажимает кнопку «GRAB NOW» из интерфейса.

Соответственно мы создадим интерфейс для расширения. Интерфейс расширения это фактически Web-сайт, состоящий из HTML-страниц с элементами управления, CSS-таблиц стилей и скриптов, которые реагируют на события элементов управления из этих HTML-страниц и выполняют определенные действия, используя в частности API расширений Google Chrome.

Интерфейс должен содержать главную страницу, которая появляется при нажатии на кнопку расширения. Эта страница может появляться либо в новой вкладке браузера, либо внутри всплывающего окна, как было показано на видео. Именно так и будет реализован интерфейс Image Grabber. Чтобы создать интерфейс всплывающего окна, внесите следующие изменения в manifest.json:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {
        "16":"icons/16.png",
        "32":"icons/32.png",
        "48":"icons/48.png",
        "128":"icons/128.png"
    },
    "action": {
        "default_popup":"popup.html"
    },
    "permissions": [],
    "background":{}
}

Здесь определено, что основное действие (action) расширения это всплывающее окно (popup), которое содержит страницу popup.html.

Теперь создайте файл popup.html с заголовком Image Grabber и кнопкой «GRAB NOW» и поместите его в папку с расширением:

<!DOCTYPE html>
<html>
    <head>
        <title>Image Grabber</title>
    </head>
    <body>
        <h1>Image Grabber</h1>
        <button id="grabBtn">GRAB NOW</button>
    </body>
</html>

Кнопка имеет идентификатор grabBtn который в дальнейшем будет использоваться из скрипта, чтобы реагировать на нажатия.

Чтобы увидеть, что изменилось, снова обновите расширение в Chrome Extensions Manager. Если все было сделано как написано выше, то при нажатии на иконку расширения будет появляться содержимое файла popup.html во всплывающем окне:

Работает!! Но выглядит не очень. Теперь нужно стилизовать этот интерфейс с помощью CSS.

Создайте файл popup.css со следующим содержимым и поместите его в папку с расширением:

body {
    text-align:center;
    width:200px;
}

button {
    width:100%;
    color:white;
    background:linear-gradient(#01a9e1, #5bc4bc);
    border-width:0px;
    border-radius:20px;
    padding:5px;
    font-weight: bold;
    cursor:pointer;
}

Этот файл определяет стили для кнопки и для body всей страницы: все содержимое выровнено по центру, а также, ширина содержимого будет 200 пикселей.

Добавьте ссылку на файл с этими стилями в popup.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Image Grabber</title>
        <link rel="stylesheet" type="text/css" href="popup.css"/>
    </head>
    <body>
        <h1>Image Grabber</h1>
        <button id="grabBtn">GRAB NOW</button>
    </body>
</html>

Теперь при нажатии на кнопку расширения появится стилизованный интерфейс:

Обратите внимание, что в данном случае не требовалось нажимать кнопку Reload, для того чтобы обновить расширение. Изменения в файлах web-интерфейса расширения начинают работать автоматически.

Чтобы придать интерфейсу завершенность, добавим JavaScript-код, который будет реагировать на нажатия кнопки «GRAB NOW«. Создайте файл popup.js в папке с расширением со следующим содержимым:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    alert("CLICKED");
})

и добавьте ссылку на этот файл в popup.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Image Grabber</title>
        <link rel="stylesheet" type="text/css" href="popup.css"/>
    </head>
    <body>
        <h1>Image Grabber</h1>
        <button id="grabBtn">GRAB NOW</button>
        <script src="popup.js"></script>
    </body>
</html>

Таким образом мы добавили событие onClick для кнопки с идентификатором «grabBtn«. Теперь, при нажатии на кнопку «GRAB NOW» в интерфейсе, должно появляться предупреждение «CLICKED».

В результате мы имеем такую файловую систему расширения:

Это все файлы, других больше добавлять не будем. Такую структуру можно использовать как базу для создания расширений Google Chrome с интерфейсом основанном на всплывающих окнах.

Теперь реализуем бизнес логику расширения: при нажатии на кнопку «GRAB NOW» расширение должно извлечь список путей ко всем картинкам текущей страницы в браузере и скопировать этот список в буфер обмена.

Функция «GRAB NOW»

Используя Javascript в расширении можно делать все то же самое, что и при использовании JavaScript на web-сайте, например открывать различные web-страницы из текущей или делать AJAX HTTP-запросы к различным серверам. Но в дополнении к этому, Javascript-код в расширении браузера может использовать различные API Chrome для взаимодействия с компонентами самого браузера. Большинство этих API доступно через пространство имен chrome. В частности, расширение Image Grabber будет использовать следующие API:

  • chrome.tabs — Chrome Tabs API. Будет использоваться для доступа к активной вкладке браузера.

  • chrome.scripting — Chrome Scripting API. Будет использоваться для внедрения кода JavaScript на web-страницу активной вкладки и для исполнения этого кода в контексте этой страницы.

Получение необходимых разрешений

По умолчанию, из соображений безопасности, расширение Chrome не имеет доступа ко всем API браузера. Необходимо запросить этот доступ через механизм разрешений. Для этого нужно указать список требуемых разрешений в параметре permissions в файле manifest.json. Существует множество различных разрешений, которые описаны здесь: https://developer.chrome.com/docs/extensions/mv3/declare_permissions/. Для Image Grabber нужно указать следующие из них:

  • activeTab — разрешение для получения доступа к текущей вкладке браузера.

  • scripting — разрешение для получения доступа к Chrome Scripting API для исполнения скриптов в контексте Web-страницы, открытой в браузере.

Добавьте эти разрешения в параметр permissions в файле manifest.json:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {
        "16":"icons/16.png",
        "32":"icons/32.png",
        "48":"icons/48.png",
        "128":"icons/128.png"
    },
    "action": {
        "default_popup":"popup.html",
    },
    "permissions": ["scripting", "activeTab"],
    "background":{}
}

и обновите расширение в Chrome Extensions Manager.

Между тем, листинг выше — это окончательный вариант файла manifest.json для расширения. Теперь здесь есть все: название, описание, версия, иконки, ссылка на главную страницу интерфейса и разрешения на доступ к браузеру, которые этому интерфейсу необходимы.

Получение информации об активной вкладке браузера

Для получения информации о вкладках браузера используется функция chrome.tabs.query, которая определена следующим образом:

chrome.tabs.query(queryObject,callback)
  • queryObject — объект запроса в котором указываются параметры поиска нужных вкладок.

  • callback — функция обратного вызова, которая выполняется после выполнения этого запроса. В нее передается массив tabs, содержащий все найденные вкладки, соответствующие критерию запроса. Каждый элемент этого массива — это объект типа Tab, содержащий информацию о вкладке, включая ее уникальный идентификатор. Этот идентификатор будет использоваться для исполнения Javascript-кода на этой вкладке.

Здесь я не буду полностью описывать синтаксис queryObject, а также все поля возвращаемых объектов Tabs. Эту информацию можно найти в официальной документации по chrome.tabs: https://developer.chrome.com/docs/extensions/reference/tabs/.

Для расширения Image Grabber нужно получить только активную вкладку. Для этой цели queryObject должен быть определен как: {active: true} .

Теперь давайте изменим код обработчика нажатия кнопки grabBtn в popup.js чтобы он получал активную вкладку и ее идентификатор, когда пользователь нажимает на кнопку «GRAB NOW» в интерфейсе расширения:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    chrome.tabs.query({active: true}, (tabs) => {
        const tab = tabs[0];
        if (tab) {
            alert(tab.id)
        } else {
            alert("There are no active tabs")
        }
    })
})

Этот код выполняет запрос ко всем вкладкам, которые активны. Может быть только одна такая вкладка, поэтому к ней можно обратиться как tabs[0]. Если такая вкладка существует, то функция отображает ее id, а если не существует, то показывает сообщение об ошибке.

Если все сделано как описано выше, то при нажатии кнопки GRAB NOW должен появляться идентификатор текущей вкладки браузера. Далее мы изменим этот код таким образом, чтобы этот идентификатор использовался для доступа к web-странице, открытой на этой вкладке.

Извлечение изображений из текущей страницы

Расширение может взаимодействовать с открытыми страницами с помощью интерфейса Chrome Scripting API, доступного через chrome.scripting. В частности, мы будем использовать функцию для внедрения своего кода в текущую web-страницу и для исполнения этого кода в ее контексте. При запуске этот код будет иметь доступ к DOM-дереву этой страницы и сможет делать нужные нам действия с любыми HTML-тэгами.

Для внедрения скрипта в страницу Web-браузера используется функция executeScript, определенная следующим образом:

chrome.scripting.executeScript(injectSpec,callback)

Рассмотрим ее параметры.

injectSpec

Это объект типа ScriptInjection. В нем определяется какой Javascript-код, в какую web-страницу и каким образом внедрить. В частности, в параметре target указывается идентификатор вкладки браузера со страницей, которая нам нужна. Мы получили его ранее. Остальные параметры указывают каким образом передать скрипт на эту страницу. Возможно использовать следующие параметры для передачи скрипта:

  • files — указывается список путей к JS-файлам, которые нужно внедрить, относительно корневой папки расширения

  • func — указывается Javascript-функция, которую нужно внедрить. Функция должна быть предварительно написана.

Скрипт, который планируется внедрить, будет извлекать список изображений с web-страницы и возвращать список URL этих изображений. Это небольшой скрипт, поэтому достаточно создать функцию для него. Она будет называться grabImages. Эта функция должна извлекать список URL изображений web-страницы и возвращать его. Возвращаемое значение этой функции будет передано расширению.

В итоге injectSpec будет определен следующим образом:

{
    target:{ tabId: tab.id, allFrames: true },
    func: grabImages,
}, 

Здесь функция, указанная в параметре func будет внедрена на страницу, определенную параметром target. В параметре target указывается полученный на предыдущем этапе идентификатор вкладки, а также, устанавливается параметр allFrames. Этот дополнительный параметр говорит что скрипт должен выполняться во всех фреймах web-страницы, в случае если они на этой странице есть.

Саму функцию grabImages мы напишем чуть позже.

callback

Это функция обратного вызова, которая будет вызвана после того, как внедренный скрипт исполнится на странице и во всех ее фреймах. В качестве параметра в ней будет массив результатов, которые вернула функция grabImages для каждого фрейма (возможно это будет всего один элемент, если фреймов нет). Каждый элемент этого массива — это объект типа InjectionResult. Он в частности содержит свойство result. Именно оно содержит то, что возвращает функция grabImages, т.е. список URL-ов.

Теперь соберем все вместе в следующем коде:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    chrome.tabs.query({active: true}, function(tabs) {
        var tab = tabs[0];
        if (tab) {
            chrome.scripting.executeScript(
                {
                    target:{tabId: tab.id, allFrames: true},
                    func:grabImages
                },
                onResult
            )
        } else {
            alert("There are no active tabs")
        }
    })
})

function grabImages() {
    // TODO - Запросить список изображений
    // и вернуть список их URL-ов
}

function onResult(frames) {
    // TODO - Объединить списки URL-ов, полученных из каждого фрейма в один,
    // затем объединить их в строку, разделенную символом перевода строки
    // и скопировать в буфер обмена
}

Функция grabImages может быть определена следующим образом:

/**
 * Функция исполняется на удаленной странице браузера,
 * получает список изображений и возвращает массив
 * путей к ним
 * 
 *  @return Array массив строк
 */
function grabImages() {
    const images = document.querySelectorAll("img");
    return Array.from(images).map(image=>image.src);    
}

Здесь все просто: получаем список DOM-элементов <img> и извлекаем свойство src каждого из них в итоговый массив. Считаю нужным напомнить, что объект document, указанный в этой функции указывает на содержимое не той HTML-страницы, где находится функция grabImages, а удаленной web-страницы, в которую эта функция будет внедрена.

После того как данная функция выполнится в каждом фрейме, результаты будут объединены в единый массив и переданы в функцию onResult. Эта функция может быть определена следующим образом:

/**
 * Выполняется после того как вызовы grabImages 
 * выполнены во всех фреймах удаленной web-страницы.
 * Функция объединяет результаты в строку и копирует  
 * список путей к изображениям в буфер обмена
 * 
 * @param {[]InjectionResult} frames Массив результатов
 * функции grabImages
 */
function onResult(frames) {
    // Если результатов нет
    if (!frames || !frames.length) { 
        alert("Could not retrieve images from specified page");
        return;
    }
    // Объединить списки URL из каждого фрейма в один массив
    const imageUrls = frames.map(frame=>frame.result)
                            .reduce((r1,r2)=>r1.concat(r2));
    // Скопировать в буфер обмена полученный массив  
    // объединив его в строку, используя символ перевода строки 
    // как разделитель
    window.navigator.clipboard
          .writeText(imageUrls.join("n"))
          .then(()=>{
             // закрыть окно расширения после 
             // завершения
             window.close();
          });
}

Следует упомянуть что не все вкладки браузера — это вкладки с web-страницами. Например, может быть вкладка свойств браузера. Страницы на таких вкладках не имеют свойства document. В этом случае функция grabImages не выполнится и не вернет результатов. Этот случай обрабатывается в самом начале функции. Затем массив массивов результатов объединяется в единый плоский массив используя концепцию map/reduce, затем функция window.navigator.clipboard используется, чтобы скопировать его в буфер обмена. Предварительно массив результатов преобразовывается в строку, разделенную символом перевода строки.

Завершающие штрихи

Здесь я описал только незначительную часть Chrome Scripting API и описал только в контексте данного расширения. Полная документация по Chrome Scripting API доступна здесь: https://developer.chrome.com/docs/extensions/reference/scripting/.

Теперь немного почистим код. Здесь я считаю нужным часть функции обработчика grabBtn, которая выполняет chrome.scripting.executeScript вынести в отдельную функцию execScript. В результате файл popup.js выглядит так:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    // Получить активную вкладку браузера
    chrome.tabs.query({active: true}, function(tabs) {
        var tab = tabs[0];
        // и если она есть, то выполнить на ней скрипт
        if (tab) {
            execScript(tab);
        } else {
            alert("There are no active tabs")
        }
    })
})

/**
 * Выполняет функцию grabImages() на веб-странице указанной
 * вкладки и во всех ее фреймах,
 * @param tab {Tab} Объект вкладки браузера
 */
function execScript(tab) {
    // Выполнить функцию на странице указанной вкладки
    // и передать результат ее выполнения в функцию onResult
    chrome.scripting.executeScript(
        {
            target:{tabId: tab.id, allFrames: true},
            func:grabImages
        },
        onResult
    )
}

/**
 * Получает список абсолютных путей всех картинок
 * на удаленной странице
 * 
 *  @return Array Массив URL
 */
function grabImages() {
    const images = document.querySelectorAll("img");
    return Array.from(images).map(image=>image.src);    
}

/**
 * Выполняется после того как вызовы grabImages 
 * выполнены во всех фреймах удаленной web-страницы.
 * Функция объединяет результаты в строку и копирует  
 * список путей к изображениям в буфер обмена
 * 
 * @param {[]InjectionResult} frames Массив результатов
 * функции grabImages
 */
function onResult(frames) {
    // Если результатов нет
    if (!frames || !frames.length) { 
        alert("Could not retrieve images from specified page");
        return;
    }
    // Объединить списки URL из каждого фрейма в один массив
    const imageUrls = frames.map(frame=>frame.result)
                            .reduce((r1,r2)=>r1.concat(r2));
    // Скопировать в буфер обмена полученный массив  
    // объединив его в строку, используя возврат каретки 
    // как разделитель  
    window.navigator.clipboard
          .writeText(imageUrls.join("n"))
          .then(()=>{
             // закрыть окно расширения после 
             // завершения
             window.close();
          });
}

Заключение

Теперь, если нажать по иконке расширения Image Grabber и затем кликнуть кнопку GRAB NOW, то в буфере обмена будет список URL-ов всех изображений текущей web-страницы. Можно вставить его в любой текстовый редактор.

Для начала, возможно, неплохо, но практическая ценность такого расширения не велика. Поэтому в следующей части я покажу как выгрузить все эти изображения в виде zip-архива, а также, создать дополнительный интерфейс, для того чтобы выбрать какие картинки добавлять в этот ZIP-архив, а какие нет. Также опишу процесс публикации готового расширения в Chrome Store.

Поэтому подписывайтесь, думаю к концу следующей недели вторая часть будет доступна вместе с полным исходным кодом.

UPD

Вторая часть опубликована и доступна здесь.

Когда Unity загружает проект, диспетчер пакетов Unity считывает манифест проекта, чтобы составить список пакетов, которые необходимо получить и загрузить. Когда пользователь устанавливает или удаляет пакет через окно диспетчера пакетов, диспетчер пакетов сохраняет эти изменения в файле манифеста проекта. Файл манифеста проекта управляет списком пакетов через объект dependencies.

Кроме того, манифест проекта служит файлом конфигурации для диспетчера пакетов, который использует манифест для настройки URL-адреса реестра и регистрации пользовательских реестров.

Вы можете найти файл манифеста проекта с именем manifest.json в папке Packages в корневой папке вашего Единый проект. Как и файл манифеста пакета, файл манифеста проекта использует синтаксис JSON (нотация объектов JavaScript).

Свойства

Все свойства являются необязательными. Однако, если файл манифеста вашего проекта не содержит никаких значений, окно диспетчера пакетов не загружается, а диспетчер пакетов не загружает пакеты.

Совет. В любой момент вы можете исправить любые проблемы с реестром, выбрав Reset packages to defaults в главное меню справки Unity. Однако имейте в виду, что это действие сбрасывает все изменения, внесенные вами в зависимости вашего проекта, поэтому лучше делать это в крайнем случае.

Ключ JSON тип Описание
dependencies
See in Словарь
Object Коллекция пакетов, необходимых для вашего проекта. Сюда входят только прямые зависимости (непрямые зависимости перечислены в манифестах пакетовКаждый пакет имеет манифест, который предоставляет диспетчеру пакетов информацию о пакете.Манифест содержит такую информацию, как имя пакета, его версия, описание для пользователей, зависимости от других пакетов (если есть) и другие сведения. Подробнее
См. в Словарь
). Каждая запись сопоставляет имя пакета с минимальной версией, необходимой для проекта:

{
  "dependencies": {
    "com.my-package": "2.3.1",
    "com.my-other-package": "1.0.1-preview.1",
      etc.
  }
}

Указание номера версии означает, что вы хотите, чтобы диспетчер пакетов загрузил пакет из реестра пакетов (то есть источником пакета является реестр ). Однако, помимо использования версий, вы также можете указать путь к локальной папке или архивному файлу или URL Git.

Примечание. Вам не нужно указывать здесь встроенные пакеты, поскольку диспетчер пакетов находит их внутри Packages и загружает их автоматически. Диспетчер пакетов игнорирует любую запись, если в его собственном манифесте пакета есть встроенный пакет с таким же именем.

enableLockFile Boolean Включает файл блокировки, чтобы гарантировать детерминированное разрешение зависимостей. По умолчанию установлено значение true. Дополнительные сведения см. в разделе Использование файлов блокировки.
registry String Это свойство зарезервировано только для внутреннего использования.

Примечание. Если вы хотите подключиться к серверу реестра пакетов в дополнение к реестру Unity, используйте реестр с областью действия.

resolutionStrategy String Обновляет косвенные зависимости на основе правил семантического управления версиями. По умолчанию установлено значение lowest. Дополнительную информацию см. в разделе Настройка стратегии разрешения проблем ниже..
scopedRegistries Array of Objects Укажите пользовательские реестры в дополнение к реестру по умолчанию. Это позволяет размещать собственные пакеты.

Дополнительные сведения см. в разделе Реестры с ограниченной областью действия.

testables Array of Strings Список имен пакетов, тесты которых вы хотите загрузить в Unity Test FrameworkПакет Test Framework (ранее называвшийся Test Runner) — это инструмент Unity, который тестирует ваш код как в режиме редактирования, так и в режиме воспроизведения, а также на целевом платформах, таких как Standalone, Android или iOS. Подробнее
См. в Словарь
. Дополнительные сведения см. в разделе Добавление тестов в пакет.

Примечание. Вам не нужно указывать здесь встроенные пакеты, поскольку Unity Test Framework предполагает, что они тестируются по умолчанию.

useSatSolver Boolean Включает алгоритм разрешения зависимостей на основе SAT Solver. По умолчанию установлено значение true.

Если вы установите для этого свойства значение false, диспетчер пакетов будет использовать устаревший стратегия, основанная на глубине.

Пример

{
"registry": "https://my.registry.com",
"scopedRegistries": [{
"name": "My internal registry",
"url": "https://my.internal.registry.com",
"scopes": [
"com.company"
]
}],
"dependencies": {
"com.unity.package-1": "1.0.0",
"com.unity.package-2": "2.0.0",
"com.company.my-package": "3.0.0",
"com.unity.my-local-package": "file:/my_package_folder",
"com.unity.my-local-tarball": "file:/my_package_tarball.tgz",
"com.unity.my-git-package": "https://my.repository/my-package.git#v1.2.3"
},
"enableLockFile": true,
"resolutionStrategy": "highestMinor",
"testables": [ "com.unity.package-1", "com.unity.package-2" ]
}

Настройка стратегии разрешения

Хотя вы можете явно добавлять версии пакетов в манифест проекта, чтобы переопределить разрешение зависимостей пакетов Unity и обновить косвенные зависимости, это не очень хорошая стратегия по двум причинам:

  • На владельца проекта возлагается больше ответственности за поддержку версий зависимостей.
  • Со временем у вас могут появиться зависимости, которые не требуются для проекта.

Лучше настроить, как диспетчер пакетов выбирает косвенные зависимости на основе правил семантического управления версиями, задав свойство resolutionStrategy:

Значение: Описание:
lowest Не обновляйте косвенные зависимости. Вместо этого он использует именно запрошенную версию. Это режим «по умолчанию».
highestPatch Обновите до самой высокой версии с теми же основными и второстепенными компонентами. Например, с запрошенной версией 1.2.3 эта стратегия выбирает самую старшую версию в диапазоне [1.2.3, 1.3.0) (то есть >= 1.2.3 и < 1.3.0).
highestMinor Обновите до самой высокой версии с тем же основным компонентом. Например, с запрошенной версией 1.2.3 эта стратегия выбирает самую старшую версию в диапазоне [1.2.3, 2.0.0) (то есть >= 1.2.3 и < 2.0.0).

Примечание. Версия 1.0.0 является первой стабильной, готовой к работе версией. Более низкие версии 0.X.Y указывают на то, что их API еще не является стабильным, и последующие второстепенные версии могут вносить критические изменения. Эта часть спецификации SemVer позволяет выпускать ранние версии пакета, не препятствуя быстрой разработке. Из-за этого, когда целевой версией является 0.XY, highestMinor ведет себя как highestPatch, чтобы гарантировать выбор предыдущей версии. -совместимая версия. Например, при запрошенной версии 0.1.3 эта стратегия выбирает самую старшую версию в диапазоне [0.1.3,0.2.0)< /код>.


highest Обновите до самой высокой версии. Например, с запрошенной версией 1.2.3 эта стратегия выбирает самую старшую версию в диапазоне [1.2.3,) (то есть >= 1.2.3 без верхней границы)

Примечание. Эти диапазоны никогда не позволяют зависимости перейти от стабильной версии к предварительный просмотр пакета.

Понравилась статья? Поделить с друзьями:
  • Joom магазин как найти
  • Как составить план главы книги
  • Как найти космическую козу
  • Как найти три джи
  • Как найти дело умершего родственника