Как сделать pwa

Usage

To store user data for your extension, you can use either :

        chrome.storage.sync.set({key: value}, function() {
          console.log('Value is set to ' + value);
        });
      
        chrome.storage.sync.get(, function(result) {
          console.log('Value currently is ' + result.key);
        });
      

or :

        chrome.storage.local.set({key: value}, function() {
          console.log('Value is set to ' + value);
        });
      
        chrome.storage.local.get(, function(result) {
          console.log('Value currently is ' + result.key);
        });
      

When using , the stored data will automatically be synced to any Chrome browser that the user is logged into, provided the user has sync enabled.

When Chrome is offline, Chrome stores the data locally. The next time the browser is online, Chrome syncs the data. Even if a user disables syncing, will still work. In this case, it will behave identically to .

Confidential user information should not be stored! The storage area isn’t encrypted.

The storage is read-only.

Activate the extension on all pages

Use a browser_action when an extension’s features are functional in most situations.

Register browser action

The field is registered in the manifest.

  {
    "name": "My Awesome browser_action Extension",
    ...
    "browser_action": {
      ...
    }
    ...
  }

Declaring keeps the icon colorized, indicating the extension is available to users.

Add a badge

Badges display a colored banner with up to four characters on top of the browser icon. They can only be used by extensions that declare in their manifest.

Use badges to indicate the state of the extension. The sample displays a badge with “ON” to show the user they successfully set an alarm and displays nothing when the extension is idle.

  chrome.browserAction.setBadgeText({text: 'ON'});
  chrome.browserAction.setBadgeBackgroundColor({color: '#4688F1'});

Building the Manifest

The manifest itself is a very familiar looking JSON object:


{  "name": "Super Racer 2000",  "short_name": "Racer2K",  "icons": [{        "src": "icon/lowres.png",        "sizes": "64x64",        "type": "image/webp"      }, {        "src": "icon/hd_small.png",        "sizes": "64x64"      }, {        "src": "icon/hd_hi.png",        "sizes": "128x128",        "density": 2      }],  "scope": "/racer/",  "start_url": "/racer/start.html",  "display": "fullscreen",  "orientation": "landscape"}

Most of these values are straight forward:

  • name: Name to show up in app listing or with icon
  • short Name: when present used instead of name along with app listings
  • start_url: when you click the tile or image, this is the URL that is launched (can be relative or full url)
  • display: determine how the app should be presented to the user. Options are fullscreen, minimul-ui, standalone, or browser (opens in browser)
  • orientation: default the app to a particular orientation as defined in the . Options are: “any”, “natural”, “landscape”, “portrait”, “portrait-primary”, “portrait-secondary”, “landscape-primary” and “landscape-secondary”

The other two values are a bit more complex, so you may need to break them down a bit more:

Icons is an array of objects that hold the characteristics for images used by the app presentation. Each object can have a few different values:

  • src: this points to the location of the asset, the manifest will point to the path in the src, whether it contain a file extension or not. src can also be used to determine file type. Again, this path can be either relative to the url from which the manifest was fetched or a full URL
  • type: determines the type of the icon file. If file extension is not present in the src, type will be determined by type (still trying to see the value of this one
  • sizes: this declares the image size. As each platform can and does require its own unique file sizes, this allows the user agent (browser) to determine which images it can use, and which ones it ignores
  • density: this is the device pixel density for which the icon is intended. If omitted, the user agent assumes 1.0

The final vale us a newer one to the spec, which is that of “scope” or navigation scope. The scope does two important things to maintain the “app experience” we are looking for as developers.

  1. Navigate outside the app: if you navigate to a URL (like click on an anchor) that is outside the scope of the app, then it will open that page in the standard browser (whatever your default browser is, even if it’s a different one).
  2. Navigate into the app: this is what we call “deep linking” when it’s to a native app. But if you navigate to a URL within the scope of the manifest , that URL will be opened inside the installable app context. This means a web page, or even native app can open up your fancy web app.

Create First API Request

Now that the extension has proper permissions, credentials, and can authorize a Google user, it can request data through the People API. Update the code in to match below.

  window.onload = function() {
    document.querySelector('button').addEventListener('click', function() {
      chrome.identity.getAuthToken({interactive: true}, function(token) {
        let init = {
          method: 'GET',
          async: true,
          headers: {
            Authorization: 'Bearer ' + token,
            'Content-Type': 'application/json'
          },
          'contentType': 'json'
        };
        fetch(
            'https://people.googleapis.com/v1/contactGroups/all?maxMembers=20&key=<API_Key_Here>',
            init)
            .then((response) => response.json())
            .then(function(data) {
              console.log(data)
            });
      });
    });
  };

Replace with the API key generated from the Google API console. The extension should log a JSON object that includes an array of s under the field.

New answers tagged manifest.json

The texts to search and highlight are not defined in the manifest.json, that is designed only for the metadata and that is managed by iiif presentation api. The search is managed via the iiif search api, that is another endpoint that you indicate as a service inside the manifest.json. In this second endpoint, you can add a process to convert results to the …

answered 2 days ago Daniel-KM 11211 gold badge11 silver badge99 bronze badges

As I added password protection to a developer-only page of mine, I suddenly started getting «manifest line 1 column 1 syntax error» (manifest.json) errors. I am also using AWS Amplify as well as Create React App to build my app. I tried all of the solutions above, but nothing helped. The one thing that did help was adding one property to the link …

answered Aug 18 at 14:58 Eldin Kajdic 3622 bronze badges

1

Chrome security prevents inline JS, which create-react-app generates. Try this In your React App, Please create a .env or add this to existing one INLINE_RUNTIME_CHUNK=false And then build your application (eg. yarn run build) Using this, no scripts, independent of size, are inlined. Check this pull request for more details https://github.com/facebook/create-…

answered Aug 14 at 5:54 Vipulw 86599 bronze badges

When you are working in Snack.expo.io, if you get this error, use the code: import Constants from ‘expo-constants’;

This worked for me.

answered Aug 5 at 16:16 Raj 4144 bronze badges

as @wOxxOm commented on my question, in my manifest.json content_scripts section I leave space before and after «js» when I remove those spaces it works.

answered Aug 1 at 17:22 Suraj Biswas 111 bronze badge

I got my solution. MY service-worker.js file was not correct. Now I paste below code in service-worker.js and it wored. self.addEventListener(‘fetch’, function(event) {});

answered Aug 1 at 11:45 vinod 2744 bronze badges

In addition to changing your start_url to «start_url»: «/»

or for sub-directory (see Keith’s answer for details) «start_url»: «./» «scope»: «.»

For the people testing the start_url changes in the manifest on Chrome Browser in Android, the changes may not reflect right away for the users of your …

answered Jul 30 at 1:36 95faf8e76605e973 4,29333 gold badges99 silver badges2424 bronze badges

1

I have had the navbar on a PWA remain, even though I tried everything, so I thought I would share everything I did, what worked, and how I solved it finally, so you won’t have to search for solutions online for hours like I had to. Extending on @alvaropaco’s answer, in the .zip file you get from PWABuilder, you must place the assetlink.json file at https://…

answered Jul 24 at 18:04 MarsNebulaSoup 1,08711 gold badge66 silver badges2222 bronze badges

You can record microphone audio by using MediaDevices.getUserMedia() or navigator.webkitGetUserMedia(). But I think you need to use this method inside the content script. Example let recorderConfig = { audio: { sampleRate: 48000, channelCount: 2, volume: 1.0 }, video: false,

} navigator….

answered Jul 24 at 4:48 Noob dev 8144 bronze badges

Top 50 recent answers are included

Examples

The following example checks for CSS code saved by a user on a form, and if found, stores it.

      function saveChanges() {
        // Get a value saved in a form.
        var theValue = textarea.value;
        // Check that there's some code there.
        if (!theValue) {
          message('Error: No value specified');
          return;
        }
        // Save it using the Chrome extension storage API.
        chrome.storage.sync.set({'value': theValue}, function() {
          // Notify that we saved.
          message('Settings saved');
        });
      }
      

If you’re interested in tracking changes made to a data object, you can add a listener to its event. Whenever anything changes in storage, that event fires. Here’s sample code to listen for saved changes:

When You Need App Behavior: Deciding Between Packaged Apps and Hosted Apps

If you want a full-page UI and an icon in the New Tab page, you should opt for an app; that is, your manifest will include a “launch” parameter. It will be a packaged app if the parameter points to a local URI («launch_path») and a hosted app if the URI is online («web_url»). Incidentally, “pure” extensions achieved a similar effect in the past by including a hyperlink to a packaged HTML page, which would then be shown as a full page. We expect many developers will migrate this kind of extension to a packaged app in the future.

How to decide between packaged and hosted apps? Let’s start with the advantages of packaged apps:

  • As we’ve already noted, packaged apps can provide extension behavior. Your packaged app might emphasise the extension behavior (an «extension with a face»), the app behavior («app with extra») or it might be a balanced blend of the two styles. The flexibility of packaged apps will be appealing to developers seeking to improve the experience of their apps and differentiate from similar products. You can still build a standard web app running on a regular website, but make it an installable web app and you can add extension behavior to enhance the experience for those who install it.
  • Packaged apps can run in the background, even when the user hasn’t launched your app. This is actually just a special case of the previous point, because a powerful extension privilege is the ability to run a background page. It starts when the browser starts and is ever-present. Your app could therefore keep data fresh and show HTML5 notifications (alerts that work even when the user is in another app). Thus, packaged apps support “always on” functionality, while hosted apps are only on when they’re in the user’s active tab.
  • Packaged apps will load immediately, being held on the user’s hard drive.
  • Certain apps, like some games and utilities, will need no network connection at all. These are ideal candidates for packaged apps because the user will be able to run them offline. That said, hosted apps can usually achieve the same effect with the judicious use of Application Caching, a generic HTML5 technology.

For comparison, these are the advantages of hosted apps:

  • Hosted apps are easier from an infrastructure perspective if you are looking to offer your web app as a regular site to all browsers. (Incidentally, we think this is fine as long as you follow basic design principles for installable web apps.) In the case of packaged apps, you’ll probably need to write a script to put your assets inside a CRX file and in some cases, you may need to refactor your code somewhat. Note, however, packaged apps can still perform requests back to your website (or indeed any website, since packaged apps can use the «permissions» parameter to perform cross-domain requests).
  • Hosted apps are especially easier if your existing web app uses server-side scripting to generate your pages and content, or if your app relies on form submissions and full page refreshes. With a packaged app, you’re relying on JavaScript to make any changes to the page.
  • Hosted apps may be a better choice if your app and content are very large. The store imposes a 2GB limit on CRX files, though a packaged app could always download further content via network calls.
  • Hosted apps will require less permissions to be granted by the user. This is the flipside to the benefits of extension behavior that packaged apps enjoy.
  • Hosted apps will update automatically, just by updating your server. However, this is not a significant advantage, because packaged apps support autoupdating, and this is transparent to the user unless you’ve changed the required permissions.

Organize Permissions

Permissions are known strings that refer to a Chrome API or match patterns that grant access to one or more hosts. They are listed in the manifest and specified as required permissions or .

  {
    "name": "Permissions Extension",
    ...
    // required permissions
    "permissions": ,
    // optional permissions
    "optional_permissions": [
      "topSites",
      "http://www.developer.chrome.com/*"
    ],
        ...
    "manifest_version": 2
  }

Limit required permissions to only what is needed for the extension’s core functionality. An extension should not request more permissions than it currently needs; do not future proof by requesting permissions that may be needed with updates.

Permissions needed for optional features should be registered as . This allows users to decide how much access they are willing to provide an extension and which features are desired.

Summary of API changes

Manifest version 2 introduces a few changes to the browser action and page action APIs, and replaces a few old APIs with newer ones.

Changes to browser actions

The browser actions API introduces some naming changes:

  • The and properties have been replaced with their singular counterparts and .
  • Under the old property, there were , , and properties. These have been replaced with:
    • for the browser action badge icon
    • for the text that appears in the tooltip when you hover over the badge
    • for the HTML page that represents the UI for the browser action (and this must now be a string, it cannot be an object)

Changes to page actions

Similar to the changes for browser actions, the page actions API has also changed:

  • The and properties have been replaced with their singular counterparts and .
  • Under the old property, there were , , and properties. These have been replaced with:
    • for the page action badge icon
    • for the text that appears in the tooltip when you hover over the badge
    • for the HTML page that represents the UI for the page action (and this must now be a string, it cannot be an object)

Removed and changed APIs

A few extension APIs have been removed and replaced with new counterparts:

  • The property has been replaced by background.
  • The property has been removed, use .
  • The property has been replaced with .
  • The and the APIs have been replaced by .

Step 2: Create a manifest file

Every app needs a manifest—a JSON-formatted file named that describes the app.

  1. Create a directory called to contain your app’s manifest.

    Note: You can use a different directory name, if you like. The only name that can’t change is .

  2. In this new directory, create a text file named and copy the following code into it, changing the italicized text to reflect your app:

    {
      "name": "Great App Name",
      "description": "Pithy description (132 characters or less, no HTML)",
      "version": "0.0.0.1",
      "manifest_version": 2,
      "icons": {
        "128": "icon_128.png"
      },
      "app": {
        "urls": [
          "http://mysubdomain.example.com/"
        ],
        "launch": {
          "web_url": "http://mysubdomain.example.com/"
        }
      }
    }
    

All new apps must specify manifest version 2 without quotes (see manifest version documentation). The remaining fields are fairly straightforward, except for «urls» and «web_url». In this example, those fields have the same values but mean different things.

«web_url»
Specifies the page that the browser shows when a user launches the app.
«urls»

Specifies the starting URLs of all other web pages that are in the app. In this example, both http://mysubdomain.example.com/page1.html and http://mysubdomain.example.com/subdir/page2.html would be in the app. You don’t need to specify the URLs for included files or for assets such as images. Currently, the domain name must be followed by at least one character («/»).

Note: If your app has only one page, you can omit the «urls» field.

For more information about what the manifest for a hosted app can contain, see Hosted Apps.

Extension origin

Each running extension exists within its own separate security origin. Without requesting additional privileges, the extension can use XMLHttpRequest to get resources within its installation. For example, if an extension contains a JSON configuration file called , in a folder, the extension can retrieve the file’s contents like this:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true);
xhr.send();

If the extension attempts to use a security origin other than itself, say https://www.google.com, the browser disallows it unless the extension has requested the appropriate cross-origin permissions.

Trigger Optional Permissions with Events

The core functionality is overriding the new tab page. One feature is displaying the user’s goal of the day. This feature only requires the storage permission, which does not include a warning.

The extension has an additional feature; displaying the user’s top sites. This feature requires the topSites permission, which has a warning.

Developing features that rely on permissions with warnings as optional and introducing those features organically gives users a risk free introduction to the extension. Additionally, this allows users to further customize their experience with an extension and creates opportunity to explain warnings.

Final Thoughts

Making your web site more of an app experience is fairly simple, and can have quite an impact for users, especially as the Manifest for Web Apps spec moves forward to implementation, and until then, use the fantastic polyfill called ManUp.js written by yours truly.

One final thought: this format needs expand to specifically call out Hosted apps as well. The myriad of formats for stores is what makes the hosted apps difficult to build and maintain. I’ve already moved my tool called the Web App Template to this format, and it works really well for the developers who use it. Let’s move that forward and make it easier for us to submit our cross-browser web apps into the landscape of app markets.


Authored by @BoyofGreen (Jeff Burtoft) , with Love for all things Web

When You Need Extension Behavior: Deciding Between Pure Extensions and Packaged Apps

If you want to extend browser behavior or modify web pages, you have no choice but to use an extension or a packaged app; hosted apps don’t have those privileges. You will then be able to provide any number of extension behaviors. Should you go down this path, the next decision comes down to pure extension versus packaged app. It’s so easy to add a “launch” parameter to your manifest, you might be tempted to take a pure extension and tack on a dedicated UI for it. Think twice. Users don’t want apps superfluously appearing on their New Tab page if they aren’t adding any value. So make your extension a packaged app only if it’s genuinely useful.

Certain extensions will really benefit from an app UI. Imagine a news reader extension that shows users notifications every time a new story is posted. It’s easy to see how this extension could introduce a dedicated UI showing the stream of recent stories—a proper «big page» experience to augment what was previously transient content.

Other extensions, not so much. Extensions often have a very specific purpose, so building a new app UI—even if it is related to the extension’s behavior—is probably not what users are after, and it would be better to build the app UI as a separate app. Imagine a social bookmarking extension providing a «bookmark this» action via a context menu item. You could imagine the extension becoming a general-purpose app for the social bookmarking service, but there’s a good argument that this is distinct functionality that should be encapsulated in a separate app, as many users will only want one or the other, but not both.

Even if your extension needs a UI, it might be enough to use one of the existing extension mechanism UIs, instead of the full-page UI offered by apps. Extensions can manifest themselves in the form of context menu items, custom toolbars, notification dialogs, and buttons on the address bar that reveal extra content when clicked. Also, note that extensions have the concept of options pages, so you don’t need to create an app just to support option setting.

API changes checklist

  • Are you using the property or the API?
    • Replace with the singular property.
    • Replace with .
    • Replace the property with .
    • Replace the property with .
    • Replace the property with (and it now must be a string).
  • Are you using the property or the API?
    • Replace with .
    • Replace with .
    • Replace the property with .
    • Replace the property with .
    • Replace the property with (and it now must be a string).
  • Are you using the property?

    Replace with chrome.extension.

  • Are you using the property?

    Replace with Port.sender.

  • Are you using the or the APIs?

    Replace with chrome.extension.getViews( { «type» : «tab» } ).

  • Does your extension use a background page?
    • Replace the property with a property.
    • Add a or property that contains the code for the page.
    • Add a property and set it to to convert your background page to an event page

Properties

Items in the storage area are synced using Chrome Sync. Properties
QUOTA_BYTES

The maximum total amount (in bytes) of data that can be stored in sync storage, as measured by the JSON stringification of every value plus every key’s length. Updates that would cause this limit to be exceeded fail immediately and set .

QUOTA_BYTES_PER_ITEM

The maximum size (in bytes) of each individual item in sync storage, as measured by the JSON stringification of its value plus its key length. Updates containing items larger than this limit will fail immediately and set .

MAX_ITEMS

The maximum number of items that can be stored in sync storage. Updates that would cause this limit to be exceeded will fail immediately and set .

MAX_WRITE_OPERATIONS_PER_HOUR

The maximum number of , , or operations that can be performed each hour. This is 1 every 2 seconds, a lower ceiling than the short term higher writes-per-minute limit.

Updates that would cause this limit to be exceeded fail immediately and set .

MAX_WRITE_OPERATIONS_PER_MINUTE

Since Chrome 40.

The maximum number of , , or operations that can be performed each minute. This is 2 per second, providing higher throughput than writes-per-hour over a shorter period of time.

Updates that would cause this limit to be exceeded fail immediately and set .

MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE

Deprecated since Chrome 40. The storage.sync API no longer has a sustained write operation quota.

Items in the storage area are local to each machine. Properties QUOTA_BYTES

The maximum amount (in bytes) of data that can be stored in local storage, as measured by the JSON stringification of every value plus every key’s length. This value will be ignored if the extension has the permission. Updates that would cause this limit to be exceeded fail immediately and set .

Items in the storage area are set by the domain administrator, and are read-only for the extension; trying to modify this namespace results in an error.

Block Faces

Now that the extension is returning a list of the user’s contacts, it can make additional requests to retrieve those contact’s profiles and information . The extension will use the to retrieve the photo information of user contacts. Update to include the following code.

  window.onload = function() {
    document.querySelector('button').addEventListener('click', function() {
      chrome.identity.getAuthToken({interactive: true}, function(token) {
        let init = {
          method: 'GET',
          async: true,
          headers: {
            Authorization: 'Bearer ' + token,
            'Content-Type': 'application/json'
          },
          'contentType': 'json'
        };
        fetch(
            'https://people.googleapis.com/v1/contactGroups/all?maxMembers=20&key=<API_Key_Here>',
            init)
            .then((response) => response.json())
            .then(function(data) {
              let photoDiv = document.querySelector('#friendDiv');
              let returnedContacts = data.memberResourceNames;
              for (let i = 0; i < returnedContacts.length; i++) {
                fetch(
                    'https://people.googleapis.com/v1/' + returnedContacts +
                        '?personFields=photos&key=<API_Key_Here>',
                    init)
                    .then((response) => response.json())
                    .then(function(data) {
                      let profileImg = document.createElement('img');
                      profileImg.src = data.photos.url;
                      photoDiv.appendChild(profileImg);
                    });
              };
            });
      });
    });
  };

Reload and return to the extension. Click the FriendBlock button and ta-da! Enjoy contact’s faces in a block.


С этим читают