diff --git a/en/application-dev/dfx/errormanager-guidelines.md b/en/application-dev/dfx/errormanager-guidelines.md index 4679cfcfc78893590fe73eab770e49fc68a1a828..8509fff09e51cd31665e80fab6dce0f2472ab08d 100644 --- a/en/application-dev/dfx/errormanager-guidelines.md +++ b/en/application-dev/dfx/errormanager-guidelines.md @@ -23,7 +23,8 @@ When an asynchronous callback is used, the return value can be processed directl | API | Description | | ------------------------------ | ------------------------------------------------------------ | -| onUnhandledException(errMsg: string): void | Called when an application generates an uncaught exception after being registered.| +| onUnhandledException(errMsg: string): void | Called when an uncaught exception is reported after the application is registered.| +| onException?(errObject: Error): void | Called when an application exception is reported to the JavaScript layer after the application is registered.| ### Result Codes for Unregistering an Observer @@ -43,6 +44,13 @@ let registerId = -1; let callback = { onUnhandledException: function (errMsg) { console.log(errMsg); + }, + onException: function (errorObj) { + console.log('onException, name: ', errorObj.name); + console.log('onException, message: ', errorObj.message); + if (typeof(errorObj.stack) === 'string') { + console.log('onException, stack: ', errorObj.stack); + } } } diff --git a/en/application-dev/web/Readme-EN.md b/en/application-dev/web/Readme-EN.md new file mode 100644 index 0000000000000000000000000000000000000000..e003a42ecdbe48166e7603ea1e879739010e8228 --- /dev/null +++ b/en/application-dev/web/Readme-EN.md @@ -0,0 +1,17 @@ +# Web + +- [Web Component Overview](web-component-overview.md) +- [Loading Pages by Using the Web Component](web-page-loading-with-web-components.md) +- Setting Basic Attributes and Events + - [Setting the Dark Mode](web-set-dark-mode.md) + - [Uploading Files](web-file-upload.md) + - [Opening Pages in a New Window](web-open-in-new-window.md) + - [Managing Location Permissions](web-geolocation-permission.md) +- Using Frontend Page JavaScript Code on the Application + - [Invoking Frontend Page Functions on the Application](web-in-app-frontend-page-function-invoking.md) + - [Invoking Application Functions on the Frontend Page](web-in-page-app-function-invoking.md) + - [Establishing a Data Channel Between the Application and Frontend Page](web-app-page-data-channel.md) +- [Managing Page Redirection and Browsing History Navigation](web-redirection-and-browsing-history-mgmt.md) +- [Managing Cookies and Data Storage](web-cookie-and-data-storage-mgmt.md) +- [Customizing Page Request Responses](web-resource-interception-request-mgmt.md) +- [Debugging Frontend Pages by Using DevTools](web-debugging-with-devtools.md) diff --git a/en/application-dev/web/figures/debug-effect.png b/en/application-dev/web/figures/debug-effect.png new file mode 100644 index 0000000000000000000000000000000000000000..32c46cadbb99a6623532f50d14fa0750854c9a5d Binary files /dev/null and b/en/application-dev/web/figures/debug-effect.png differ diff --git a/en/application-dev/web/figures/resource-path.png b/en/application-dev/web/figures/resource-path.png new file mode 100644 index 0000000000000000000000000000000000000000..602c750894581e13296cb7cb77e9714f143983f9 Binary files /dev/null and b/en/application-dev/web/figures/resource-path.png differ diff --git a/en/application-dev/web/web-app-page-data-channel.md b/en/application-dev/web/web-app-page-data-channel.md new file mode 100644 index 0000000000000000000000000000000000000000..f26c635fdf294c9237342381355538da950ad281 --- /dev/null +++ b/en/application-dev/web/web-app-page-data-channel.md @@ -0,0 +1,143 @@ +# Establishing a Data Channel Between the Application and the Frontend Page + + +The [createWebMessagePorts()](../reference/apis/js-apis-webview.md#createwebmessageports) API allows you to create message ports to implement communication between the application and frontend page. + + +In the following example, **createWebMessagePorts** is used to create message ports on the application and [postMessage()](../reference/apis/js-apis-webview.md#postmessage) is used to forward one of the message ports to the frontend page so that the application and frontend page can exchange messages with each other over the port. + + +- Application code: + + ```ts + // xxx.ets + import web_webview from '@ohos.web.webview'; + + @Entry + @Component + struct WebComponent { + controller: web_webview.WebviewController = new web_webview.WebviewController(); + ports: web_webview.WebMessagePort[]; + @State sendFromEts: string = 'Send this message from ets to HTML'; + @State receivedFromHtml: string = 'Display received message send from HTML'; + + build() { + Column() { + // Display the content received from the HTML side. + Text(this.receivedFromHtml) + // Send the content in the text box to the HTML side. + TextInput({placeholder: 'Send this message from ets to HTML'}) + .onChange((value: string) => { + this.sendFromEts = value; + }) + + Button('postMessage') + .onClick(() => { + try { + // 1. Create two message ports. + this.ports = this.controller.createWebMessagePorts(); + // 2. Register a callback for the message port (for example, port 1) on the application. + this.ports[1].onMessageEvent((result: web_webview.WebMessage) => { + let msg = 'Got msg from HTML:'; + if (typeof(result) === 'string') { + console.info(`received string message from html5, string is: ${result}`); + msg = msg + result; + } else if (typeof(result) === 'object') { + if (result instanceof ArrayBuffer) { + console.info(`received arraybuffer from html5, length is: ${result.byteLength}`); + msg = msg + 'lenght is ' + result.byteLength; + } else { + console.info('not support'); + } + } else { + console.info('not support'); + } + this.receivedFromHtml = msg; + }) + // 3. Send the other message port (for example, port 0) to the HTML side, which then saves the message port. + this.controller.postMessage('__init_port__', [this.ports[0]], '*'); + } catch (error) { + console.error(`ErrorCode: ${error.code}, Message: ${error.message}`); + } + }) + + // 4. Use the message port on the application to send messages to the message port that has been sent to the HTML side. + Button('SendDataToHTML') + .onClick(() => { + try { + if (this.ports && this.ports[1]) { + this.ports[1].postMessageEvent(this.sendFromEts); + } else { + console.error(`ports is null, Please initialize first`); + } + } catch (error) { + console.error(`ErrorCode: ${error.code}, Message: ${error.message}`); + } + }) + Web({ src: $rawfile('xxx.html'), controller: this.controller }) + } + } + } + ``` + +- Frontend page code: + + ```html + + + +
+ +display received message send from ets
+ + + ``` diff --git a/en/application-dev/web/web-component-overview.md b/en/application-dev/web/web-component-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..187661ee6c6f9f98411d89c67052615e04d14bca --- /dev/null +++ b/en/application-dev/web/web-component-overview.md @@ -0,0 +1,14 @@ +# Web Component Overview + + +In addition to displaying web page content on applications, the **Web** component provides you with some other helpful functions, including: + + +- **Page loading**: provides a full set of basic frontend page loading capabilities, which allow you to load network pages, local pages, and HTML text data. + +- **Page interaction**: supports a wide range of page interaction modes, which allow you to set the dark mode for frontend pages, load pages in a new window, manage location permissions and cookies, and use frontend page JavaScript code on the application. + +- **Page debugging**: uses DevTools to debug frontend pages. + + +To help you better understand the features of the **Web** component, the following sections will exemplify use of the **Web** component in common application scenarios. diff --git a/en/application-dev/web/web-cookie-and-data-storage-mgmt.md b/en/application-dev/web/web-cookie-and-data-storage-mgmt.md new file mode 100644 index 0000000000000000000000000000000000000000..e5d402724d420bae4157fe18f56e9de6e00adac6 --- /dev/null +++ b/en/application-dev/web/web-cookie-and-data-storage-mgmt.md @@ -0,0 +1,131 @@ +# Managing Cookies and Data Storage + + +## Cookie Management + +A cookie is a segment of data sent from the server to the client to uniquely identify a user during network access. The client may hold the data and provide it to the server at later interactions so that the server can quickly identify the client identity and status. + +The **Web** component provides the **WebCookieManager** class for you to manage cookie information, which is stored in the **/proc/{pid}/root/data/storage/el2/base/cache/web/Cookiesd** file in the application sandbox path. + +The following uses [setCookie()](../reference/apis/js-apis-webview.md#setcookie) as an example to describe how to set a cookie's value to **test** for **www.example.com**. For details about functions and usage of other APIs, see [WebCookieManager()](../reference/apis/js-apis-webview.md#webcookiemanager). + + +```ts +// xxx.ets +import web_webview from '@ohos.web.webview'; + +@Entry +@Component +struct WebComponent { + controller: web_webview.WebviewController = new web_webview.WebviewController(); + + build() { + Column() { + Button('setCookie') + .onClick(() => { + try { + web_webview.WebCookieManager.setCookie('https://www.example.com', 'value=test'); + } catch (error) { + console.error(`ErrorCode: ${error.code}, Message: ${error.message}`); + } + }) + Web({ src: 'www.example.com', controller: this.controller }) + } + } +} +``` + + +## Cache and Storage Management + +Network resource requests are relatively time-consuming during website access. You can use store resources locally by means of cache and Dom Storage to fasten the access to the same website. + + +### Cache + +Use [cacheMode()](../reference/arkui-ts/ts-basic-components-web.md#cachemode) to configure the cache mode for page resources. Four cache modes are supported: + +- **Default**: Page resources in a cache that has not expired are preferentially used. If the cache does not exist, page resources are obtained from the network. + +- **None**: Page resources are loaded from the cache. If the cache does not exist, page resources are obtained from the network. + +- **Online**: Page resources are not loaded from the cache. All resources are obtained from the network. + +- **Only**: Page resources are only loaded from the cache. + + +In the following example, the cache mode is set to **None**. + + + +```ts +// xxx.ets +import web_webview from '@ohos.web.webview'; + +@Entry +@Component +struct WebComponent { + @State mode: CacheMode = CacheMode.None; + controller: web_webview.WebviewController = new web_webview.WebviewController(); + build() { + Column() { + Web({ src: 'www.example.com', controller: this.controller }) + .cacheMode(this.mode) + } + } +} +``` + + + To obtain up-to-date resources, you can use [removeCache()](../reference/apis/js-apis-webview.md#removecache) to clear cached resources. The sample code is as follows: + +```ts +// xxx.ets +import web_webview from '@ohos.web.webview'; + +@Entry +@Component +struct WebComponent { + @State mode: CacheMode = CacheMode.None; + controller: web_webview.WebviewController = new web_webview.WebviewController(); + build() { + Column() { + Button('removeCache') + .onClick(() => { + try { + // If this parameter is set to true, the cache in both the ROM and RAM is cleared. If this parameter is set to false, only the cache in the RAM is cleared. + this.controller.removeCache(true); + } catch (error) { + console.error(`ErrorCode: ${error.code}, Message: ${error.message}`); + } + }) + Web({ src: 'www.example.com', controller: this.controller }) + .cacheMode(this.mode) + } + } +} +``` + + +### Dom Storage + +Dom Storage falls into Session Storage and Local Storage. Wherein, Session Storage applies to the temporary data, and its data storage and release follow the session lifecycle; Local Storage applies to the persistent data, which is flushed to the application directory. In both storage modes, data is stored in a form of key-value pair, and is usually used when a page that needs to be stored on the client is accessed. You can use [domStorageAccess()](../reference/arkui-ts/ts-basic-components-web.md#domstorageaccess) to enable Dom Storage. The following is the sample code: + + + +```ts +// xxx.ets +import web_webview from '@ohos.web.webview'; + +@Entry +@Component +struct WebComponent { + controller: web_webview.WebviewController = new web_webview.WebviewController(); + build() { + Column() { + Web({ src: 'www.example.com', controller: this.controller }) + .domStorageAccess(true) + } + } +} +``` diff --git a/en/application-dev/web/web-debugging-with-devtools.md b/en/application-dev/web/web-debugging-with-devtools.md new file mode 100644 index 0000000000000000000000000000000000000000..3a38a48ab12cfd740bba0d5b99cf8140d4224e4b --- /dev/null +++ b/en/application-dev/web/web-debugging-with-devtools.md @@ -0,0 +1,45 @@ +# Debugging Frontend Pages by Using DevTools + + +The **Web** component supports debugging of web frontend pages by using DevTools, a web frontend development and debugging tool that allows you to debug an application's frontend pages on a PC. Before you do this, use [setWebDebuggingAccess()](../reference/apis/js-apis-webview.md#setwebdebuggingaccess) to enable frontend page debugging for the **Web** component. + + +To use DevTools for frontend page debugging, perform the following steps: + + +1. Enable web frontend page debugging in the application code. + + ```ts + // xxx.ets + import web_webview from '@ohos.web.webview'; + + @Entry + @Component + struct WebComponent { + controller: web_webview.WebviewController = new web_webview.WebviewController(); + aboutToAppear() { + // Enable web frontend page debugging. + web_webview.WebviewController.setWebDebuggingAccess(true); + } + build() { + Column() { + Web({ src: 'www.example.com', controller: this.controller }) + } + } + } + ``` + +2. Connect your device to a PC, and configure port mapping on the PC as follows: + + ``` + // Configure port mapping. + hdc fport tcp:9222 tcp:9222 + // View port mapping. + hdc fport ls + ``` + +3. Enter **chrome://inspect/\#devices** in the address box of the Chrome browser on the PC. Once the device is identified, you can get started with page debugging. The debugging effect is as follows: + + **Figure 1** Page debugging effect + +  diff --git a/en/application-dev/web/web-file-upload.md b/en/application-dev/web/web-file-upload.md new file mode 100644 index 0000000000000000000000000000000000000000..e06f0345b2dfdbd5fd59548ed31c19bacd89f5f0 --- /dev/null +++ b/en/application-dev/web/web-file-upload.md @@ -0,0 +1,52 @@ +# Uploading Files + + +The **Web** component supports file uploading on a frontend page. You can use [onShowFileSelector()](../reference/arkui-ts/ts-basic-components-web.md#onshowfileselector9) to process file upload requests sent from a frontend page. + + +In the following example, when a user clicks the **Upload** button on the frontend page, the application receives a file upload request through [onShowFileSelector()](../reference/arkui-ts/ts-basic-components-web.md#onshowfileselector9), which carries the path of the local file to be uploaded. + + +- Application code: + + ```ts + // xxx.ets + import web_webview from '@ohos.web.webview'; + @Entry + @Component + struct WebComponent { + controller: WebController = new WebController() + build() { + Column() { + // Load the local.html page. + Web({ src: $rawfile('local.html'), controller: this.controller }) + .onShowFileSelector((event) => { + // Set the path of the local file to be uploaded. + let fileList: ArrayLocation information
+ + + + + ``` + + +- Application code: + + ```ts + // xxx.ets + import web_webview from '@ohos.web.webview'; + + @Entry + @Component + struct WebComponent { + controller: web_webview.WebviewController = new web_webview.WebviewController(); + build() { + Column() { + Web({ src:$rawfile('getLocation.html'), controller:this.controller }) + .geolocationAccess(true) + .onGeolocationShow((event) => { // Notification of the location permission request + AlertDialog.show({ + title: 'Location Permission', + message:'Grant access to the device location?', + primaryButton: { + value: 'cancel', + action: () => { + event.geolocation.invoke(event.origin, false, false); // Deny access to the device location. + } + }, + secondaryButton: { + value: 'ok', + action: () => { + event.geolocation.invoke(event.origin, true, false); // Allow access to the device location. + } + }, + cancel: () => { + event.geolocation.invoke(event.origin, false, false); // Deny access to the device location. + } + }) + }) + } + } + } + ``` diff --git a/en/application-dev/web/web-in-app-frontend-page-function-invoking.md b/en/application-dev/web/web-in-app-frontend-page-function-invoking.md new file mode 100644 index 0000000000000000000000000000000000000000..66e9ef25c171a346586d3294c3a9f3919a0726ab --- /dev/null +++ b/en/application-dev/web/web-in-app-frontend-page-function-invoking.md @@ -0,0 +1,48 @@ +# Invoking Frontend Page Functions on the Application + + +You can call [runJavaScript()](../reference/apis/js-apis-webview.md#runjavascript) on an application to call JavaScript functions of frontend pages. + + +In the following example, when a user clicks the **runJavaScript** button on the application, the **htmlTest()** API of the frontend page will be triggered. + + +- Frontend page code: + + ```html + + + + + + + + ``` + + +- Application code: + + ```ts + // xxx.ets + import web_webview from '@ohos.web.webview'; + + @Entry + @Component + struct WebComponent { + webviewController: web_webview.WebviewController = new web_webview.WebviewController(); + + build() { + Column() { + Web({ src: $rawfile('index.html'), controller: this.webviewController}) + Button('runJavaScript') + .onClick(() => { + this.webviewController.runJavaScript('htmlTest()'); + }) + } + } + } + ``` diff --git a/en/application-dev/web/web-in-page-app-function-invoking.md b/en/application-dev/web/web-in-page-app-function-invoking.md new file mode 100644 index 0000000000000000000000000000000000000000..6ef1ed5fa8f5e5fad67e96d20189209ca51016e1 --- /dev/null +++ b/en/application-dev/web/web-in-page-app-function-invoking.md @@ -0,0 +1,113 @@ +# Invoking Application Functions on the Frontend Page + + +You can use the **Web** component to register application code with frontend pages. After the registration is done, frontend pages can use the registered object names to call application functions. + + +Two methods are available for registering the application code:Hello World
+ + + ``` + + +## Loading HTML Rich Text Data + +The **Web** component provides the [loadData()](../reference/apis/js-apis-webview.md#loaddata) API for you to load HTML rich text data. This API is applicable if you want to display some page sections instead of the entire page. + + + +```ts +// xxx.ets +import web_webview from '@ohos.web.webview'; + +@Entry +@Component +struct WebComponent { + controller: web_webview.WebviewController = new web_webview.WebviewController(); + + build() { + Column() { + Button('loadData') + .onClick(() => { + try { + // Upon button clicking, call loadData to load HTML rich text data. + this.controller.loadData( + 'Source:source', + 'text/html', + 'UTF-8' + ); + } catch (error) { + console.error(`ErrorCode: ${error.code}, Message: ${error.message}`); + } + }) + // When creating a Web component, set the default network page to be loaded to www.example.com. + Web({ src: 'www.example.com', controller: this.controller }) + } + } +} +``` diff --git a/en/application-dev/web/web-redirection-and-browsing-history-mgmt.md b/en/application-dev/web/web-redirection-and-browsing-history-mgmt.md new file mode 100644 index 0000000000000000000000000000000000000000..6edb18eed157d0525bb19c815fae26f51a66d6fa --- /dev/null +++ b/en/application-dev/web/web-redirection-and-browsing-history-mgmt.md @@ -0,0 +1,157 @@ +# Managing Page Redirection and Browsing History Navigation + + +## History Navigation + +When a user clicks a web page link on the frontend page, the **Web** component automatically opens and loads the target website by default. When the current page is assigned a new loading link, the address of the accessed web page is automatically recorded. You can call [forward()](../reference/apis/js-apis-webview.md#forward) or [backward()](../reference/apis/js-apis-webview.md#backward) to browse the previous or next history record. + + In the following example, when a user clicks the button, **backward()** is called to go back to the previous page. + +```ts +// xxx.ets +import web_webview from '@ohos.web.webview'; + +@Entry +@Component +struct WebComponent { + webviewController: web_webview.WebviewController = new web_webview.WebviewController(); + build() { + Column() { + Button('loadData') + .onClick(() => { + if (this.webviewController.accessBackward()) { + this.webviewController.backward(); + return true; + } + }) + Web({ src: 'https://www.example.com/cn/', controller: this.webviewController}) + } + } +} +``` + + +If a previous record exists, [accessBackward()](../reference/apis/js-apis-webview.md#accessbackward) will return **true**. Similarly, you can call [accessForward()](../reference/apis/js-apis-webview.md#accessforward) to check whether a next record exists. If you skip the check, [forward()](../reference/apis/js-apis-webview.md#forward) and [backward()](../reference/apis/js-apis-webview.md#backward) will not trigger any action if the user has navigated to the end of history records. + + +## Page Redirection + +The **Web** component provides the [onUrlLoadIntercept()](../reference/arkui-ts/ts-basic-components-web.md#onurlloadintercept) API to redirect you from one page to another. + +In the following example, the frontend page **route.html** is loaded on to the application home page **Index.ets**, and the user is redirected to the application page **ProfilePage.ets** when clicking the link on the **route.html** page. + +- Code of the **index.ets** page: + + ```ts + // index.ets + import web_webview from '@ohos.web.webview'; + import router from '@ohos.router'; + @Entry + @Component + struct WebComponent { + webviewController: web_webview.WebviewController = new web_webview.WebviewController(); + + build() { + Column() { + Web({ src: $rawfile('route.html'), controller: this.webviewController }) + .onUrlLoadIntercept((event) => { + let url: string = event.data as string; + if (url.indexOf('native://') === 0) { + // Redirect to another page. + router.pushUrl({ url:url.substring(9) }) + return true; + } + return false; + }) + } + } + } + ``` + +- Code of the **route.html** page: + + ```html + + + + +