postMessage is primarily for communicating between different content pages. It is essentially a structured event with a convenient wrapper for creating and sending it. It has built in support to address cross-origin security concerns although some responsibility for security still rests with the callers. Although it is obviously intended and designed for communication between separate documents (ie. pages) it is based on a window, hence communication is only between different pages in a particular window. Caution if you’re breaking the default settings to run multiple content processes for tabs in the same window.
Almost by coincidence, communication between different web pages can be used by extensions to submit and receive the same messages. This is handy, but less useful than you might expect. It doesn’t perform cross-process messaging. You can postMessage from the chrome process to a content process, but only by accessing the content window which is a CPOW. Not good! You should use a frame script to call postMessage from an extension, unless you force the relevant page to stay in the parent process.
You have always been able to use custom events to communicate between different pages within the same window, and even with extension code (using a special flag), but there was no security mechanism built into this, so it could be risky depending on what action was taken or data transferred. postMessage automatically includes origin information which you can check to be sure who you are communicating with and to restrict who gets which messages. However there are security glitches when communicating to and from chrome:// urls, and I don’t think it works at all with file:// urls. A postMessage event can be raised by any content, so reacting to it without checking the origin is a security risk, but with chrome messages you can’t currently check the origin. The origin from a chrome event is null, although it is possibly for an extension to spoof itself as any origin it wants using a sandbox. Similarly, postMessage to an addon (chrome:// url) with a targetOrigin specified doesn’t work and you have to specify “*” which is a massive security hole. The current recommendation is not to do it.
One more possible confusion. postMessage is an HTML5 API for window objects., but there is another postMessage which is an SDK API. They look the same, but aren’t. It has been suggested that the SDK postMessage be deprecated in favour of the port API.